initial push

This commit is contained in:
Marcelo Dares
2026-03-15 15:03:56 +01:00
parent d48b9d5352
commit 65aaf9275e
146 changed files with 70245 additions and 100 deletions

View File

@@ -0,0 +1,195 @@
import { readFileSync, existsSync } from "node:fs";
import { resolve } from "node:path";
const DEFAULT_TIMEOUT_MS = 20000;
function loadDotenv(filePath) {
if (!existsSync(filePath)) {
return;
}
const raw = readFileSync(filePath, "utf8");
for (const line of raw.split(/\r?\n/)) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#")) {
continue;
}
const eqIndex = trimmed.indexOf("=");
if (eqIndex === -1) {
continue;
}
const key = trimmed.slice(0, eqIndex).trim();
if (!key || process.env[key] !== undefined) {
continue;
}
let value = trimmed.slice(eqIndex + 1).trim();
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
value = value.slice(1, -1);
}
process.env[key] = value;
}
}
function parseArgs(argv) {
const args = {
baseUrl: process.env.LICITAYA_BASE_URL,
endpoint: process.env.LICITAYA_TEST_ENDPOINT,
accept: process.env.LICITAYA_ACCEPT || "application/json",
method: "GET",
timeoutMs: Number.parseInt(process.env.LICITAYA_TIMEOUT_MS || "", 10) || DEFAULT_TIMEOUT_MS,
};
for (let i = 0; i < argv.length; i += 1) {
const current = argv[i];
const next = argv[i + 1];
if (current === "--base-url" && next) {
args.baseUrl = next;
i += 1;
continue;
}
if (current === "--endpoint" && next) {
args.endpoint = next;
i += 1;
continue;
}
if (current === "--accept" && next) {
args.accept = next;
i += 1;
continue;
}
if (current === "--method" && next) {
args.method = next.toUpperCase();
i += 1;
continue;
}
if (current === "--timeout" && next) {
const parsed = Number.parseInt(next, 10);
if (Number.isFinite(parsed) && parsed > 0) {
args.timeoutMs = parsed;
}
i += 1;
continue;
}
}
return args;
}
function buildUrl(baseUrl, endpoint) {
if (!endpoint) {
throw new Error("Missing LICITAYA_TEST_ENDPOINT (or --endpoint).");
}
if (endpoint.includes("<") || endpoint.includes(">")) {
throw new Error(
"LICITAYA_TEST_ENDPOINT still contains placeholders. Use a real path such as /tender/search or /tender/<tenderId>.",
);
}
if (/^https?:\/\//i.test(endpoint)) {
return new URL(endpoint);
}
if (!baseUrl) {
throw new Error("Missing LICITAYA_BASE_URL (or --base-url).");
}
const normalizedBase = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
const cleanEndpoint = endpoint.startsWith("/") ? endpoint.slice(1) : endpoint;
return new URL(cleanEndpoint, normalizedBase);
}
function previewBody(rawBody, contentType) {
const trimmed = rawBody.trim();
if (!trimmed) {
return "(empty body)";
}
const isJson = contentType.includes("application/json") || trimmed.startsWith("{") || trimmed.startsWith("[");
if (isJson) {
try {
const json = JSON.parse(trimmed);
return JSON.stringify(json, null, 2);
} catch {
return trimmed.slice(0, 3000);
}
}
return trimmed.slice(0, 3000);
}
loadDotenv(resolve(process.cwd(), ".env"));
const apiKey = process.env.LICITAYA_API_KEY || process.env.X_API_KEY || process.env.X_API_KEY_LICITAYA;
if (!apiKey) {
console.error("Missing API key. Set LICITAYA_API_KEY in .env or shell env.");
process.exit(1);
}
const args = parseArgs(process.argv.slice(2));
let url;
try {
url = buildUrl(args.baseUrl, args.endpoint);
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
process.exit(1);
}
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), args.timeoutMs);
try {
const response = await fetch(url, {
method: args.method,
headers: {
"X-API-KEY": apiKey,
Accept: args.accept,
},
signal: controller.signal,
});
const contentType = response.headers.get("content-type") || "";
const rawBody = await response.text();
const bodyPreview = previewBody(rawBody, contentType);
console.log(`URL: ${url.toString()}`);
console.log(`Method: ${args.method}`);
console.log(`Status: ${response.status} ${response.statusText}`);
console.log(`Content-Type: ${contentType || "(none)"}`);
console.log("--- Response Preview ---");
console.log(bodyPreview);
if (response.status === 404 && url.pathname.endsWith("/tender/search")) {
console.error("No tenders matched the current filters. Try a broader keyword or fewer filters.");
}
if (!response.ok) {
process.exit(1);
}
} catch (error) {
if (error instanceof Error && error.name === "AbortError") {
console.error(`Request timed out after ${args.timeoutMs} ms.`);
} else {
console.error(error instanceof Error ? error.message : String(error));
}
process.exit(1);
} finally {
clearTimeout(timeout);
}