Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@scalar/oas-utils

Package Overview
Dependencies
Maintainers
8
Versions
99
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@scalar/oas-utils - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

dist/getExampleFromSchema.d.ts

6

CHANGELOG.md
# @scalar/oas-utils
## 0.1.1
### Patch Changes
- 31aae5e: chore: moved shared types and methods into oas-utils
## 0.1.0

@@ -4,0 +10,0 @@

9

dist/index.d.ts
export { fetchSpecFromUrl } from './fetch-spec';
export * from './parse';
export { getExampleFromSchema } from './getExampleFromSchema';
export { getHarRequest } from './getHarRequest';
export { getParametersFromOperation } from './getParametersFromOperation';
export { getRequestBodyFromOperation } from './getRequestBodyFromOperation';
export { getRequestFromOperation } from './getRequestFromOperation';
export { json2xml } from './json2xml';
export { formatJsonOrYamlString, isJsonString, json, parseJsonOrYaml, transformToJson, yaml, } from './parse';
export { prettyPrintJson } from './prettyPrintJson';
export * from './types';
//# sourceMappingURL=index.d.ts.map
import { parse, stringify } from 'yaml';
import { AxiosHeaders } from 'axios';

@@ -92,2 +93,451 @@ const yaml = {

export { fetchSpecFromUrl, formatJsonOrYamlString, isJsonString, json, parseJsonOrYaml, transformToJson, yaml };
const getExampleFromSchema = (schema, options, level = 0) => {
if (level > 5) {
return null;
}
if (options?.mode === "write" && schema.readOnly) {
return void 0;
}
if (options?.mode === "read" && schema.writeOnly) {
return void 0;
}
if (Array.isArray(schema.examples) && schema.examples.length > 0) {
return schema.examples[0];
}
if (schema.example !== void 0) {
return schema.example;
}
if (schema.default !== void 0) {
return schema.default;
}
if (schema.enum !== void 0) {
return schema.enum[0];
}
if (schema.type === "object" || schema.properties !== void 0) {
const response = {};
if (schema.properties !== void 0) {
Object.keys(schema.properties).forEach((name) => {
const property = schema.properties[name];
const propertyXmlTagName = options?.xml ? property.xml?.name : void 0;
response[propertyXmlTagName ?? name] = getExampleFromSchema(
property,
options,
level + 1
);
});
}
if (schema.anyOf !== void 0) {
Object.assign(
response,
getExampleFromSchema(schema.anyOf[0]),
options,
level + 1
);
} else if (schema.oneOf !== void 0) {
Object.assign(
response,
getExampleFromSchema(schema.oneOf[0]),
options,
level + 1
);
} else if (schema.allOf !== void 0) {
Object.assign(
response,
...schema.allOf.map(
(item) => getExampleFromSchema(item, options, level + 1)
)
);
}
if (schema.additionalProperties !== void 0 && schema.additionalProperties !== false) {
const additionalSchema = getExampleFromSchema(
schema.additionalProperties,
options,
level + 1
);
if (additionalSchema && typeof additionalSchema === "object" && !Array.isArray(additionalSchema)) {
return {
...response,
...getExampleFromSchema(
schema.additionalProperties,
options,
level + 1
)
};
}
if (additionalSchema === null) {
return null;
}
return {
...response,
someKey: getExampleFromSchema(
schema.additionalProperties,
options,
level + 1
)
};
}
return response;
}
if (schema.type === "array" || schema.items !== void 0) {
const itemsXmlTagName = schema?.items?.xml?.name;
const wrapItems = !!(options?.xml && schema.xml?.wrapped && itemsXmlTagName);
if (schema.example !== void 0) {
return wrapItems ? { [itemsXmlTagName]: schema.example } : schema.example;
}
if (schema.items) {
const rules = ["anyOf", "oneOf", "allOf"];
for (const rule of rules) {
if (!schema.items[rule]) {
continue;
}
const schemas = ["anyOf", "oneOf"].includes(rule) ? (
// Use the first item only
schema.items[rule].slice(0, 1)
) : (
// Use all items
schema.items[rule]
);
const exampleFromRule = schemas.map(
(item) => getExampleFromSchema(item, options, level + 1)
);
return wrapItems ? [{ [itemsXmlTagName]: exampleFromRule }] : exampleFromRule;
}
}
if (schema.items?.type) {
const exampleFromSchema = getExampleFromSchema(
schema.items,
options,
level + 1
);
return wrapItems ? [{ [itemsXmlTagName]: exampleFromSchema }] : [exampleFromSchema];
}
return [];
}
const exampleValues = {
string: options?.emptyString ?? "",
boolean: true,
integer: schema.min ?? 1,
number: schema.min ?? 1,
array: []
};
if (schema.type !== void 0 && exampleValues[schema.type] !== void 0) {
return exampleValues[schema.type];
}
if (Array.isArray(schema.oneOf) && schema.oneOf.length > 0) {
const firstOneOfItem = schema.oneOf[0];
return getExampleFromSchema(firstOneOfItem, options, level + 1);
}
if (Array.isArray(schema.allOf)) {
let example = null;
schema.allOf.forEach((allOfItem) => {
const newExample = getExampleFromSchema(allOfItem, options, level + 1);
example = typeof newExample === "object" && typeof example === "object" ? {
...example ?? {},
...newExample
} : Array.isArray(newExample) && Array.isArray(example) ? [...example ?? {}, ...newExample] : newExample;
});
return example;
}
console.warn(`[getExampleFromSchema] Unknown property type "${schema.type}".`);
return null;
};
const getHarRequest = (...requests) => {
let mergedRequests = {
httpVersion: "1.1",
method: "GET",
url: "",
path: "",
headers: [],
headersSize: -1,
queryString: [],
cookies: [],
bodySize: -1
};
requests.forEach((request) => {
mergedRequests = {
...mergedRequests,
...request,
headers: [...mergedRequests.headers, ...request.headers ?? []],
queryString: [
...mergedRequests.queryString,
...request.queryString ?? []
],
cookies: [...mergedRequests.cookies, ...request.cookies ?? []]
};
});
const headersObj = mergedRequests.headers.reduce(
(obj, { name, value }) => {
obj[name] = value;
return obj;
},
{}
);
const normalizedAxiosHeaders = AxiosHeaders.from(headersObj).normalize(true);
mergedRequests.headers = Object.entries(normalizedAxiosHeaders).map(
([name, value]) => ({ name, value })
);
const { path, ...result } = mergedRequests;
if (path) {
return {
...result,
url: `${mergedRequests.url}${path}`
};
}
return result;
};
function getParametersFromOperation(operation, where, requiredOnly = true) {
const parameters = [
...operation.pathParameters || [],
...operation.information?.parameters || []
];
const params = parameters.filter((parameter) => parameter.in === where).filter(
(parameter) => requiredOnly && parameter.required || !requiredOnly
).map((parameter) => ({
name: parameter.name,
description: parameter.description ?? null,
value: parameter.example ? parameter.example : parameter.schema ? getExampleFromSchema(parameter.schema, { mode: "write" }) : "",
required: parameter.required ?? false,
enabled: parameter.required ?? false
}));
return params.sort((a, b) => {
if (a.required && !b.required) {
return -1;
} else if (!a.required && b.required) {
return 1;
}
return 0;
});
}
function json2xml(data, tab) {
const toXml = function(value, key, indentation) {
let xml2 = "";
if (value instanceof Array) {
for (let i = 0, n = value.length; i < n; i++) {
xml2 += indentation + toXml(value[i], key, indentation + " ") + "\n";
}
} else if (typeof value == "object") {
let hasChild = false;
xml2 += indentation + "<" + key;
for (const m in value) {
if (m.charAt(0) == "@")
xml2 += " " + m.substr(1) + '="' + value[m].toString() + '"';
else
hasChild = true;
}
xml2 += hasChild ? ">" : "/>";
if (hasChild) {
for (const m in value) {
if (m == "#text")
xml2 += value[m];
else if (m == "#cdata")
xml2 += "<![CDATA[" + value[m] + "]]>";
else if (m.charAt(0) != "@")
xml2 += toXml(value[m], m, indentation + " ");
}
xml2 += (xml2.charAt(xml2.length - 1) == "\n" ? indentation : "") + "</" + key + ">";
}
} else {
xml2 += indentation + "<" + key + ">" + value.toString() + "</" + key + ">";
}
return xml2;
};
let xml = "";
for (const key in data) {
xml += toXml(data[key], key, "");
}
return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
}
const prettyPrintJson = (value) => {
try {
if (typeof value === "string") {
return JSON.stringify(JSON.parse(value), null, 2);
} else {
return JSON.stringify(value, null, 2);
}
} catch {
console.log("[prettyPrintJson] Error parsing JSON", value);
return value;
}
};
function getRequestBodyFromOperation(operation, selectedExampleKey) {
const mimeTypes = [
"application/json",
"application/octet-stream",
"application/x-www-form-urlencoded",
"application/xml",
"multipart/form-data",
"text/plain"
];
const mimeType = mimeTypes.find(
(currentMimeType) => !!operation.information?.requestBody?.content?.[currentMimeType]
);
const examples = operation.information?.requestBody?.content?.["application/json"]?.examples;
const selectedExample = (examples ?? {})?.[selectedExampleKey ?? Object.keys(examples ?? {})[0]];
if (selectedExample) {
return {
postData: {
mimeType: "application/json",
text: prettyPrintJson(selectedExample?.value)
}
};
}
const bodyParameters = getParametersFromOperation(operation, "body", false);
if (bodyParameters.length > 0) {
return {
postData: {
mimeType: "application/json",
text: prettyPrintJson(bodyParameters[0].value)
}
};
}
const formDataParameters = getParametersFromOperation(
operation,
"formData",
false
);
if (formDataParameters.length > 0) {
return {
postData: {
mimeType: "application/x-www-form-urlencoded",
params: formDataParameters.map((parameter) => ({
name: parameter.name,
value: parameter.value
}))
}
};
}
if (!mimeType) {
return {
postData: void 0
};
}
const requestBodyObject = operation.information?.requestBody?.content?.[mimeType];
const headers = [
{
name: "Content-Type",
value: mimeType
}
];
const example = requestBodyObject?.example ? requestBodyObject?.example : void 0;
if (mimeType === "application/json") {
const exampleFromSchema = requestBodyObject?.schema ? getExampleFromSchema(requestBodyObject?.schema, { mode: "write" }) : null;
const body = example ?? exampleFromSchema;
return {
headers,
postData: {
mimeType,
text: typeof body === "string" ? body : JSON.stringify(body, null, 2)
}
};
}
if (mimeType === "application/xml") {
const exampleFromSchema = requestBodyObject?.schema ? getExampleFromSchema(requestBodyObject?.schema, {
xml: true,
mode: "write"
}) : null;
return {
headers,
postData: {
mimeType,
text: example ?? json2xml(exampleFromSchema, " ")
}
};
}
if (mimeType === "application/octet-stream") {
return {
headers,
postData: {
mimeType,
text: "BINARY"
}
};
}
if (mimeType === "text/plain") {
const exampleFromSchema = requestBodyObject?.schema ? getExampleFromSchema(requestBodyObject?.schema, {
xml: true,
mode: "write"
}) : null;
return {
headers,
postData: {
mimeType,
text: example ?? exampleFromSchema ?? ""
}
};
}
if (mimeType === "application/x-www-form-urlencoded") {
return {
headers,
postData: {
mimeType
// TODO: We have an object, but how do we get that kind of array from the object?
// Don’t forget to include nested properties … :|
// params: [
// {
// name: 'foo',
// value: 'bar',
// },
// ],
}
};
}
if (mimeType === "multipart/form-data") {
return {
headers,
postData: {
mimeType
// TODO: We have an object, but how do we get that kind of array from the object?
// Don’t forget to include nested properties … :|
// params: [
// {
// name: 'foo',
// value: 'bar',
// },
// ],
}
};
}
return void 0;
}
const getRequestFromOperation = (operation, options, selectedExampleKey) => {
let path = operation.path;
if (options?.replaceVariables === true) {
const pathVariables = path.match(/{(.*?)}/g);
if (pathVariables) {
pathVariables.forEach((variable) => {
const variableName = variable.replace(/{|}/g, "");
path = path.replace(variable, `__${variableName.toUpperCase()}__`);
});
}
}
const requestBody = getRequestBodyFromOperation(operation, selectedExampleKey);
return {
method: operation.httpVerb.toUpperCase(),
path,
headers: [
...getParametersFromOperation(operation, "header", options?.requiredOnly),
...requestBody?.headers ?? []
],
// TODO: Sorry, something is off here and I don’t get it.
// @ts-ignore
postData: requestBody?.postData,
queryString: getParametersFromOperation(
operation,
"query",
options?.requiredOnly
),
cookies: getParametersFromOperation(
operation,
"cookie",
options?.requiredOnly
)
};
};
export { fetchSpecFromUrl, formatJsonOrYamlString, getExampleFromSchema, getHarRequest, getParametersFromOperation, getRequestBodyFromOperation, getRequestFromOperation, isJsonString, json, json2xml, parseJsonOrYaml, prettyPrintJson, transformToJson, yaml };

@@ -0,3 +1,106 @@

import { type OpenAPIV3 } from '@scalar/openapi-parser';
import type { HarRequest } from 'httpsnippet-lite';
export type AnyObject = Record<string, any>;
export type AnyStringOrObject = string | Record<string, any>;
export type BaseParameter = {
name: string;
description?: string | null;
value: string | number | Record<string, any>;
required?: boolean;
enabled: boolean;
};
export type ContentType = 'application/json' | 'application/xml' | 'text/plain' | 'text/html' | 'application/octet-stream' | 'application/x-www-form-urlencoded' | 'multipart/form-data';
export type Cookie = {
name: string;
value: string;
};
export type CustomRequestExample = {
lang: string;
label: string;
source: string;
};
export type HarRequestWithPath = HarRequest & {
path: string;
};
export type Header = {
name: string;
value: string;
};
export type Information = {
'description'?: string;
'operationId'?: string | number;
'parameters'?: Parameters[];
'responses'?: Record<string, ScalarResponse>;
'security'?: OpenAPIV3.SecurityRequirementObject[];
'requestBody'?: RequestBody;
'summary'?: string;
'tags'?: string[];
'deprecated'?: boolean;
/**
* Scalar
**/
'x-custom-examples'?: CustomRequestExample[];
/**
* Redocly, current
**/
'x-codeSamples'?: CustomRequestExample[];
/**
* Redocly, deprecated
**/
'x-code-samples'?: CustomRequestExample[];
};
export type Operation = {
httpVerb: string;
path: string;
operationId?: string;
name?: string;
description?: string;
information?: Information;
};
export type Parameters = {
name: string;
in?: string;
description?: string;
required?: boolean;
deprecated?: boolean;
allowEmptyValue?: boolean;
style?: 'form' | 'simple';
explode?: boolean;
allowReserved?: boolean;
schema?: Schema;
example?: any;
examples?: Map<string, any>;
};
export type Query = {
name: string;
value: string;
};
export type RequestBodyMimeTypes = {
[K in ContentType]?: {
schema?: any;
example?: any;
examples?: any;
};
};
export type ScalarResponse = {
description: string;
content: any;
};
export type RequestBody = {
description?: string;
required?: boolean;
content?: RequestBodyMimeTypes;
};
export type Schema = {
type: string;
name?: string;
example?: any;
default?: any;
format?: string;
description?: string;
properties?: Record<string, Schema>;
};
export type TransformedOperation = Operation & {
pathParameters?: Parameters[];
};
//# sourceMappingURL=types.d.ts.map

7

package.json

@@ -14,3 +14,3 @@ {

],
"version": "0.1.0",
"version": "0.1.1",
"engines": {

@@ -49,6 +49,9 @@ "node": ">=18"

"devDependencies": {
"@scalar/openapi-parser": "^0.3.2",
"axios": "^1.6.7",
"httpsnippet-lite": "^3.0.5",
"tsc-alias": "^1.8.8",
"vite": "^5.1.1",
"vitest": "^1.2.2",
"@scalar/build-tooling": "0.1.0"
"@scalar/build-tooling": "0.1.1"
},

@@ -55,0 +58,0 @@ "scripts": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc