Loading...
Loading...
Compare original and translation side by side
undefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefined// scripts/generate-http-files.ts
import * as fs from "fs";
import * as path from "path";
interface RouteInfo {
method: string;
path: string;
name: string;
description?: string;
body?: object;
headers?: Record<string, string>;
queryParams?: { name: string; value: string; optional?: boolean }[];
}
interface HttpFileOptions {
baseUrlVar: string;
authType?: "bearer" | "basic" | "apikey";
authVar?: string;
includeComments?: boolean;
}
function generateHttpFile(
routes: RouteInfo[],
options: HttpFileOptions
): string {
const lines: string[] = [];
// Add file header
lines.push("# Auto-generated API requests");
lines.push(`# Base URL: {{${options.baseUrlVar}}}`);
lines.push("# Switch environment: Ctrl+Alt+E (Cmd+Alt+E on Mac)");
lines.push("");
for (const route of routes) {
// Request separator and name
lines.push(`### ${route.name}`);
if (route.description) {
lines.push(`# ${route.description}`);
}
// Method and URL
let url = `{{${options.baseUrlVar}}}${route.path}`;
// Convert :param to {{param}}
url = url.replace(/:(\w+)/g, "{{$1}}");
// Add query params
if (route.queryParams?.length) {
const queryString = route.queryParams
.map((p) => `${p.name}=${p.value}`)
.join("&");
url += `?${queryString}`;
}
lines.push(`${route.method} ${url}`);
// Headers
if (["POST", "PUT", "PATCH"].includes(route.method)) {
lines.push("Content-Type: application/json");
}
// Authentication
if (options.authType === "bearer" && options.authVar) {
lines.push(`Authorization: Bearer {{${options.authVar}}}`);
} else if (options.authType === "basic") {
lines.push(`Authorization: Basic {{${options.authVar}}}`);
} else if (options.authType === "apikey") {
lines.push(`X-API-Key: {{${options.authVar}}}`);
}
// Custom headers
if (route.headers) {
for (const [key, value] of Object.entries(route.headers)) {
lines.push(`${key}: ${value}`);
}
}
// Request body
if (route.body && ["POST", "PUT", "PATCH"].includes(route.method)) {
lines.push("");
lines.push(JSON.stringify(route.body, null, 2));
}
lines.push("");
lines.push("");
}
return lines.join("\n");
}
function generateHttpFilesByResource(
routes: RouteInfo[],
outputDir: string,
options: HttpFileOptions
): void {
const groupedRoutes = groupRoutesByResource(routes);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
for (const [resource, resourceRoutes] of Object.entries(groupedRoutes)) {
const content = generateHttpFile(resourceRoutes, options);
const filePath = path.join(outputDir, `${resource}.http`);
fs.writeFileSync(filePath, content);
console.log(`Generated ${filePath}`);
}
}
function groupRoutesByResource(
routes: RouteInfo[]
): Record<string, RouteInfo[]> {
const groups: Record<string, RouteInfo[]> = {};
for (const route of routes) {
const parts = route.path.split("/").filter(Boolean);
const resource = parts[0] || "api";
if (!groups[resource]) {
groups[resource] = [];
}
groups[resource].push(route);
}
return groups;
}// scripts/generate-http-files.ts
import * as fs from "fs";
import * as path from "path";
interface RouteInfo {
method: string;
path: string;
name: string;
description?: string;
body?: object;
headers?: Record<string, string>;
queryParams?: { name: string; value: string; optional?: boolean }[];
}
interface HttpFileOptions {
baseUrlVar: string;
authType?: "bearer" | "basic" | "apikey";
authVar?: string;
includeComments?: boolean;
}
function generateHttpFile(
routes: RouteInfo[],
options: HttpFileOptions
): string {
const lines: string[] = [];
// Add file header
lines.push("# Auto-generated API requests");
lines.push(`# Base URL: {{${options.baseUrlVar}}}`);
lines.push("# Switch environment: Ctrl+Alt+E (Cmd+Alt+E on Mac)");
lines.push("");
for (const route of routes) {
// Request separator and name
lines.push(`### ${route.name}`);
if (route.description) {
lines.push(`# ${route.description}`);
}
// Method and URL
let url = `{{${options.baseUrlVar}}}${route.path}`;
// Convert :param to {{param}}
url = url.replace(/:(\w+)/g, "{{$1}}");
// Add query params
if (route.queryParams?.length) {
const queryString = route.queryParams
.map((p) => `${p.name}=${p.value}`)
.join("&");
url += `?${queryString}`;
}
lines.push(`${route.method} ${url}`);
// Headers
if (["POST", "PUT", "PATCH"].includes(route.method)) {
lines.push("Content-Type: application/json");
}
// Authentication
if (options.authType === "bearer" && options.authVar) {
lines.push(`Authorization: Bearer {{${options.authVar}}}`);
} else if (options.authType === "basic") {
lines.push(`Authorization: Basic {{${options.authVar}}}`);
} else if (options.authType === "apikey") {
lines.push(`X-API-Key: {{${options.authVar}}}`);
}
// Custom headers
if (route.headers) {
for (const [key, value] of Object.entries(route.headers)) {
lines.push(`${key}: ${value}`);
}
}
// Request body
if (route.body && ["POST", "PUT", "PATCH"].includes(route.method)) {
lines.push("");
lines.push(JSON.stringify(route.body, null, 2));
}
lines.push("");
lines.push("");
}
return lines.join("\n");
}
function generateHttpFilesByResource(
routes: RouteInfo[],
outputDir: string,
options: HttpFileOptions
): void {
const groupedRoutes = groupRoutesByResource(routes);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
for (const [resource, resourceRoutes] of Object.entries(groupedRoutes)) {
const content = generateHttpFile(resourceRoutes, options);
const filePath = path.join(outputDir, `${resource}.http`);
fs.writeFileSync(filePath, content);
console.log(`Generated ${filePath}`);
}
}
function groupRoutesByResource(
routes: RouteInfo[]
): Record<string, RouteInfo[]> {
const groups: Record<string, RouteInfo[]> = {};
for (const route of routes) {
const parts = route.path.split("/").filter(Boolean);
const resource = parts[0] || "api";
if (!groups[resource]) {
groups[resource] = [];
}
groups[resource].push(route);
}
return groups;
}undefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefined// .vscode/settings.json
{
"rest-client.environmentVariables": {
"$shared": {
"version": "v1",
"contentType": "application/json"
},
"local": {
"baseUrl": "http://localhost:3000/api",
"authToken": "",
"userId": "1"
},
"staging": {
"baseUrl": "https://staging-api.example.com",
"authToken": "",
"userId": "test-123"
},
"production": {
"baseUrl": "https://api.example.com",
"authToken": "",
"userId": ""
}
},
"rest-client.previewResponseInUntitledDocument": true,
"rest-client.timeoutinmilliseconds": 10000,
"rest-client.followRedirect": true,
"rest-client.defaultHeaders": {
"Accept": "application/json",
"User-Agent": "rest-client"
}
}// .vscode/settings.json
{
"rest-client.environmentVariables": {
"$shared": {
"version": "v1",
"contentType": "application/json"
},
"local": {
"baseUrl": "http://localhost:3000/api",
"authToken": "",
"userId": "1"
},
"staging": {
"baseUrl": "https://staging-api.example.com",
"authToken": "",
"userId": "test-123"
},
"production": {
"baseUrl": "https://api.example.com",
"authToken": "",
"userId": ""
}
},
"rest-client.previewResponseInUntitledDocument": true,
"rest-client.timeoutinmilliseconds": 10000,
"rest-client.followRedirect": true,
"rest-client.defaultHeaders": {
"Accept": "application/json",
"User-Agent": "rest-client"
}
}#!/usr/bin/env node
// scripts/http-gen.ts
import * as fs from "fs";
import { program } from "commander";
program
.name("http-gen")
.description("Generate .http files from API routes")
.option("-f, --framework <type>", "Framework type", "express")
.option("-s, --source <path>", "Source directory", "./src")
.option("-o, --output <path>", "Output directory", "./http")
.option("--single-file", "Generate single file instead of per-resource")
.option("-a, --auth <type>", "Auth type (bearer|basic|apikey)")
.parse();
const options = program.opts();
async function main() {
const routes = await scanRoutes(options.framework, options.source);
const httpOptions = {
baseUrlVar: "baseUrl",
authType: options.auth,
authVar: "authToken",
};
if (options.singleFile) {
const content = generateHttpFile(routes, httpOptions);
fs.writeFileSync(path.join(options.output, "api.http"), content);
} else {
generateHttpFilesByResource(routes, options.output, httpOptions);
}
console.log(`Generated .http files in ${options.output}`);
}
main();#!/usr/bin/env node
// scripts/http-gen.ts
import * as fs from "fs";
import { program } from "commander";
program
.name("http-gen")
.description("Generate .http files from API routes")
.option("-f, --framework <type>", "Framework type", "express")
.option("-s, --source <path>", "Source directory", "./src")
.option("-o, --output <path>", "Output directory", "./http")
.option("--single-file", "Generate single file instead of per-resource")
.option("-a, --auth <type>", "Auth type (bearer|basic|apikey)")
.parse();
const options = program.opts();
async function main() {
const routes = await scanRoutes(options.framework, options.source);
const httpOptions = {
baseUrlVar: "baseUrl",
authType: options.auth,
authVar: "authToken",
};
if (options.singleFile) {
const content = generateHttpFile(routes, httpOptions);
fs.writeFileSync(path.join(options.output, "api.http"), content);
} else {
generateHttpFilesByResource(routes, options.output, httpOptions);
}
console.log(`Generated .http files in ${options.output}`);
}
main();# @name requestName# @name requestName{{param}}{{param}}