🚀. Socket Launch Week Day 2:Introducing Manifest Alerts.Learn more
Sign In

dynamic-openapi-cli

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dynamic-openapi-cli - npm Package Compare versions

Comparing version
0.1.2
to
0.1.3-next.31f39f5
+14
-192
dist/index.d.ts

@@ -1,192 +0,10 @@

import { OpenAPIV3 } from 'openapi-types';
import { PrimitiveValue, CommandDefinition, CLI } from 'cli-args-parser';
import { ParsedOperation, ParsedSpec, ParsedServer, OperationFilters } from 'dynamic-openapi-tools/parser';
export { ExternalDocs, OperationFilter, OperationFilters, ParsedOperation, ParsedParameter, ParsedRequestBody, ParsedResponse, ParsedServer, ParsedServerVariable, ParsedSpec, ParsedTag, filterOperations, loadSpec, resolveSource, resolveSpec } from 'dynamic-openapi-tools/parser';
import { ResolvedAuth, AuthConfig } from 'dynamic-openapi-tools/auth';
export { AuthConfig, ResolvedAuth, TokenExchangeApplyConfig, TokenExchangeAuthConfig, TokenExchangeRequestConfig, TokenExchangeResponseConfig, resolveAuth } from 'dynamic-openapi-tools/auth';
import { FetchWithRetryOptions } from 'dynamic-openapi-tools/utils';
export { FetchWithRetryOptions, RetryPolicy, fetchWithRetry } from 'dynamic-openapi-tools/utils';
import { PrimitiveValue, CommandDefinition, CLI } from 'dynamic-openapi-tools/cli';
import { BuildBundleResult } from 'dynamic-openapi-tools/bundle';
declare function resolveSource(source: string | OpenAPIV3.Document): {
type: "inline";
value: OpenAPIV3.Document<{}>;
} | {
type: "url";
value: string;
} | {
type: "inline";
value: string;
} | {
type: "file";
value: string;
};
declare function loadSpec(source: string | OpenAPIV3.Document): Promise<OpenAPIV3.Document>;
interface ParsedServerVariable {
enum?: string[];
default: string;
description?: string;
}
interface ParsedServer {
url: string;
description?: string;
variables?: Record<string, ParsedServerVariable>;
}
interface ParsedTag {
name: string;
description?: string;
externalDocs?: {
url: string;
description?: string;
};
}
interface ExternalDocs {
url: string;
description?: string;
}
interface ParsedExample {
summary?: string;
description?: string;
value?: unknown;
}
interface ParsedLink {
operationId?: string;
operationRef?: string;
parameters?: Record<string, string>;
description?: string;
}
interface ParsedResponse {
description: string;
content?: Record<string, {
schema?: OpenAPIV3.SchemaObject;
}>;
schema?: OpenAPIV3.SchemaObject;
mediaType?: string;
example?: unknown;
examples?: Record<string, ParsedExample>;
links?: Record<string, ParsedLink>;
}
interface ParsedOperation {
operationId: string;
method: string;
path: string;
summary?: string;
description?: string;
deprecated?: boolean;
/** Set by the `x-hidden: true` vendor extension on the operation. Hidden ops are always removed by `filterOperations`. */
hidden?: boolean;
parameters: ParsedParameter[];
requestBody?: ParsedRequestBody;
responses: Record<string, ParsedResponse>;
security: OpenAPIV3.SecurityRequirementObject[];
tags: string[];
externalDocs?: ExternalDocs;
}
interface ParsedParameter {
name: string;
in: 'path' | 'query' | 'header' | 'cookie';
required: boolean;
description?: string;
schema: OpenAPIV3.SchemaObject;
example?: unknown;
examples?: Record<string, ParsedExample>;
deprecated?: boolean;
}
interface ParsedRequestBody {
required: boolean;
description?: string;
content: Record<string, {
schema: OpenAPIV3.SchemaObject;
example?: unknown;
examples?: Record<string, ParsedExample>;
}>;
}
interface ParsedSpec {
title: string;
version: string;
description?: string;
servers: ParsedServer[];
operations: ParsedOperation[];
schemas: Record<string, OpenAPIV3.SchemaObject>;
securitySchemes: Record<string, OpenAPIV3.SecuritySchemeObject>;
tags: ParsedTag[];
externalDocs?: ExternalDocs;
raw: OpenAPIV3.Document;
}
declare function resolveSpec(doc: OpenAPIV3.Document): Promise<ParsedSpec>;
interface OperationFilter {
include?: string[];
exclude?: string[];
}
interface OperationFilters {
tags?: OperationFilter;
operations?: OperationFilter;
}
/**
* Filter operations according to the provided rules.
*
* Precedence (first match wins):
* 1. `x-hidden: true` on the operation always removes it — spec author wins.
* 2. `operations.exclude` removes the operation unconditionally.
* 3. `operations.include` forces the operation through, even against `tags.exclude`.
* 4. `tags.exclude` removes the operation if any of its tags match.
* 5. When any include list is non-empty, only operations matching at least one include pass.
* 6. Otherwise, the operation passes.
*/
declare function filterOperations(operations: ParsedOperation[], filters?: OperationFilters): ParsedOperation[];
interface TokenExchangeRequestConfig {
method?: string;
contentType?: 'application/json' | 'application/x-www-form-urlencoded';
headers?: Record<string, string>;
fields?: Record<string, string | number | boolean>;
}
interface TokenExchangeResponseConfig {
tokenField?: string;
tokenTypeField?: string;
expiresInField?: string;
expiresAtField?: string;
}
interface TokenExchangeApplyConfig {
location?: 'header' | 'query' | 'cookie';
name?: string;
prefix?: string;
}
interface TokenExchangeAuthConfig {
tokenUrl: string;
request?: TokenExchangeRequestConfig;
response?: TokenExchangeResponseConfig;
apply?: TokenExchangeApplyConfig;
refreshBufferSeconds?: number;
defaultExpiresIn?: number;
}
interface AuthConfig {
bearerToken?: string;
apiKey?: string;
basicAuth?: {
username: string;
password: string;
};
oauth2?: {
clientId: string;
clientSecret: string;
tokenUrl: string;
scopes?: string[];
};
tokenExchange?: TokenExchangeAuthConfig;
custom?: (url: string, init: RequestInit) => RequestInit | Promise<RequestInit>;
}
interface ResolvedAuth {
apply(url: URL, init: RequestInit): Promise<RequestInit>;
refresh?(url: URL, init: RequestInit): Promise<RequestInit>;
}
declare function resolveAuth(config: AuthConfig | undefined, securitySchemes: Record<string, OpenAPIV3.SecuritySchemeObject>): ResolvedAuth | null;
type RetryPolicy = 'safe-only' | 'all' | 'none';
interface FetchWithRetryOptions {
timeout?: number;
retries?: number;
retryDelay?: number;
retryOn?: number[];
retryPolicy?: RetryPolicy;
}
declare function fetchWithRetry(url: string, init?: RequestInit, opts?: FetchWithRetryOptions): Promise<Response>;
interface HttpClientConfig {

@@ -239,3 +57,7 @@ baseUrl: string;

}
declare function buildBundle(options: BundleOptions): Promise<void>;
/**
* Build a standalone bash CLI around the shared dynamic-openapi-tools renderer
* and emit the same stderr summary the previous inline implementation printed.
*/
declare function buildBundle(options: BundleOptions): Promise<BuildBundleResult>;

@@ -270,2 +92,2 @@ interface BuildCliOptions {

export { type AuthConfig, type BuildCliOptions, type ExecutedRequest, type ExternalDocs, type FetchWithRetryOptions, type HttpClientConfig, type OperationFilter, type OperationFilters, type ParsedOperation, type ParsedParameter, type ParsedRequestBody, type ParsedResponse, type ParsedServer, type ParsedServerVariable, type ParsedSpec, type ParsedTag, RequestError, type ResolvedAuth, type RetryPolicy, type TokenExchangeApplyConfig, type TokenExchangeAuthConfig, type TokenExchangeRequestConfig, type TokenExchangeResponseConfig, ValidationError, buildBundle, buildCli, buildCommandsFromSpec, executeOperation, fetchWithRetry, filterOperations, loadSpec, resolveAuth, resolveBaseUrl, resolveServerUrl, resolveSource, resolveSpec, runCli };
export { type BuildCliOptions, type ExecutedRequest, type HttpClientConfig, RequestError, ValidationError, buildBundle, buildCli, buildCommandsFromSpec, executeOperation, resolveBaseUrl, resolveServerUrl, runCli };

@@ -1,810 +0,13 @@

// src/parser/loader.ts
import { readFile } from "fs/promises";
import { parse as parseYaml } from "yaml";
// src/index.ts
import {
loadSpec,
resolveSource,
resolveSpec,
filterOperations as filterOperations2
} from "dynamic-openapi-tools/parser";
import { resolveAuth as resolveAuth2 } from "dynamic-openapi-tools/auth";
import { fetchWithRetry as fetchWithRetry2 } from "dynamic-openapi-tools/utils";
// src/utils/fetch.ts
var DEFAULT_OPTIONS = {
timeout: 3e4,
retries: 3,
retryDelay: 1e3,
retryOn: [429, 500, 502, 503, 504],
retryPolicy: "safe-only"
};
async function fetchWithRetry(url, init, opts) {
const { timeout, retries, retryDelay, retryOn, retryPolicy } = { ...DEFAULT_OPTIONS, ...opts };
const canRetry = shouldRetry(init, retryPolicy);
let lastError;
for (let attempt = 0; attempt <= retries; attempt++) {
try {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeout);
const response = await fetch(url, {
...init,
signal: controller.signal
});
clearTimeout(timer);
if (retryOn.includes(response.status) && attempt < retries && canRetry) {
const retryAfter = response.headers.get("Retry-After");
const delay = retryAfter ? parseRetryAfter(retryAfter) : retryDelay * Math.pow(2, attempt);
await sleep(delay);
continue;
}
return response;
} catch (error) {
lastError = error instanceof Error ? error : new Error(String(error));
if (lastError.name === "AbortError") {
lastError = new Error(`Request timed out after ${timeout}ms: ${url}`);
}
if (attempt < retries && canRetry) {
await sleep(retryDelay * Math.pow(2, attempt));
continue;
}
break;
}
}
throw lastError ?? new Error(`Request failed after ${retries + 1} attempts: ${url}`);
}
function parseRetryAfter(value) {
const seconds = Number(value);
if (!Number.isNaN(seconds)) {
return Math.min(seconds * 1e3, 6e4);
}
const date = Date.parse(value);
if (!Number.isNaN(date)) {
return Math.min(Math.max(date - Date.now(), 0), 6e4);
}
return 1e3;
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function shouldRetry(init, retryPolicy) {
switch (retryPolicy) {
case "all":
return true;
case "none":
return false;
case "safe-only":
return SAFE_METHODS.has((init?.method ?? "GET").toUpperCase());
}
}
var SAFE_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS", "TRACE"]);
// src/parser/loader.ts
function resolveSource(source) {
if (typeof source !== "string") {
return { type: "inline", value: source };
}
if (source.startsWith("http://") || source.startsWith("https://")) {
return { type: "url", value: source };
}
if (source.trim().startsWith("{") || source.trim().startsWith("openapi")) {
return { type: "inline", value: source };
}
return { type: "file", value: source };
}
async function loadSpec(source) {
const resolved = resolveSource(source);
switch (resolved.type) {
case "url": {
const res = await fetchWithRetry(resolved.value);
if (!res.ok) {
throw new Error(`Failed to fetch spec from ${resolved.value}: ${res.status} ${res.statusText}`);
}
const text = await res.text();
return parseSpecText(text, resolved.value);
}
case "file": {
let text;
try {
text = await readFile(resolved.value, "utf-8");
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
throw new Error(`Failed to read spec file "${resolved.value}": ${msg}`);
}
return parseSpecText(text, resolved.value);
}
case "inline": {
if (typeof resolved.value === "string") {
return parseSpecText(resolved.value, "(inline)");
}
return resolved.value;
}
}
}
function parseSpecText(text, source) {
const trimmed = text.trim();
if (trimmed.startsWith("{")) {
try {
return JSON.parse(trimmed);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
throw new Error(`Failed to parse JSON spec from ${source}: ${msg}`);
}
}
try {
return parseYaml(trimmed);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
throw new Error(`Failed to parse YAML spec from ${source}: ${msg}`);
}
}
// src/parser/resolver.ts
import { validate, dereference } from "@readme/openapi-parser";
async function resolveSpec(doc) {
const validation = await validate(structuredClone(doc));
if (!validation.valid) {
const validationResult = validation;
const errors = validationResult.errors ?? [];
throw new Error(`Invalid OpenAPI spec: ${JSON.stringify(errors)}`);
}
const dereferenced = await dereference(structuredClone(doc));
const operations = extractOperations(dereferenced);
const schemas = extractSchemas(dereferenced);
const securitySchemes = extractSecuritySchemes(dereferenced);
const servers = extractServers(dereferenced);
const tags = extractTags(dereferenced);
const externalDocs = extractExternalDocs(dereferenced.externalDocs);
return {
title: dereferenced.info.title,
version: dereferenced.info.version,
description: dereferenced.info.description,
servers,
operations,
schemas,
securitySchemes,
tags,
externalDocs,
raw: dereferenced
};
}
var HTTP_METHODS = ["get", "post", "put", "delete", "patch", "head", "options", "trace"];
function extractOperations(doc) {
const operations = [];
const paths = doc.paths ?? {};
for (const [path2, pathItem] of Object.entries(paths)) {
if (!pathItem) continue;
const pathParams = pathItem.parameters ?? [];
for (const method of HTTP_METHODS) {
const operation = pathItem[method];
if (!operation) continue;
const operationParams = operation.parameters ?? [];
const allParams = mergeParameters(pathParams, operationParams);
const operationId = operation.operationId ?? generateOperationId(method, path2);
const parameters = allParams.map((p) => ({
name: p.name,
in: p.in,
required: p.required ?? p.in === "path",
description: p.description,
schema: p.schema ?? { type: "string" },
example: p.example,
examples: p.examples ? extractExamples(p.examples) : void 0,
deprecated: p.deprecated
}));
let requestBody;
if (operation.requestBody) {
const rb = operation.requestBody;
const content = {};
for (const [mediaType, mediaObj] of Object.entries(rb.content ?? {})) {
if (mediaObj.schema) {
content[mediaType] = {
schema: mediaObj.schema,
example: mediaObj.example,
examples: mediaObj.examples ? extractExamples(mediaObj.examples) : void 0
};
}
}
requestBody = {
required: rb.required ?? false,
description: rb.description,
content
};
}
const responses = {};
for (const [code, resp] of Object.entries(operation.responses ?? {})) {
responses[code] = extractResponse(resp);
}
operations.push({
operationId,
method: method.toUpperCase(),
path: path2,
summary: operation.summary,
description: operation.description,
deprecated: operation.deprecated,
hidden: operation["x-hidden"] === true,
parameters,
requestBody,
responses,
security: operation.security ?? doc.security ?? [],
tags: operation.tags ?? [],
externalDocs: extractExternalDocs(operation.externalDocs)
});
}
}
return operations;
}
function extractResponse(resp) {
const parsed = {
description: resp.description ?? "",
content: {}
};
if (resp.content) {
for (const [mediaType, mediaObj] of Object.entries(resp.content)) {
parsed.content[mediaType] = {
schema: mediaObj.schema
};
if (!parsed.schema && mediaObj.schema) {
parsed.schema = mediaObj.schema;
parsed.mediaType = mediaType;
}
if (parsed.example === void 0 && mediaObj.example !== void 0) {
parsed.example = mediaObj.example;
}
if (!parsed.examples && mediaObj.examples) {
parsed.examples = extractExamples(mediaObj.examples);
}
}
}
if (resp.links) {
parsed.links = extractLinks(resp.links);
}
return parsed;
}
function extractExamples(examples) {
const result = {};
for (const [name, ex] of Object.entries(examples)) {
result[name] = {
summary: ex.summary,
description: ex.description,
value: ex.value
};
}
return result;
}
function extractLinks(links) {
const result = {};
for (const [name, link] of Object.entries(links)) {
result[name] = {
operationId: link.operationId,
operationRef: link.operationRef,
parameters: link.parameters,
description: link.description
};
}
return result;
}
function generateOperationId(method, path2) {
const cleaned = path2.replace(/\{([^}]+)\}/g, "by_$1").replace(/[^a-zA-Z0-9]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
return `${method}_${cleaned}`.toLowerCase();
}
function mergeParameters(pathParams, operationParams) {
const merged = /* @__PURE__ */ new Map();
for (const p of pathParams) {
merged.set(`${p.in}:${p.name}`, p);
}
for (const p of operationParams) {
merged.set(`${p.in}:${p.name}`, p);
}
return Array.from(merged.values());
}
function extractSchemas(doc) {
const schemas = {};
const components = doc.components?.schemas ?? {};
for (const [name, schema] of Object.entries(components)) {
schemas[name] = schema;
}
return schemas;
}
function extractSecuritySchemes(doc) {
const schemes = {};
const components = doc.components?.securitySchemes ?? {};
for (const [name, scheme] of Object.entries(components)) {
schemes[name] = scheme;
}
return schemes;
}
function extractServers(doc) {
return (doc.servers ?? []).map((s) => {
const server = { url: s.url };
if (s.description) server.description = s.description;
if (s.variables) {
server.variables = {};
for (const [name, v] of Object.entries(s.variables)) {
server.variables[name] = {
default: v.default,
enum: v.enum,
description: v.description
};
}
}
return server;
});
}
function extractTags(doc) {
return (doc.tags ?? []).map((t) => {
const tag = { name: t.name };
if (t.description) tag.description = t.description;
if (t.externalDocs) {
tag.externalDocs = {
url: t.externalDocs.url,
description: t.externalDocs.description
};
}
return tag;
});
}
function extractExternalDocs(docs) {
if (!docs) return void 0;
return {
url: docs.url,
description: docs.description
};
}
// src/parser/filter.ts
function filterOperations(operations, filters) {
const tagInclude = filters?.tags?.include ?? [];
const tagExclude = filters?.tags?.exclude ?? [];
const opInclude = filters?.operations?.include ?? [];
const opExclude = filters?.operations?.exclude ?? [];
const hasInclude = tagInclude.length > 0 || opInclude.length > 0;
return operations.filter((op) => {
if (op.hidden) return false;
if (opExclude.includes(op.operationId)) return false;
if (opInclude.includes(op.operationId)) return true;
const opTags = op.tags ?? [];
if (tagExclude.length > 0 && opTags.some((t) => tagExclude.includes(t))) {
return false;
}
if (!hasInclude) return true;
return opTags.some((t) => tagInclude.includes(t));
});
}
// src/auth/strategies.ts
var BearerAuth = class {
constructor(token) {
this.token = token;
}
token;
async apply(_url, init) {
const headers = new Headers(init.headers);
headers.set("Authorization", `Bearer ${this.token}`);
return { ...init, headers };
}
};
var ApiKeyAuth = class {
constructor(key, paramName, location) {
this.key = key;
this.paramName = paramName;
this.location = location;
}
key;
paramName;
location;
async apply(url, init) {
switch (this.location) {
case "header": {
const headers = new Headers(init.headers);
headers.set(this.paramName, this.key);
return { ...init, headers };
}
case "query": {
url.searchParams.set(this.paramName, this.key);
return init;
}
case "cookie": {
const headers = new Headers(init.headers);
setCookieValue(headers, this.paramName, this.key);
return { ...init, headers };
}
}
}
};
var BasicAuth = class {
constructor(username, password) {
this.username = username;
this.password = password;
}
username;
password;
async apply(_url, init) {
const credentials = `${this.username}:${this.password}`;
const encoded = Buffer.from(credentials, "utf-8").toString("base64");
const headers = new Headers(init.headers);
headers.set("Authorization", `Basic ${encoded}`);
return { ...init, headers };
}
};
var OAuth2ClientCredentials = class {
constructor(clientId, clientSecret, tokenUrl, scopes = []) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.tokenUrl = tokenUrl;
this.scopes = scopes;
}
clientId;
clientSecret;
tokenUrl;
scopes;
tokenCache = null;
pendingRefresh = null;
async apply(_url, init) {
const token = await this.getToken();
const headers = new Headers(init.headers);
headers.set("Authorization", `Bearer ${token}`);
return { ...init, headers };
}
async refresh(_url, init) {
this.tokenCache = null;
const token = await this.getToken();
const headers = new Headers(init.headers);
headers.set("Authorization", `Bearer ${token}`);
return { ...init, headers };
}
async getToken() {
if (this.tokenCache && Date.now() < this.tokenCache.expiresAt) {
return this.tokenCache.token;
}
if (this.pendingRefresh) {
return this.pendingRefresh;
}
this.pendingRefresh = this.fetchToken();
try {
return await this.pendingRefresh;
} finally {
this.pendingRefresh = null;
}
}
async fetchToken() {
const body = new URLSearchParams({
grant_type: "client_credentials",
client_id: this.clientId,
client_secret: this.clientSecret
});
if (this.scopes.length > 0) {
body.set("scope", this.scopes.join(" "));
}
const res = await fetchWithRetry(this.tokenUrl, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body
}, { retries: 2, timeout: 15e3 });
if (!res.ok) {
const errorBody = await res.text().catch(() => "");
throw new Error(
`OAuth2 token request failed: ${res.status} ${res.statusText}${errorBody ? ` - ${errorBody}` : ""}`
);
}
let data;
try {
data = await res.json();
} catch {
throw new Error("OAuth2 token response is not valid JSON");
}
if (typeof data.access_token !== "string" || !data.access_token) {
throw new Error('OAuth2 token response missing "access_token" field');
}
const expiresIn = typeof data.expires_in === "number" ? data.expires_in : 3600;
const bufferSeconds = Math.min(60, expiresIn * 0.1);
this.tokenCache = {
token: data.access_token,
expiresAt: Date.now() + (expiresIn - bufferSeconds) * 1e3
};
return data.access_token;
}
};
var TokenExchangeAuth = class {
constructor(config) {
this.config = config;
}
config;
tokenCache = null;
pendingRefresh = null;
async apply(url, init) {
const token = await this.getToken();
return applyTokenValue(url, init, token, this.config.apply);
}
async refresh(url, init) {
this.tokenCache = null;
const token = await this.getToken();
return applyTokenValue(url, init, token, this.config.apply);
}
async getToken() {
if (this.tokenCache && Date.now() < this.tokenCache.expiresAt) {
return this.tokenCache;
}
if (this.pendingRefresh) {
return this.pendingRefresh;
}
this.pendingRefresh = this.fetchToken();
try {
return await this.pendingRefresh;
} finally {
this.pendingRefresh = null;
}
}
async fetchToken() {
const request = this.config.request ?? {};
const method = request.method?.toUpperCase() ?? "POST";
const url = new URL(this.config.tokenUrl);
const headers = new Headers(request.headers);
let body;
if (request.fields && Object.keys(request.fields).length > 0) {
if (method === "GET" || method === "HEAD") {
for (const [key, value] of Object.entries(request.fields)) {
url.searchParams.set(key, String(value));
}
} else {
const contentType = request.contentType ?? "application/json";
headers.set("Content-Type", contentType);
if (contentType === "application/x-www-form-urlencoded") {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(request.fields)) {
params.set(key, String(value));
}
body = params;
} else {
body = JSON.stringify(request.fields);
}
}
}
const res = await fetchWithRetry(url.toString(), {
method,
headers,
body
}, { retries: 2, timeout: 15e3, retryPolicy: "all" });
if (!res.ok) {
const errorBody = await res.text().catch(() => "");
throw new Error(
`Token exchange request failed: ${res.status} ${res.statusText}${errorBody ? ` - ${errorBody}` : ""}`
);
}
let data;
try {
data = await res.json();
} catch {
throw new Error("Token exchange response is not valid JSON");
}
const responseConfig = this.config.response ?? {};
const tokenValue = getValueAtPath(data, responseConfig.tokenField ?? "access_token");
if (typeof tokenValue !== "string" || !tokenValue) {
throw new Error(`Token exchange response missing "${responseConfig.tokenField ?? "access_token"}" field`);
}
const tokenTypeValue = getValueAtPath(data, responseConfig.tokenTypeField ?? "token_type");
const tokenType = typeof tokenTypeValue === "string" && tokenTypeValue ? normalizeSchemeName(tokenTypeValue) : void 0;
const token = {
token: tokenValue,
tokenType,
expiresAt: resolveTokenExpiry(data, this.config)
};
this.tokenCache = token;
return token;
}
};
var CustomAuth = class {
constructor(handler) {
this.handler = handler;
}
handler;
async apply(url, init) {
return this.handler(url.toString(), init);
}
};
var CompositeAuth = class {
constructor(strategies) {
this.strategies = strategies;
}
strategies;
async apply(url, init) {
let result = init;
for (const strategy of this.strategies) {
result = await strategy.apply(url, result);
}
return result;
}
async refresh(url, init) {
let result = init;
for (const strategy of this.strategies) {
if (strategy.refresh) {
result = await strategy.refresh(url, result);
} else {
result = await strategy.apply(url, result);
}
}
return result;
}
};
function createAuthFromScheme(scheme, credential) {
switch (scheme.type) {
case "http": {
if (scheme.scheme === "bearer") {
return new BearerAuth(credential);
}
if (scheme.scheme === "basic") {
const colonIndex = credential.indexOf(":");
if (colonIndex === -1) {
return new BasicAuth(credential, "");
}
return new BasicAuth(credential.slice(0, colonIndex), credential.slice(colonIndex + 1));
}
return null;
}
case "apiKey": {
const location = scheme.in;
if (!["header", "query", "cookie"].includes(location)) {
return new ApiKeyAuth(credential, scheme.name, "header");
}
return new ApiKeyAuth(credential, scheme.name, location);
}
default:
return null;
}
}
function applyTokenValue(url, init, token, applyConfig) {
const location = applyConfig?.location ?? "header";
const name = applyConfig?.name ?? (location === "header" ? "Authorization" : "access_token");
const prefix = applyConfig?.prefix ?? (location === "header" && name.toLowerCase() === "authorization" ? `${token.tokenType ?? "Bearer"} ` : "");
const value = `${prefix}${token.token}`;
switch (location) {
case "header": {
const headers = new Headers(init.headers);
headers.set(name, value);
return { ...init, headers };
}
case "query": {
url.searchParams.set(name, value);
return init;
}
case "cookie": {
const headers = new Headers(init.headers);
setCookieValue(headers, name, value);
return { ...init, headers };
}
}
}
function getValueAtPath(value, path2) {
return path2.split(".").reduce((current, segment) => {
if (current && typeof current === "object" && segment in current) {
return current[segment];
}
return void 0;
}, value);
}
function resolveTokenExpiry(data, config) {
const response = config.response ?? {};
const now = Date.now();
if (response.expiresAtField) {
const expiresAt = parseAbsoluteTimestamp(getValueAtPath(data, response.expiresAtField));
if (expiresAt !== null) {
return applyRefreshBuffer(expiresAt, now, config.refreshBufferSeconds);
}
}
const expiresInValue = getValueAtPath(data, response.expiresInField ?? "expires_in");
const expiresIn = parseDurationSeconds(expiresInValue) ?? config.defaultExpiresIn;
if (expiresIn === void 0) {
return Number.POSITIVE_INFINITY;
}
const bufferSeconds = config.refreshBufferSeconds ?? Math.min(60, Math.max(5, expiresIn * 0.1));
return now + Math.max(expiresIn - bufferSeconds, 0) * 1e3;
}
function parseDurationSeconds(value) {
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
return value;
}
if (typeof value === "string" && value.trim() !== "") {
const parsed = Number(value);
if (Number.isFinite(parsed) && parsed >= 0) {
return parsed;
}
}
return null;
}
function parseAbsoluteTimestamp(value) {
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
return value > 1e12 ? value : value * 1e3;
}
if (typeof value === "string" && value.trim() !== "") {
const numeric = Number(value);
if (Number.isFinite(numeric) && numeric > 0) {
return numeric > 1e12 ? numeric : numeric * 1e3;
}
const parsed = Date.parse(value);
if (!Number.isNaN(parsed)) {
return parsed;
}
}
return null;
}
function applyRefreshBuffer(expiresAt, now, configuredBufferSeconds) {
const secondsUntilExpiry = Math.max((expiresAt - now) / 1e3, 0);
const bufferSeconds = configuredBufferSeconds ?? Math.min(60, Math.max(5, secondsUntilExpiry * 0.1));
return Math.max(now, expiresAt - bufferSeconds * 1e3);
}
function normalizeSchemeName(value) {
if (!value) return value;
return value.charAt(0).toUpperCase() + value.slice(1);
}
function setCookieValue(headers, name, value) {
const encodedName = encodeURIComponent(name);
const encodedValue = encodeURIComponent(value);
const existing = headers.get("Cookie");
if (!existing) {
headers.set("Cookie", `${encodedName}=${encodedValue}`);
return;
}
const parts = existing.split(";").map((part) => part.trim()).filter(Boolean);
const withoutTarget = parts.filter((part) => !part.startsWith(`${encodedName}=`));
withoutTarget.push(`${encodedName}=${encodedValue}`);
headers.set("Cookie", withoutTarget.join("; "));
}
// src/auth/resolver.ts
function resolveAuth(config, securitySchemes) {
const strategies = [];
if (config?.custom) {
return new CustomAuth(config.custom);
}
if (config?.bearerToken) {
strategies.push(new BearerAuth(config.bearerToken));
}
if (config?.apiKey) {
const apiKeyScheme = Object.values(securitySchemes).find(
(s) => s.type === "apiKey"
);
if (apiKeyScheme) {
strategies.push(new ApiKeyAuth(config.apiKey, apiKeyScheme.name, apiKeyScheme.in));
} else {
strategies.push(new ApiKeyAuth(config.apiKey, "X-API-Key", "header"));
}
}
if (config?.basicAuth) {
strategies.push(new BasicAuth(config.basicAuth.username, config.basicAuth.password));
}
if (config?.oauth2) {
strategies.push(
new OAuth2ClientCredentials(
config.oauth2.clientId,
config.oauth2.clientSecret,
config.oauth2.tokenUrl,
config.oauth2.scopes
)
);
}
if (config?.tokenExchange) {
strategies.push(new TokenExchangeAuth(config.tokenExchange));
}
if (strategies.length > 0) {
return strategies.length === 1 ? strategies[0] : new CompositeAuth(strategies);
}
return resolveAuthFromEnv(securitySchemes);
}
function resolveAuthFromEnv(securitySchemes) {
for (const [name, scheme] of Object.entries(securitySchemes)) {
const envName = name.toUpperCase().replace(/[^A-Z0-9]/g, "_");
const envToken = process.env[`OPENAPI_AUTH_${envName}_TOKEN`] ?? process.env[`OPENAPI_AUTH_${envName}_KEY`];
if (envToken) {
const auth = createAuthFromScheme(scheme, envToken);
if (auth) return auth;
}
}
const globalToken = process.env["OPENAPI_AUTH_TOKEN"];
if (globalToken) {
return new BearerAuth(globalToken);
}
const globalApiKey = process.env["OPENAPI_API_KEY"];
if (globalApiKey) {
const apiKeyScheme = Object.values(securitySchemes).find(
(s) => s.type === "apiKey"
);
if (apiKeyScheme) {
return new ApiKeyAuth(globalApiKey, apiKeyScheme.name, apiKeyScheme.in);
}
return new ApiKeyAuth(globalApiKey, "X-API-Key", "header");
}
return null;
}
// src/http/client.ts
import { fetchWithRetry } from "dynamic-openapi-tools/utils";
var RequestError = class extends Error {

@@ -1113,13 +316,4 @@ constructor(message, cause) {

// src/utils/naming.ts
function sanitizeToolName(name) {
return name.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").slice(0, 64);
}
function truncateDescription(text, maxLength = 200) {
if (!text) return "";
if (text.length <= maxLength) return text;
return text.slice(0, maxLength - 3) + "...";
}
// src/cli/command-builder.ts
import { sanitizeToolName, truncateDescription } from "dynamic-openapi-tools/utils";
function buildCommandsFromSpec(spec, options) {

@@ -1288,390 +482,28 @@ const commands = {};

// src/cli/bundle.ts
import { createHash } from "crypto";
import { chmod, writeFile } from "fs/promises";
import path from "path";
import { createParser } from "cli-args-parser";
import { createParser } from "dynamic-openapi-tools/cli";
import { buildBundle as toolsBuildBundle } from "dynamic-openapi-tools/bundle";
var RUNNER_PACKAGE = "dynamic-openapi-cli";
var KIND_LABEL = "CLI";
var RUNNER_INVOCATION = '--spec "$SPEC_FILE" --name "$CLI_NAME" --app-version "$CLI_VERSION" "${PASSTHROUGH[@]}"';
var INSTALL_SUCCESS_HINT = "Run: %s --help";
async function buildBundle(options) {
const doc = await loadSpec(options.source);
const spec = await resolveSpec(doc);
const json = JSON.stringify(spec.raw);
const base64 = Buffer.from(json, "utf-8").toString("base64");
const md5 = createHash("md5").update(json).digest("hex");
const cliName = options.name;
const cliVersion = options.appVersion ?? spec.version;
const cliDescription = options.description ?? spec.title;
const specSource = computeSpecSource(options.source);
const script = renderShim({
cliName,
cliVersion,
cliDescription,
specSource,
base64,
md5
const result = await toolsBuildBundle({
source: options.source,
name: options.name,
out: options.out,
appVersion: options.appVersion,
description: options.description,
runnerPackage: RUNNER_PACKAGE,
kindLabel: KIND_LABEL,
runnerInvocation: RUNNER_INVOCATION,
installSuccessHint: INSTALL_SUCCESS_HINT
});
await writeFile(options.out, script, "utf-8");
await chmod(options.out, 493);
const bytes = Buffer.byteLength(script, "utf-8");
const updateHint = specSource.kind === "inline" ? " (update: unavailable \u2014 inline spec)" : "";
const updateHint = result.specSource.kind === "inline" ? " (update: unavailable \u2014 inline spec)" : "";
process.stderr.write(
`bundled "${cliName}" v${cliVersion} \u2192 ${options.out} (${formatBytes(bytes)}, ${spec.operations.length} operations)${updateHint}
`bundled "${options.name}" v${result.version} \u2192 ${options.out} (${formatBytes(result.bytes)}, ${result.operations} operations)${updateHint}
`
);
return result;
}
function computeSpecSource(source) {
const resolved = resolveSource(source);
switch (resolved.type) {
case "url":
return { kind: "url", value: resolved.value };
case "file":
return { kind: "file", value: path.resolve(resolved.value) };
case "inline":
return { kind: "inline", value: "" };
}
}
function renderShim(params) {
const { cliName, cliVersion, cliDescription, specSource, base64, md5 } = params;
const safeName = shellSingleQuote(cliName);
const safeVersion = shellSingleQuote(cliVersion);
const safeDescription = shellSingleQuote(cliDescription);
const safeSpecSource = shellSingleQuote(specSource.value);
const specSourceKind = shellSingleQuote(specSource.kind);
const safeMd5 = shellSingleQuote(md5);
return `#!/usr/bin/env bash
# Generated by dynamic-openapi-cli
# Generator: dynamic-openapi-cli
# CLI name: ${cliName}
# Version: ${cliVersion}
# Spec source: ${specSource.kind === "inline" ? "(inline \u2014 update unavailable)" : specSource.value}
# Spec MD5: ${md5}
# Spec: embedded as base64-encoded JSON (dereferenced OpenAPI v3)
set -euo pipefail
CLI_NAME=${safeName}
CLI_VERSION=${safeVersion}
CLI_DESCRIPTION=${safeDescription}
SPEC_SOURCE=${safeSpecSource}
SPEC_SOURCE_KIND=${specSourceKind}
SPEC_MD5=${safeMd5}
SPEC_B64='${base64}'
_self_path() {
local src="\${BASH_SOURCE[0]}"
local dir
dir="$(cd "$(dirname "$src")" && pwd)"
printf '%s/%s' "$dir" "$(basename "$src")"
}
_resolve_runner() {
if command -v dynamic-openapi-cli >/dev/null 2>&1; then
printf 'dynamic-openapi-cli\\n'
return 0
fi
if command -v npx >/dev/null 2>&1; then
printf 'npx --yes dynamic-openapi-cli\\n'
return 0
fi
printf >&2 'Error: neither dynamic-openapi-cli nor npx was found on PATH.\\n'
printf >&2 ' Install with: npm install -g dynamic-openapi-cli\\n'
printf >&2 ' Or install Node.js (>= 18): https://nodejs.org\\n'
return 127
}
if [[ "\${1:-}" == "--show-spec" ]]; then
printf '%s' "$SPEC_B64" | base64 -d
printf '\\n'
exit 0
fi
if [[ "\${1:-}" == "--spec-md5" ]]; then
printf '%s\\n' "$SPEC_MD5"
exit 0
fi
_default_install_dir() {
if [[ -n "\${XDG_BIN_HOME:-}" ]]; then
printf '%s' "$XDG_BIN_HOME"
else
printf '%s/.local/bin' "\${HOME:-~}"
fi
}
_is_in_path() {
local dir="$1"
case ":$PATH:" in
*":$dir:"*) return 0 ;;
*) return 1 ;;
esac
}
if [[ "\${1:-}" == "install" ]]; then
shift
TARGET_DIR="$(_default_install_dir)"
MODE="symlink"
FORCE=0
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
printf 'Usage: %s install [--dir <path>] [--copy] [--force]\\n' "$CLI_NAME"
printf '\\n'
printf 'Installs this CLI into a directory on your PATH.\\n'
printf '\\n'
printf 'Options:\\n'
printf ' --dir <path> Target directory (default: \\$XDG_BIN_HOME or \\$HOME/.local/bin)\\n'
printf ' --copy Copy the file instead of creating a symlink\\n'
printf ' --force Overwrite an existing file at the destination\\n'
exit 0
;;
--dir) TARGET_DIR="$2"; shift 2 ;;
--dir=*) TARGET_DIR="\${1#--dir=}"; shift ;;
--copy) MODE="copy"; shift ;;
--force) FORCE=1; shift ;;
*)
printf >&2 '%s install: unknown argument: %s\\n' "$CLI_NAME" "$1"
exit 2
;;
esac
done
SELF="$(_self_path)"
mkdir -p "$TARGET_DIR"
LINK="$TARGET_DIR/$CLI_NAME"
if [[ -e "$LINK" || -L "$LINK" ]]; then
if [[ "$FORCE" -ne 1 ]]; then
printf >&2 '%s install: %s already exists. Pass --force to overwrite.\\n' "$CLI_NAME" "$LINK"
exit 1
fi
rm -f "$LINK"
fi
if [[ "$MODE" == "copy" ]]; then
cp "$SELF" "$LINK"
chmod +x "$LINK"
printf >&2 '%s install: copied to %s\\n' "$CLI_NAME" "$LINK"
else
ln -s "$SELF" "$LINK"
printf >&2 '%s install: symlinked %s \u2192 %s\\n' "$CLI_NAME" "$LINK" "$SELF"
fi
if ! _is_in_path "$TARGET_DIR"; then
printf >&2 '\\n'
printf >&2 '%s install: warning \u2014 %s is not on your PATH yet.\\n' "$CLI_NAME" "$TARGET_DIR"
printf >&2 ' Add this line to your shell rc (~/.bashrc, ~/.zshrc, or equivalent):\\n'
printf >&2 '\\n'
printf >&2 ' export PATH="%s:$PATH"\\n' "$TARGET_DIR"
printf >&2 '\\n'
printf >&2 ' Then run: exec $SHELL (or open a new terminal)\\n'
else
printf >&2 ' Run: %s --help\\n' "$CLI_NAME"
fi
exit 0
fi
if [[ "\${1:-}" == "uninstall" ]]; then
shift
TARGET_DIR="$(_default_install_dir)"
FORCE=0
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
printf 'Usage: %s uninstall [--dir <path>] [--force]\\n' "$CLI_NAME"
exit 0
;;
--dir) TARGET_DIR="$2"; shift 2 ;;
--dir=*) TARGET_DIR="\${1#--dir=}"; shift ;;
--force) FORCE=1; shift ;;
*)
printf >&2 '%s uninstall: unknown argument: %s\\n' "$CLI_NAME" "$1"
exit 2
;;
esac
done
SELF="$(_self_path)"
LINK="$TARGET_DIR/$CLI_NAME"
if [[ ! -e "$LINK" && ! -L "$LINK" ]]; then
printf >&2 '%s uninstall: %s does not exist.\\n' "$CLI_NAME" "$LINK"
exit 1
fi
if [[ "$FORCE" -ne 1 ]]; then
if [[ -L "$LINK" ]]; then
RESOLVED="$(readlink "$LINK" 2>/dev/null || true)"
if [[ "$RESOLVED" != "$SELF" ]]; then
printf >&2 '%s uninstall: %s is a symlink to %s, not to this CLI. Pass --force to remove anyway.\\n' \\
"$CLI_NAME" "$LINK" "$RESOLVED"
exit 1
fi
elif ! cmp -s "$LINK" "$SELF"; then
printf >&2 '%s uninstall: %s differs from this CLI. Pass --force to remove anyway.\\n' "$CLI_NAME" "$LINK"
exit 1
fi
fi
rm -f "$LINK"
printf >&2 '%s uninstall: removed %s\\n' "$CLI_NAME" "$LINK"
exit 0
fi
if [[ "\${1:-}" == "update" ]]; then
shift
UPDATE_SPEC=""
UPDATE_VERSION_OVERRIDE=""
UPDATE_VERSION_SET=0
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
printf 'Usage: %s update [--spec <url|file>] [--app-version <version>]\\n' "$CLI_NAME"
printf '\\n'
printf 'Re-fetches the original spec and rewrites this CLI in-place.\\n'
printf '\\n'
printf 'By default, the new CLI_VERSION tracks the spec.info.version of the freshly\\n'
printf 'fetched spec \u2014 the bundled version is a snapshot of the API, not of the CLI.\\n'
printf '\\n'
printf 'Options:\\n'
printf ' --spec <url|file> Use a different spec source (default: the one baked in at bundle time)\\n'
printf ' --app-version <version> Override the version written to the new shim\\n'
exit 0
;;
--spec)
if [[ $# -lt 2 ]]; then
printf >&2 '%s update: --spec requires a value\\n' "$CLI_NAME"
exit 2
fi
UPDATE_SPEC="$2"
shift 2
;;
--spec=*)
UPDATE_SPEC="\${1#--spec=}"
shift
;;
--app-version)
if [[ $# -lt 2 ]]; then
printf >&2 '%s update: --app-version requires a value\\n' "$CLI_NAME"
exit 2
fi
UPDATE_VERSION_OVERRIDE="$2"
UPDATE_VERSION_SET=1
shift 2
;;
--app-version=*)
UPDATE_VERSION_OVERRIDE="\${1#--app-version=}"
UPDATE_VERSION_SET=1
shift
;;
*)
printf >&2 '%s update: unknown argument: %s\\n' "$CLI_NAME" "$1"
exit 2
;;
esac
done
UPDATE_SOURCE="\${UPDATE_SPEC:-$SPEC_SOURCE}"
if [[ -z "$UPDATE_SOURCE" ]]; then
printf >&2 '%s update: this CLI was bundled from an inline spec \u2014 no remote source to refresh.\\n' "$CLI_NAME"
printf >&2 ' Pass --spec <url|file> to update, or re-run "dynamic-openapi-cli bundle" manually.\\n'
exit 1
fi
if [[ "$SPEC_SOURCE_KIND" == "file" && -z "$UPDATE_SPEC" && ! -e "$UPDATE_SOURCE" ]]; then
printf >&2 '%s update: baked-in spec file not found: %s\\n' "$CLI_NAME" "$UPDATE_SOURCE"
printf >&2 ' Pass --spec <url|file> to override.\\n'
exit 1
fi
RUNNER_STR="$(_resolve_runner)" || exit $?
read -r -a RUNNER <<< "$RUNNER_STR"
SELF="$(_self_path)"
TMP="\${SELF}.update.$$"
trap 'rm -f "$TMP"' EXIT
VERSION_ARGS=()
if [[ "$UPDATE_VERSION_SET" -eq 1 ]]; then
VERSION_ARGS=(--app-version "$UPDATE_VERSION_OVERRIDE")
fi
printf >&2 '%s update: fetching %s ...\\n' "$CLI_NAME" "$UPDATE_SOURCE"
if ! "\${RUNNER[@]}" bundle \\
--source "$UPDATE_SOURCE" \\
--name "$CLI_NAME" \\
"\${VERSION_ARGS[@]}" \\
--out "$TMP"; then
printf >&2 '%s update: bundle failed, CLI not modified.\\n' "$CLI_NAME"
exit 1
fi
NEW_VERSION="$(grep -m1 "^CLI_VERSION=" "$TMP" 2>/dev/null | sed -E "s/^CLI_VERSION='(.*)'$/\\1/")"
[[ -z "$NEW_VERSION" ]] && NEW_VERSION="unknown"
NEW_MD5="$(grep -m1 "^SPEC_MD5=" "$TMP" 2>/dev/null | sed -E "s/^SPEC_MD5='(.*)'$/\\1/")"
[[ -z "$NEW_MD5" ]] && NEW_MD5="unknown"
mv "$TMP" "$SELF"
chmod +x "$SELF"
trap - EXIT
if [[ "$NEW_MD5" == "$SPEC_MD5" ]]; then
printf >&2 '%s update: spec unchanged (md5 %s), %s is up to date at version %s.\\n' \\
"$CLI_NAME" "\${NEW_MD5:0:8}" "$SELF" "$NEW_VERSION"
else
printf >&2 '%s update: spec changed (md5 %s \u2192 %s), %s %s \u2192 %s.\\n' \\
"$CLI_NAME" "\${SPEC_MD5:0:8}" "\${NEW_MD5:0:8}" "$SELF" "$CLI_VERSION" "$NEW_VERSION"
fi
exit 0
fi
SPEC_OVERRIDE=""
PASSTHROUGH=()
while [[ $# -gt 0 ]]; do
case "$1" in
--spec)
if [[ $# -lt 2 ]]; then
printf >&2 '%s: --spec requires a value\\n' "$CLI_NAME"
exit 2
fi
SPEC_OVERRIDE="$2"
shift 2
;;
--spec=*)
SPEC_OVERRIDE="\${1#--spec=}"
shift
;;
--)
shift
while [[ $# -gt 0 ]]; do
PASSTHROUGH+=("$1")
shift
done
;;
*)
PASSTHROUGH+=("$1")
shift
;;
esac
done
if [[ -n "$SPEC_OVERRIDE" ]]; then
SPEC_FILE="$SPEC_OVERRIDE"
else
SPEC_FILE="$(mktemp -t "\${CLI_NAME}.XXXXXX.json")"
trap 'rm -f "$SPEC_FILE"' EXIT
printf '%s' "$SPEC_B64" | base64 -d > "$SPEC_FILE"
fi
RUNNER_STR="$(_resolve_runner)" || exit $?
read -r -a RUNNER <<< "$RUNNER_STR"
exec "\${RUNNER[@]}" \\
--spec "$SPEC_FILE" \\
--name "$CLI_NAME" \\
--app-version "$CLI_VERSION" \\
"\${PASSTHROUGH[@]}"
`;
}
function shellSingleQuote(value) {
return `'${value.replace(/'/g, `'\\''`)}'`;
}
function formatBytes(bytes) {

@@ -1684,7 +516,9 @@ if (bytes < 1024) return `${bytes} B`;

// src/cli/app.ts
import { readFile as readFile2 } from "fs/promises";
import { createCLI, formatErrors } from "cli-args-parser";
import { readFile } from "fs/promises";
import { createCLI, formatErrors } from "dynamic-openapi-tools/cli";
import { resolveAuth } from "dynamic-openapi-tools/auth";
import { filterOperations } from "dynamic-openapi-tools/parser";
// src/cli/output.ts
import { writeFile as writeFile2 } from "fs/promises";
import { writeFile } from "fs/promises";
var INLINE_BINARY_LIMIT = 256 * 1024;

@@ -1705,3 +539,3 @@ async function renderResponse(response, options = {}) {

const bytes2 = new Uint8Array(await response.arrayBuffer());
await writeFile2(options.outputFile, bytes2);
await writeFile(options.outputFile, bytes2);
process.stderr.write(`wrote ${bytes2.byteLength} bytes to ${options.outputFile}

@@ -1890,3 +724,3 @@ `);

if (bodyFile) {
const text = await readFile2(bodyFile, "utf-8");
const text = await readFile(bodyFile, "utf-8");
merged["body"] = tryParseJson(text);

@@ -1923,6 +757,6 @@ } else if (bodyRaw !== void 0) {

executeOperation,
fetchWithRetry,
filterOperations,
fetchWithRetry2 as fetchWithRetry,
filterOperations2 as filterOperations,
loadSpec,
resolveAuth,
resolveAuth2 as resolveAuth,
resolveBaseUrl,

@@ -1929,0 +763,0 @@ resolveServerUrl,

+4
-6
{
"name": "dynamic-openapi-cli",
"version": "0.1.2",
"version": "0.1.3-next.31f39f5",
"description": "Transform any OpenAPI v3 spec into a fully functional CLI",

@@ -30,6 +30,3 @@ "type": "module",

"dependencies": {
"@readme/openapi-parser": "^4.1.0",
"cli-args-parser": "^1.0.6",
"openapi-types": "^12.1.3",
"yaml": "^2.7.0"
"dynamic-openapi-tools": "^1.1.1"
},

@@ -41,3 +38,4 @@ "devDependencies": {

"typescript": "^5.7.3",
"vitest": "^3.0.5"
"vitest": "^3.0.5",
"yaml": "^2.7.0"
},

@@ -44,0 +42,0 @@ "scripts": {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display