zzapi
Version:
zzAPI is a REST API testing and documentation tool set. It is an open-source Postman alternative.
1,451 lines (1,437 loc) • 48.6 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve2, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve2(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/index.ts
var index_exports = {};
__export(index_exports, {
VarStore: () => VarStore,
captureVariables: () => captureVariables,
constructGotRequest: () => constructGotRequest,
convertCollection: () => convertCollection,
convertEnvironment: () => convertEnvironment,
executeGotRequest: () => executeGotRequest,
getAllRequestSpecs: () => getAllRequestSpecs,
getCurlRequest: () => getCurlRequest,
getEnvironments: () => getEnvironments,
getRequestPositions: () => getRequestPositions,
getRequestSpec: () => getRequestSpec,
loadVariables: () => loadVariables,
replaceVariablesInRequest: () => replaceVariablesInRequest,
runAllTests: () => runAllTests
});
module.exports = __toCommonJS(index_exports);
// src/parseBundle.ts
var YAML = __toESM(require("yaml"));
// src/utils/typeUtils.ts
function isArrayOrDict(obj) {
return typeof obj == "object" && !(obj instanceof Date) && obj !== null;
}
function isDict(obj) {
return isArrayOrDict(obj) && !Array.isArray(obj);
}
function getDescriptiveType(obj) {
if (obj === null) return "null";
if (Array.isArray(obj)) return "array";
if (obj instanceof Date) return "instanceof Date";
if (typeof obj === "object") return "dict";
return typeof obj;
}
function getStringIfNotScalar(data) {
if (typeof data !== "object") return data;
return JSON.stringify(data);
}
function getStringValueIfDefined(value) {
if (typeof value === "undefined") return void 0;
if (typeof value === "object") return JSON.stringify(value);
return value.toString();
}
function getStrictStringValue(value) {
if (typeof value === "undefined") return "undefined";
return getStringValueIfDefined(value);
}
function isString(value) {
return typeof value === "string" || value instanceof String;
}
function isFilePath(value) {
if (!isString(value)) {
return false;
}
const fileRegex = /file:\/\/([^\s]+)/g;
return fileRegex.test(value);
}
function hasFile(formValues) {
if (!formValues) {
return false;
}
for (const formValue of formValues) {
if (isFilePath(formValue.value)) {
return true;
}
}
return false;
}
// src/mergeData.ts
function paramObjectToArray(params) {
const paramArray = [];
Object.entries(params).forEach(([name, value]) => {
if (Array.isArray(value)) {
value.forEach((v) => {
paramArray.push({ name, value: v });
});
} else {
paramArray.push({ name, value });
}
});
return paramArray;
}
function getMergedParams(commonParams, requestParams) {
let mixedParams = [];
if (commonParams) {
if (Array.isArray(commonParams)) {
mixedParams = mixedParams.concat(commonParams);
} else {
mixedParams = mixedParams.concat(paramObjectToArray(commonParams));
}
}
if (requestParams) {
if (Array.isArray(requestParams)) {
mixedParams = mixedParams.concat(requestParams);
} else {
mixedParams = mixedParams.concat(paramObjectToArray(requestParams));
}
}
return mixedParams;
}
function getMergedHeaders(commonHeaders, requestHeaders) {
if (Array.isArray(commonHeaders)) {
commonHeaders = getArrayHeadersAsObject(commonHeaders);
}
if (Array.isArray(requestHeaders)) {
requestHeaders = getArrayHeadersAsObject(requestHeaders);
}
commonHeaders = withLowerCaseKeys(commonHeaders);
requestHeaders = withLowerCaseKeys(requestHeaders);
return Object.assign({}, commonHeaders, requestHeaders);
}
function getMergedOptions(cOptions = {}, rOptions = {}) {
const options = Object.assign(cOptions, rOptions);
const follow = options.follow === true;
const verifySSL = options.verifySSL === true;
const keepRawJSON = options.keepRawJSON === true;
const showHeaders = options.showHeaders === true;
const rawParams = options.rawParams === true;
const stopOnFailure = options.stopOnFailure === true;
return { follow, verifySSL, keepRawJSON, showHeaders, rawParams, stopOnFailure };
}
function getMergedSetVars(setvars = {}, captures = {}) {
const mergedVars = [];
let hasJsonVars = false;
if (captures.body) {
mergedVars.push({ varName: captures.body, type: "body", spec: "" });
}
if (captures.status) {
mergedVars.push({ varName: captures.status, type: "status", spec: "" });
}
if (captures.headers) {
for (const header in captures.headers) {
mergedVars.push({
varName: captures.headers[header],
type: "header",
spec: header
});
}
}
if (captures.json) {
for (const path3 in captures.json) {
hasJsonVars = true;
mergedVars.push({
varName: captures.json[path3],
type: "json",
spec: path3
});
}
}
for (const varName in setvars) {
let spec = setvars[varName];
let type;
if (spec.startsWith("$.")) {
type = "json";
hasJsonVars = true;
} else if (spec.startsWith("$h.")) {
type = "header";
spec = spec.replace(/^\$h\./, "");
} else if (spec === "status" || spec === "body") {
type = spec;
} else {
continue;
}
mergedVars.push({ varName, type, spec });
}
return { mergedVars, hasJsonVars };
}
function mergePrefixBasedTests(tests2) {
if (!tests2.json) tests2.json = {};
if (!tests2.headers) tests2.headers = {};
for (const key of Object.keys(tests2)) {
if (key.startsWith("$.")) {
tests2.json[key] = tests2[key];
delete tests2[key];
} else if (key.startsWith("$h.")) {
const headerName = key.replace(/^\$h\./, "");
tests2.headers[headerName] = tests2[key];
delete tests2[key];
}
}
}
function getMergedTests(cTests = {}, rTests = {}) {
mergePrefixBasedTests(cTests);
mergePrefixBasedTests(rTests);
cTests.headers = withLowerCaseKeys(cTests.headers);
rTests.headers = withLowerCaseKeys(rTests.headers);
let mergedData = {
status: rTests.status || cTests.status,
body: rTests.body || cTests.body,
headers: Object.assign({}, cTests.headers, rTests.headers),
json: Object.assign({}, cTests.json, rTests.json)
};
return { mergedTests: mergedData, hasJsonTests: Object.keys(mergedData.json).length > 0 };
}
function getArrayHeadersAsObject(objectSet) {
if (!objectSet) return {};
let finalObject = {};
objectSet.forEach((currObj) => {
const key = currObj.name;
const value = currObj.value;
finalObject[key] = value;
});
return finalObject;
}
function withLowerCaseKeys(obj) {
if (!obj) return {};
let newObj = {};
for (const key in obj) {
newObj[key.toLowerCase()] = obj[key];
}
return newObj;
}
function getMergedData(commonData, requestData) {
const name = requestData.name;
const method = requestData.method;
const params = getMergedParams(commonData.params, requestData.params);
const headers = getMergedHeaders(commonData.headers, requestData.headers);
const body = requestData.body;
const formValues = getMergedParams([], requestData.formValues);
const options = getMergedOptions(commonData.options, requestData.options);
const { mergedTests: tests2, hasJsonTests } = getMergedTests(
commonData == null ? void 0 : commonData.tests,
requestData.tests
);
const { mergedVars: setvars, hasJsonVars } = getMergedSetVars(
requestData.setvars,
requestData.capture
);
const mergedData = {
name,
httpRequest: {
baseUrl: commonData == null ? void 0 : commonData.baseUrl,
url: requestData.url,
method,
params,
headers,
body,
formValues: formValues.length > 0 ? formValues : void 0
},
options,
tests: tests2,
setvars,
expectJson: hasJsonTests || hasJsonVars
};
return mergedData;
}
// src/checkTypes.ts
function checkKey(obj, item, key, expectedTypes, optional) {
if (!optional && !obj.hasOwnProperty(key)) {
return `${key} key must be present in each ${item} item`;
} else if (obj.hasOwnProperty(key)) {
if (!expectedTypes.some((type) => type === "null" && obj[key] === null || typeof obj[key] === type)) {
return `${key} of ${item} must have one of ${expectedTypes} value, found ${typeof obj[key]}`;
}
}
return void 0;
}
function checkObjIsDict(obj, item) {
if (!isDict(obj)) {
return `${item} item must be a dict: found ${getDescriptiveType(obj)}`;
} else {
return void 0;
}
}
function checkHeaderItem(obj) {
let ret = checkObjIsDict(obj, "header");
if (ret !== void 0) return ret;
ret = checkKey(obj, "header", "name", ["string"], false);
if (ret !== void 0) return ret;
ret = checkKey(obj, "header", "value", ["string", "number", "boolean", "null"], false);
if (ret !== void 0) return ret;
return void 0;
}
function checkParamItem(obj) {
let ret = checkObjIsDict(obj, "param");
if (ret !== void 0) return ret;
ret = checkKey(obj, "param", "name", ["string"], true);
if (ret !== void 0) return ret;
return void 0;
}
function checkHeadersParamsOptionsTestsCaptures(obj) {
if (obj.hasOwnProperty("headers")) {
const headers = obj.headers;
if (!isArrayOrDict(headers)) {
return `Headers must be an array or a dictionary: found ${typeof headers}`;
}
if (Array.isArray(headers)) {
for (const header of headers) {
const headerError = checkHeaderItem(header);
if (headerError !== void 0) {
return `error in header item ${getStrictStringValue(header)}: ${headerError}`;
}
}
} else {
for (const header in headers) {
const headerError = checkHeaderItem({ name: header, value: headers[header] });
if (headerError !== void 0) {
return `error in header item ${getStrictStringValue(header)}: ${headerError}`;
}
}
}
}
if (obj.hasOwnProperty("params")) {
const params = obj.params;
if (!isArrayOrDict(params)) {
return `Params must be an array or a dictionary: found ${typeof params}`;
}
if (Array.isArray(params)) {
for (const param of params) {
const paramError = checkParamItem(param);
if (paramError !== void 0) {
return `error in param item ${getStrictStringValue(param)}: ${paramError}`;
}
}
}
}
if (obj.hasOwnProperty("options")) {
const optionsError = checkOptions(obj.options);
if (optionsError !== void 0) return `error in options: ${optionsError}`;
}
if (obj.hasOwnProperty("tests")) {
const testsError = checkTests(obj.tests);
if (testsError !== void 0) return `error in tests: ${testsError}`;
}
if (obj.hasOwnProperty("capture")) {
const capturesError = checkCaptures(obj.capture);
if (capturesError !== void 0) return `error in captures: ${capturesError}`;
}
return void 0;
}
function checkTests(obj) {
let ret = checkObjIsDict(obj, "tests");
if (ret !== void 0) return ret;
if (obj.hasOwnProperty("json")) {
ret = checkObjIsDict(obj.json, "JSON tests");
if (ret !== void 0) return ret;
}
if (obj.hasOwnProperty("body") && !(isDict(obj.body) || typeof obj.body === "string")) {
return `body tests item must be a dict or string: found ${getDescriptiveType(obj.body)}`;
}
if (obj.hasOwnProperty("status") && !(isDict(obj.status) || typeof obj.status === "number")) {
return `status tests item must be a dict or number: found ${getDescriptiveType(obj.status)}`;
}
if (obj.hasOwnProperty("headers")) {
ret = checkObjIsDict(obj.headers, "header tests");
if (ret !== void 0) return ret;
}
return void 0;
}
function checkCaptures(obj) {
let ret = checkObjIsDict(obj, "captures");
if (ret !== void 0) return ret;
if (obj.hasOwnProperty("json")) {
ret = checkObjIsDict(obj.json, "JSON captures");
return ret;
}
ret = checkKey(obj, "captures", "body", ["string"], true);
if (ret !== void 0) return ret;
ret = checkKey(obj, "captures", "status", ["string"], true);
if (ret !== void 0) return ret;
if (obj.hasOwnProperty("headers")) {
ret = checkObjIsDict(obj.headers, "header captures");
if (ret !== void 0) return ret;
}
return void 0;
}
var VALID_OPTIONS = {
follow: true,
verifySSL: true,
keepRawJSON: true,
showHeaders: true,
rawParams: true,
stopOnFailure: true
};
function checkOptions(obj) {
let ret = checkObjIsDict(obj, "options");
if (ret !== void 0) return ret;
for (const key in obj) {
if (VALID_OPTIONS[key]) {
ret = checkKey(obj, "options", key, ["boolean"], true);
if (ret !== void 0) return ret;
} else {
return `options must be among ${Object.keys(VALID_OPTIONS)}: found ${key}`;
}
}
return void 0;
}
function checkCommonType(obj) {
let ret = checkObjIsDict(obj, "common");
if (ret !== void 0) return ret;
ret = checkKey(obj, "common", "baseUrl", ["string"], true);
if (ret !== void 0) return ret;
ret = checkHeadersParamsOptionsTestsCaptures(obj);
if (ret !== void 0) return ret;
return void 0;
}
var VALID_METHODS = {
options: true,
get: true,
post: true,
put: true,
patch: true,
head: true,
delete: true,
trace: true
};
function validateRawRequest(obj) {
let ret = checkObjIsDict(obj, "request");
if (ret !== void 0) return ret;
ret = checkHeadersParamsOptionsTestsCaptures(obj);
if (ret !== void 0) return ret;
ret = checkKey(obj, "request", "url", ["string"], false);
if (ret !== void 0) return ret;
if (!obj.hasOwnProperty("method")) {
return `method key must be present in each request item`;
} else {
if (typeof obj.method !== "string") {
return `value of method key must be a string`;
} else {
const methodToPass = obj.method.toLowerCase();
if (!VALID_METHODS[methodToPass])
return `method key must have value among ${Object.keys(VALID_METHODS)}: found ${methodToPass}`;
}
}
if (obj.hasOwnProperty("formValues") && obj.hasOwnProperty("body")) {
return `both body and formValues can't be present in the same request.`;
}
if (obj.hasOwnProperty("method") && obj["method"] == "GET" && obj.hasOwnProperty("formValues")) {
return `formValues can't be used with method GET`;
}
if (obj.hasOwnProperty("method") && obj["method"] == "GET" && obj.hasOwnProperty("body")) {
return `body can't be used with method GET`;
}
return void 0;
}
function checkVariables(obj) {
let ret = checkObjIsDict(obj, "variables");
if (ret !== void 0) return ret;
for (const key in obj) {
if (typeof key !== "string") return `Environment names must be a string: ${key} is not a string`;
const variables = obj[key];
ret = checkObjIsDict(obj, `variables environment ${key}`);
if (ret !== void 0) return ret;
for (const varName in variables) {
if (typeof varName !== "string") {
return `variable name ${varName} in env ${key} is not a string`;
}
}
}
return void 0;
}
// src/parseBundle.ts
var VALID_KEYS = {
requests: true,
common: true,
variables: true
};
function getRawRequests(doc) {
let parsedData = YAML.parse(doc);
if (!isDict(parsedData)) {
throw new Error("Bundle could not be parsed. Is your bundle a valid YAML document?");
}
for (const key in parsedData) {
if (!VALID_KEYS[key]) {
throw new Error(`Invalid key: ${key} in bundle. Only ${Object.keys(VALID_KEYS)} are allowed.`);
}
}
let commonData = parsedData.common;
if (commonData !== void 0) {
const error = checkCommonType(commonData);
if (error !== void 0) throw new Error(`error in common: ${error}`);
} else {
commonData = {};
}
const allRequests = parsedData.requests;
if (!isDict(allRequests)) {
throw new Error("requests must be a dictionary in the bundle.");
}
return { rawRequests: allRequests, commonData };
}
function checkAndMergeRequest(commonData, allRequests, name) {
let request = allRequests[name];
if (request === void 0) throw new Error(`Request ${name} is not defined in this bundle`);
request.name = name;
const error = validateRawRequest(request);
if (error !== void 0) throw new Error(`error in request '${name}': ${error}`);
return getMergedData(commonData, request);
}
function getRequestPositions(document) {
let positions = [];
const lineCounter = new YAML.LineCounter();
let doc = YAML.parseDocument(document, { lineCounter });
if (!YAML.isMap(doc.contents)) {
return positions;
}
let contents = doc.contents;
function getPosition(key, name) {
var _a, _b;
const start = (_a = key.range) == null ? void 0 : _a[0];
const end = (_b = key.range) == null ? void 0 : _b[1];
const pos = {
name,
start: lineCounter.linePos(start),
end: lineCounter.linePos(end)
};
return pos;
}
contents.items.forEach((topLevelItem) => {
if (!YAML.isMap(topLevelItem.value)) {
return;
}
let key = topLevelItem.key;
if (key.value !== "requests") {
return;
}
positions.push(getPosition(key));
let requests = topLevelItem.value;
requests.items.forEach((request) => {
if (!YAML.isMap(request.value)) {
return;
}
let key2 = request.key;
const name = key2.value;
positions.push(getPosition(key2, name));
});
});
return positions;
}
function getAllRequestSpecs(document) {
const { rawRequests: allRequests, commonData } = getRawRequests(document);
const requests = {};
for (const name in allRequests) {
requests[name] = checkAndMergeRequest(commonData, allRequests, name);
}
return requests;
}
function getRequestSpec(document, name) {
const { rawRequests: allRequests, commonData } = getRawRequests(document);
return checkAndMergeRequest(commonData, allRequests, name);
}
// src/variables.ts
var VarStore = class {
constructor() {
this.loadedVariables = {};
this.capturedVariables = {};
}
getLoadedVariables() {
return this.loadedVariables;
}
setLoadedVariables(vars) {
this.loadedVariables = vars;
}
resetLoadedVariables(vars) {
this.setLoadedVariables({});
}
mergeLoadedVariables(vars) {
Object.assign(this.loadedVariables, vars);
}
getCapturedVariables() {
return this.capturedVariables;
}
setCapturedVariables(vars) {
this.capturedVariables = vars;
}
resetCapturedVariables() {
this.setCapturedVariables({});
}
mergeCapturedVariables(vars) {
Object.assign(this.capturedVariables, vars);
}
getAllVariables() {
return Object.assign({}, this.loadedVariables, this.capturedVariables);
}
};
// src/variableParser.ts
var YAML2 = __toESM(require("yaml"));
function getBundleVariables(doc) {
let parsedData = doc ? YAML2.parse(doc) : {};
if (!isDict(parsedData)) {
throw new Error("Bundle could not be parsed. Is your bundle a valid YAML document?");
}
const variables = parsedData.variables;
if (variables !== void 0) {
const error = checkVariables(variables);
if (error !== void 0) throw new Error(`error in variables: ${error}`);
return variables;
} else {
return {};
}
}
function getEnvironments(bundleContent, varFileContents) {
const bundleEnvNames = Object.keys(getBundleVariables(bundleContent));
const fileEnvNames = [];
varFileContents.forEach((fileContent) => {
const envs = YAML2.parse(fileContent);
if (isDict(envs)) {
fileEnvNames.push(...Object.keys(envs));
}
});
const uniqueNames = /* @__PURE__ */ new Set([...bundleEnvNames, ...fileEnvNames]);
return [...uniqueNames];
}
function replaceEnvironmentVariables(vars) {
const PREFIX = "$env.";
const getVal = (val) => {
if (typeof val !== "string" || !val.startsWith(PREFIX)) return val;
const envVarName = val.slice(PREFIX.length);
return envVarName in process.env ? process.env[envVarName] : val;
};
const replacedVars = {};
for (const key in vars) replacedVars[key] = getVal(vars[key]);
return replacedVars;
}
function loadVariables(envName, bundleContent, varFileContents) {
var _a;
if (!envName) return {};
const allBundleVariables = getBundleVariables(bundleContent);
const bundleVars = (_a = allBundleVariables[envName]) != null ? _a : {};
const envVars = {};
varFileContents.forEach((fileContents) => {
const parsedData = YAML2.parse(fileContents);
if (parsedData && isDict(parsedData[envName])) Object.assign(envVars, parsedData[envName]);
});
const basicVars = Object.assign({}, envVars, bundleVars);
const vars = replaceEnvironmentVariables(basicVars);
return vars;
}
// src/replaceVars.ts
function replaceVariablesInArray(data, variables) {
let newData = [];
let undefs = [];
data.forEach((item) => {
const { data: newItem, undefinedVars: newUndefs } = replaceVariables(item, variables);
newData.push(newItem);
undefs.push(...newUndefs);
});
return { data: newData, undefinedVars: undefs };
}
function replaceVariablesInDict(obj, variables) {
let newData = {};
let undefs = [];
for (const key in obj) {
const { data: newItem, undefinedVars: newUndefs } = replaceVariables(obj[key], variables);
newData[key] = newItem;
undefs.push(...newUndefs);
}
return { data: newData, undefinedVars: undefs };
}
function replaceVariablesInObject(data, variables) {
if (Array.isArray(data)) {
return replaceVariablesInArray(data, variables);
} else {
return replaceVariablesInDict(data, variables);
}
}
var VAR_REGEX_WITH_BRACES = new RegExp("(?<!\\\\)\\$\\(([_a-zA-Z]\\w*)\\)", "g");
var VAR_REGEX_WITHOUT_BRACES = new RegExp("(?<!\\\\)\\$([_a-zA-Z]\\w*)(?=\\W|$)", "g");
function replaceVariablesInString(text, variables) {
let valueInNativeType;
let variableIsFullText = false;
const undefs = [];
function replaceVar(match, varName) {
if (typeof varName === "string") {
if (variables.hasOwnProperty(varName)) {
const varVal = variables[varName];
if (text === match) {
variableIsFullText = true;
valueInNativeType = varVal;
}
return getStrictStringValue(varVal);
} else {
undefs.push(varName);
}
}
return match;
}
const outputText = text.replace(VAR_REGEX_WITH_BRACES, (match, varName) => {
return replaceVar(match, varName);
}).replace(VAR_REGEX_WITHOUT_BRACES, (match) => {
if (match.length <= 1) return match;
const varName = match.slice(1);
return replaceVar(match, varName);
});
if (variableIsFullText) {
return { data: valueInNativeType, undefinedVars: undefs };
} else {
return { data: outputText, undefinedVars: undefs };
}
}
function replaceVariables(data, variables) {
if (isArrayOrDict(data)) {
return replaceVariablesInObject(data, variables);
} else if (typeof data === "string") {
return replaceVariablesInString(data, variables);
} else {
return { data, undefinedVars: [] };
}
}
function replaceVariablesInRequest(request, variables) {
const undefs = [];
const httpPropertiesToReplace = ["baseUrl", "url", "params", "headers", "body"];
httpPropertiesToReplace.forEach((prop) => {
const httpKey = prop;
const replacedData2 = replaceVariables(request.httpRequest[httpKey], variables);
request.httpRequest[httpKey] = replacedData2.data;
undefs.push(...replacedData2.undefinedVars);
});
const replacedData = replaceVariables(request.tests, variables);
request.tests = replacedData.data;
undefs.push(...replacedData.undefinedVars);
return undefs;
}
// src/executeRequest.ts
var import_got = __toESM(require("got"));
var import_file_from_path = require("formdata-node/file-from-path");
var import_form_data_encoder = require("form-data-encoder");
var import_formdata_node = require("formdata-node");
var import_stream = require("stream");
var path = __toESM(require("path"));
function constructGotRequest(allData, workingDir) {
const completeUrl = getURL(
allData.httpRequest.baseUrl,
allData.httpRequest.url,
getParamsForUrl(allData.httpRequest.params, allData.options.rawParams)
);
const options = {
method: allData.httpRequest.method.toLowerCase(),
body: getBody(allData, workingDir),
headers: allData.httpRequest.headers,
followRedirect: allData.options.follow,
https: { rejectUnauthorized: allData.options.verifySSL },
retry: { limit: 0 }
};
return (0, import_got.default)(completeUrl, options);
}
function getFileFromPath(filePath, workingDir) {
if (workingDir) {
filePath = path.resolve(workingDir, filePath.slice(7));
} else {
filePath = path.resolve(filePath.slice(7));
}
const fileName = path.basename(filePath);
return (0, import_file_from_path.fileFromPathSync)(filePath, fileName);
}
function constructFormUrlEncoded(request) {
const formValues = request.httpRequest.formValues;
if (!formValues) return "";
const result = new URLSearchParams();
if (formValues) {
request.httpRequest.headers["content-type"] = "application/x-www-form-urlencoded";
}
for (const { name, value } of formValues) {
result.append(name, value);
}
return result.toString();
}
function constructFormData(request, workingDir) {
const formValues = request.httpRequest.formValues;
if (!formValues) return;
const multipart = new import_formdata_node.FormData();
for (const fv of formValues) {
if (isFilePath(fv.value)) {
multipart.append(fv.name, getFileFromPath(fv.value, workingDir));
} else {
multipart.append(fv.name, fv.value);
}
}
const fde = new import_form_data_encoder.FormDataEncoder(multipart);
request.httpRequest.headers["content-type"] = fde.contentType;
return import_stream.Readable.from(fde);
}
function getBody(request, workingDir) {
const body = request.httpRequest.body;
const formValues = request.httpRequest.formValues;
if (request.httpRequest.headers["content-type"] == "multipart/form-data" || hasFile(formValues)) {
return constructFormData(request, workingDir);
}
if (formValues) {
return constructFormUrlEncoded(request);
}
return getStringValueIfDefined(body);
}
function executeGotRequest(httpRequest) {
return __async(this, null, function* () {
const startTime = (/* @__PURE__ */ new Date()).getTime();
let responseObject;
let size = 0;
let error = "";
try {
responseObject = yield httpRequest;
size = Buffer.byteLength(responseObject.rawBody);
} catch (e) {
const res = e.response;
if (res) {
responseObject = res;
size = res.body ? Buffer.byteLength(res.body) : 0;
} else {
responseObject = {};
if (e.code === "ERR_INVALID_URL") {
error = `Invalid URL: ${e.input}`;
} else if (e.name === "CancelError") {
error = "Cancelled";
} else {
error = e.message || e.code;
}
}
}
const executionTime = (/* @__PURE__ */ new Date()).getTime() - startTime;
return { response: responseObject, executionTime, byteLength: size, error };
});
}
function getParamsForUrl(params, rawParams) {
if (!params || params.length < 1) return "";
let paramArray = [];
params.forEach((param) => {
const key = param.name;
let value = param.value;
if (value == void 0) {
paramArray.push(key);
} else if (rawParams) {
paramArray.push(`${key}=${getStringValueIfDefined(value)}`);
} else {
paramArray.push(`${key}=${encodeURIComponent(getStringValueIfDefined(value))}`);
}
});
const paramString = paramArray.join("&");
return `?${paramString}`;
}
function getURL(baseUrl, url, paramsForUrl) {
if (!baseUrl || !url.startsWith("/")) return url + paramsForUrl;
return baseUrl + url + paramsForUrl;
}
// src/constructCurl.ts
var import_path = __toESM(require("path"));
function replaceSingleQuotes(value) {
if (typeof value !== "string") return value;
return value.replace(/'/g, "%27");
}
function formatCurlFormField(key, value, workingDir) {
if (isFilePath(value)) {
return ` --form ${key}=@"${import_path.default.resolve(workingDir || "", value.slice(7))}"`;
}
return ` --form '${key}="${encodeURIComponent(value)}"'`;
}
function getFormDataUrlEncoded(request) {
const formValues = request.httpRequest.formValues;
if (!formValues) return "";
let result = "";
formValues.forEach((formValue) => {
result += ` --data "${formValue.name}=${encodeURIComponent(formValue.value)}"`;
});
return result;
}
function getFormDataCurlRequest(request, workingDir) {
const formValues = request.httpRequest.formValues;
if (!formValues) return "";
let result = "";
for (const { name, value } of formValues) {
result += formatCurlFormField(name, value, workingDir);
}
return result;
}
function getCurlRequest(request, workingDir) {
let curl = "curl";
if (request.httpRequest.headers["content-type"] == "multipart/form-data" || hasFile(request.httpRequest.formValues)) {
curl += getFormDataCurlRequest(request, workingDir);
curl += ` '${replaceSingleQuotes(
getURL(
request.httpRequest.baseUrl,
request.httpRequest.url,
getParamsForUrl(request.httpRequest.params, request.options.rawParams)
)
)}'`;
return curl;
} else if (request.httpRequest.headers["content-type"] == "application/x-www-form-urlencoded" || request.httpRequest.formValues) {
curl += getFormDataUrlEncoded(request);
curl += ` '${replaceSingleQuotes(
getURL(
request.httpRequest.baseUrl,
request.httpRequest.url,
getParamsForUrl(request.httpRequest.params, request.options.rawParams)
)
)}'`;
return curl;
}
curl += ` -X ${request.httpRequest.method.toUpperCase()}`;
if (request.httpRequest.headers !== void 0) {
for (const header in request.httpRequest.headers) {
curl += ` -H '${replaceSingleQuotes(`${header}: ${request.httpRequest.headers[header]}`)}'`;
}
}
if (request.httpRequest.body !== void 0) {
curl += ` -d '${replaceSingleQuotes(getStringValueIfDefined(request.httpRequest.body))}'`;
}
if (request.options.follow) curl += " -L";
if (!request.options.verifySSL) curl += " -k";
if (request.options.showHeaders) curl += " -i";
curl += ` '${replaceSingleQuotes(
getURL(
request.httpRequest.baseUrl,
request.httpRequest.url,
getParamsForUrl(request.httpRequest.params, request.options.rawParams)
)
)}'`;
return curl;
}
// src/runTests.ts
var import_jsonpath = __toESM(require("jsonpath"));
var SKIP_CLAUSE = "$skip";
var OPTIONS_CLAUSE = "$options";
var MULTI_CLAUSE = "$multi";
function hasFailure(res) {
return res.results.some((r) => !r.pass) || res.subResults.some(hasFailure);
}
function runAllTests(tests2, responseData, stopOnFailure, rootSpec = null, skip) {
const res = { spec: rootSpec, results: [], subResults: [] };
if (!tests2) return res;
if (tests2.status) {
const expected = tests2.status;
const received = responseData.status;
const statusResults = runTest("status", expected, received, skip);
res.subResults.push(statusResults);
}
if (stopOnFailure && hasFailure(res)) return res;
for (const spec in tests2.headers) {
const expected = tests2.headers[spec];
const received = responseData.headers ? responseData.headers[spec] : "";
const headerResults = runTest(spec, expected, received, skip);
res.subResults.push(headerResults);
}
res.subResults.push(...runJsonTests(tests2.json, responseData.json, skip));
if (tests2.body) {
const expected = tests2.body;
const received = responseData.body;
const bodyResults = runTest("body", expected, received, skip);
res.subResults.push(bodyResults);
}
return res;
}
function runJsonTests(tests2, jsonData, skip) {
const results = [];
for (const spec in tests2) {
const expected = tests2[spec];
let received;
try {
received = getValueForJSONTests(
jsonData,
spec,
typeof expected === "object" && expected !== null && expected[MULTI_CLAUSE]
);
} catch (err) {
results.push({
spec,
skipped: skip || typeof expected === "object" && expected !== null && expected[SKIP_CLAUSE],
results: [{ pass: false, expected, received: "", op: spec, message: err }],
subResults: []
});
continue;
}
const jsonResults = runTest(spec, expected, received, skip);
results.push(jsonResults);
}
return results;
}
function runTest(spec, expected, received, skip) {
if (expected !== null && typeof expected === "object")
return runObjectTests(expected, received, spec, skip);
expected = getStringIfNotScalar(expected);
received = getStringIfNotScalar(received);
const pass = expected === received;
return { spec, skipped: skip, results: [{ pass, expected, received, op: ":" }], subResults: [] };
}
function getValueForJSONTests(responseContent, key, multi) {
try {
return multi ? import_jsonpath.default.query(responseContent, key) : import_jsonpath.default.value(responseContent, key);
} catch (err) {
throw new Error(`Error while evaluating JSONPath ${key}: ${err.description || err.message || err}`);
}
}
function getType(data) {
if (data === null) return "null";
if (Array.isArray(data)) return "array";
return typeof data;
}
var tests = {
$eq: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [{ pass: received === expected, expected, received, op }]
};
},
$ne: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [{ pass: received !== expected, expected, received, op }]
};
},
$gt: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [{ pass: received > expected, expected, received, op }]
};
},
$lt: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [{ pass: received < expected, expected, received, op }]
};
},
$lte: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [{ pass: received <= expected, expected, received, op }]
};
},
$gte: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [{ pass: received >= expected, expected, received, op }]
};
},
$size: function(expectedObj, receivedObj, spec, op, options) {
const res = { spec, results: [], subResults: [] };
const receivedLen = typeof receivedObj === "object" && receivedObj !== null ? Object.keys(receivedObj).length : typeof receivedObj === "string" || Array.isArray(receivedObj) ? receivedObj.length : void 0;
const received = getStringIfNotScalar(receivedObj);
const expected = getStringIfNotScalar(expectedObj);
if (typeof expectedObj === "number") {
const compResult2 = {
pass: expected === receivedLen,
op,
expected,
received: `(length: ${receivedLen}) -> ${received}`
};
res.results.push(compResult2);
return res;
}
if (isDict(expectedObj)) {
const compRes = runObjectTests(expectedObj, receivedLen, spec);
res.results.push(...compRes.results);
res.subResults.push(...compRes.subResults);
return res;
}
const compResult = {
pass: false,
op,
expected,
received,
message: "value for $size is not a number or valid JSON"
};
res.results.push(compResult);
return res;
},
$exists: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
const exists = received !== void 0;
return {
spec,
subResults: [],
results: [{ pass: exists === expected, expected, received, op }]
};
},
$type: function(expectedObj, receivedObj, spec, op, options) {
const receivedType = getType(receivedObj);
const receivedStr = `${getStringIfNotScalar(receivedObj)} (type ${receivedType})`;
const expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [{ pass: expected === receivedType, expected, received: receivedStr, op }]
};
},
$regex: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
const regexOpts = options[OPTIONS_CLAUSE];
const regex = new RegExp(expected, regexOpts);
let pass = false, message = "";
try {
pass = typeof received === "string" && regex.test(received);
} catch (err) {
message = err.message;
}
return {
spec,
subResults: [],
results: [{ pass, expected, received, op, message }]
};
},
$sw: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [
{ pass: typeof received === "string" && received.startsWith(expected), expected, received, op }
]
};
},
$ew: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [
{ pass: typeof received === "string" && received.endsWith(expected), expected, received, op }
]
};
},
$co: function(expectedObj, receivedObj, spec, op, options) {
const received = getStringIfNotScalar(receivedObj), expected = getStringIfNotScalar(expectedObj);
return {
spec,
subResults: [],
results: [
{ pass: typeof received === "string" && received.includes(expected), expected, received, op }
]
};
},
[OPTIONS_CLAUSE]: function(expectedObj, receivedObj, spec, op, options) {
return {
spec,
subResults: [],
results: []
};
},
[SKIP_CLAUSE]: function(expectedObj, receivedObj, spec, op, options) {
return {
spec,
subResults: [],
results: []
};
},
[MULTI_CLAUSE]: function(expectedObj, receivedObj, spec, op, options) {
return {
spec,
subResults: [],
results: []
};
},
$tests: function(expectedObj, receivedObj, spec, op, options) {
const res = { spec, results: [], subResults: [] };
const expected = getStringIfNotScalar(expectedObj);
const received = getStringIfNotScalar(receivedObj);
const recursiveTests = expectedObj;
if (!isDict(recursiveTests)) {
const compResult = {
pass: false,
op,
expected,
received,
message: "recursive tests must be dicts"
};
res.results.push(compResult);
return res;
}
mergePrefixBasedTests(recursiveTests);
const compRes = runJsonTests(recursiveTests.json, receivedObj, options[SKIP_CLAUSE]);
res.subResults.push(...compRes);
return res;
}
};
function runObjectTests(opVals, receivedObject, spec, skip) {
const objRes = {
spec,
results: [],
subResults: [],
skipped: skip || opVals[SKIP_CLAUSE]
};
const options = {
[OPTIONS_CLAUSE]: opVals[OPTIONS_CLAUSE],
[SKIP_CLAUSE]: objRes.skipped
};
const testNames = Object.keys(tests);
for (const op in opVals) {
if (testNames.includes(op)) {
const res = tests[op](opVals[op], receivedObject, spec, op, options);
objRes.results.push(...res.results);
objRes.subResults.push(...res.subResults);
} else {
objRes.results.push({
pass: false,
expected: `one of ${testNames.join(", ")}`,
received: op,
op: "",
message: "Note: use $eq to compare objects"
});
}
}
return objRes;
}
// src/captureVars.ts
var import_jsonpath2 = __toESM(require("jsonpath"));
function captureVariables(requestData, responseData) {
const setvars = requestData.setvars;
const headers = responseData.headers;
let captureOutput = "";
let capturedVariables = {};
for (const { varName, type, spec } of setvars) {
let value = void 0;
if (type === "json") {
let errorInJP = void 0;
try {
value = import_jsonpath2.default.value(responseData.json, spec);
} catch (err) {
if (err.description !== void 0) {
errorInJP = err.description;
}
}
if (errorInJP !== void 0) {
captureOutput += `Could not set "${varName}", error in jsonpath: ${errorInJP}
`;
}
} else if (type === "header") {
value = headers !== void 0 ? headers[spec.toLowerCase()] : void 0;
} else if (type === "status") {
value = responseData.status;
} else if (type === "body") {
value = requestData.expectJson ? responseData.json : responseData.body;
}
capturedVariables[varName] = value;
}
return { capturedVars: capturedVariables, captureErrors: captureOutput };
}
// src/convertPostman.ts
var fs = __toESM(require("fs"));
var YAML3 = __toESM(require("yaml"));
var re = /\{\{(\w+)\}\}/g;
function reformatVariables(text) {
return text.replace(re, "$($1)");
}
function reformatVariablesInObject(object) {
for (const key in object) {
if (typeof object[key] === "string") {
object[key] = reformatVariables(object[key]);
} else if (typeof object[key] === "object") {
reformatVariablesInObject(object[key]);
}
}
}
function addRequest(prefix, element, requests) {
var _a, _b, _c;
const request = {};
const name = `${prefix}${element.name}`;
requests[name] = request;
const r = element.request;
request.method = r.method;
if (r.url) {
const protocol = r.url.protocol || "";
const host = (r.url.host || []).join(".");
const path3 = (r.url.path || []).join("/");
if (protocol) {
request.url = reformatVariables(`${protocol}://${host}/${path3}`);
} else {
request.url = reformatVariables(`${host}/${path3}`);
}
}
let contentType = "";
if (r.header && r.header.length > 0) {
request.headers = {};
for (const h of r.header) {
request.headers[h.key] = reformatVariables(h.value);
if (h.key.toLowerCase() === "content-type") {
contentType = h.value;
}
}
}
if (r.url && r.url.query && r.url.query.length > 0) {
request.params = {};
for (const q of r.url.query) {
const { key, value } = q;
if (request.params[key]) {
if (!Array.isArray(request.params[key])) {
request.params[key] = [request.params[key]];
}
request.params[key].push(value);
} else {
request.params[key] = value;
}
}
}
if (r.body && r.body.mode === "raw") {
if (((_c = (_b = (_a = r.body) == null ? void 0 : _a.options) == null ? void 0 : _b.raw) == null ? void 0 : _c.language) === "json" || contentType === "application/json") {
try {
request.body = JSON.parse(r.body.raw);
reformatVariablesInObject(request.body);
} catch (e) {
request.body = reformatVariables(r.body.raw);
}
} else {
request.body = reformatVariables(r.body.raw);
}
} else if (r.body) {
request.body = `UNSUPPORTED body type ${r.body.mode}, could not convert.`;
}
}
function addRequestsFromFolder(prefix, item, requests) {
item.forEach((element) => {
if (element.item) {
const subPrefix = prefix ? `${prefix}${element.name}/` : `${element.name}/`;
addRequestsFromFolder(subPrefix, element.item, requests);
} else if (element.request) {
addRequest(prefix, element, requests);
}
});
}
function convertCollection(filePath) {
var _a;
const contents = fs.readFileSync(filePath, "utf-8");
const collection = JSON.parse(contents);
if (((_a = collection == null ? void 0 : collection.info) == null ? void 0 : _a.schema) !== "https://schema.getpostman.com/json/collection/v2.1.0/collection.json") {
throw Error("Not a Postman v2.1.0 collection. Cannot import");
}
const bundle = {
requests: {}
};
addRequestsFromFolder("", collection.item, bundle.requests);
const yamlDoc = new YAML3.Document(bundle);
YAML3.visit(yamlDoc, {
Pair(_, node) {
var _a2, _b, _c;
if (((_a2 = node == null ? void 0 : node.key) == null ? void 0 : _a2.value) === "requests") {
node.key.spaceBefore = true;
node.value.items.forEach((i) => {
i.key.spaceBefore = true;
});
}
if (((_b = node == null ? void 0 : node.key) == null ? void 0 : _b.value) === "headers" || ((_c = node == null ? void 0 : node.key) == null ? void 0 : _c.value) === "params") {
node.value.items.forEach((i) => {
i.flow = true;
});
}
}
});
return YAML3.stringify(yamlDoc);
}
function convertEnvironment(filePath) {
const contents = fs.readFileSync(filePath, "utf-8");
const environment = JSON.parse(contents);
const essentialKeys = ["name", "_postman_variable_scope", "values"];
essentialKeys.forEach((key) => {
if (!environment.hasOwnProperty(key)) {
throw Error(`Did you select an exported postman environment?`);
}
});
const name = environment.name;
const variables = {};
variables[name] = {};
const postmanVars = environment.values;
postmanVars.forEach((item) => {
variables[name][item.key] = item.value;
});
let env = "";
env += "# The variable set corresponding to the environment is below.\n# Save it as a .zzv file, or copy-paste it into an existing .zzv file,\n# or paste it into your bundle under the top level 'variables' object.\n";
if (environment._postman_variable_scope === "globals") {
env += "# If these variables are intended to be global, add them to each env\n";
}
env += "\n" + YAML3.stringify(variables);
return env;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
VarStore,
captureVariables,
constructGotRequest,
convertCollection,
convertEnvironment,
executeGotRequest,
getAllRequestSpecs,
getCurlRequest,
getEnvironments,
getRequestPositions,
getRequestSpec,
loadVariables,
replaceVariablesInRequest,
runAllTests
});
//# sourceMappingURL=index.js.map
;