Primeiro Commit v0.beta1

This commit is contained in:
2026-04-29 00:27:50 -03:00
parent 93d4906fb5
commit 8662a153fe
27 changed files with 16303 additions and 0 deletions

View File

@@ -0,0 +1,200 @@
import fs from "node:fs/promises";
import {
ensureParentDir,
resolveOutputFilePath,
} from "./runtime-paths.mjs";
const NULL_SENTINEL = "__CODEX_NULL__";
const MONETARY_FIELD_KEYS = new Set(["bookingValue", "opportunityValue", "workloadAmount", "pipelineAmount"]);
const THOUSANDS_DISPLAY_KEYS = new Set([
...MONETARY_FIELD_KEYS,
"totalBookingValue",
"totalOpportunityValue",
"totalWorkloadAmount",
"totalPipelineAmount",
]);
const THOUSANDS_DISPLAY_SOURCE_FIELDS = new Set(MONETARY_FIELD_KEYS);
const ORACLE_MONTHS = {
JAN: "01",
FEB: "02",
MAR: "03",
APR: "04",
MAY: "05",
JUN: "06",
JUL: "07",
AUG: "08",
SEP: "09",
OCT: "10",
NOV: "11",
DEC: "12",
};
export function buildWarnings({ requestedLimit, recordsCount, customSql, customSqlColumnsResolved = false }) {
const warnings = [];
if (requestedLimit > 0 && recordsCount >= requestedLimit) {
warnings.push(
`The query returned ${recordsCount} rows, which matches the requested limit (${requestedLimit}). Results may be truncated; rerun with a higher --limit if you need a complete extract.`
);
}
if (customSql && !customSqlColumnsResolved) {
warnings.push("Custom SQL records are returned as raw row arrays because the Oracle DV response does not guarantee stable field aliases.");
}
return warnings;
}
export function parseNumericValue(value) {
if (typeof value === "number") return Number.isFinite(value) ? value : 0;
const normalized = String(value ?? "")
.replace(/,/g, "")
.trim();
if (!normalized) return 0;
const parsed = Number(normalized);
return Number.isFinite(parsed) ? parsed : 0;
}
function isLikelyMonetaryFieldName(fieldName) {
return /booking|workload|pipeline|opportunityvalue/i.test(String(fieldName || ""));
}
function formatThousandsDisplayValue(value) {
const thousands = Math.trunc(parseNumericValue(value) / 1000);
const grouped = String(thousands).replace(/\B(?=(\d{3})+(?!\d))/g, ".");
return `${grouped}k`;
}
function formatDisplaySection(node, displayKeys = THOUSANDS_DISPLAY_KEYS) {
if (Array.isArray(node)) {
return node.map((item) => formatDisplaySection(item, displayKeys));
}
if (!node || typeof node !== "object") {
return node;
}
return Object.fromEntries(
Object.entries(node).map(([key, value]) => {
if ((displayKeys.has(key) || isLikelyMonetaryFieldName(key)) && value !== null && value !== undefined && value !== "") {
return [key, formatThousandsDisplayValue(value)];
}
return [key, formatDisplaySection(value, displayKeys)];
})
);
}
function collectThousandsDisplayKeys(payload) {
const displayKeys = new Set(THOUSANDS_DISPLAY_KEYS);
for (const columnName of payload?.columns || []) {
if (MONETARY_FIELD_KEYS.has(columnName) || isLikelyMonetaryFieldName(columnName)) {
displayKeys.add(columnName);
}
}
const querySpec = payload?.request?.query;
if (querySpec && typeof querySpec === "object") {
for (const item of [...(querySpec.select || []), ...(querySpec.measure || [])]) {
if (!item || typeof item !== "object") continue;
if (!THOUSANDS_DISPLAY_SOURCE_FIELDS.has(item.fieldName)) continue;
if (item.outputName) displayKeys.add(item.outputName);
}
}
for (const inferredColumn of payload?.request?.inferredColumns || []) {
if (MONETARY_FIELD_KEYS.has(inferredColumn) || isLikelyMonetaryFieldName(inferredColumn)) {
displayKeys.add(inferredColumn);
}
}
return displayKeys;
}
function rowsPulledFromApi(result) {
return Array.isArray(result?.aResults) ? result.aResults.length : 0;
}
function buildApiQueryMetric({
label,
result = null,
rowsReturned = null,
source = null,
countedInTotal = true,
} = {}) {
const resolvedRowsReturned = Number.isFinite(rowsReturned) ? rowsReturned : rowsPulledFromApi(result);
return {
label: label || "query",
rowsPulledFromApi: resolvedRowsReturned,
source: source || null,
countedInTotal: countedInTotal !== false,
};
}
export function buildApiMetrics(entries = []) {
const queries = entries
.filter(Boolean)
.map((entry) =>
buildApiQueryMetric({
label: entry.label,
result: entry.result,
rowsReturned: entry.rowsReturned,
source: entry.source,
countedInTotal: entry.countedInTotal,
})
);
const totalRowsPulledFromApi = queries.reduce(
(sum, query) => sum + (query.countedInTotal ? query.rowsPulledFromApi : 0),
0
);
return {
totalRowsPulledFromApi,
queries,
explanation: `Raw rows pulled from API: ${totalRowsPulledFromApi}.`,
};
}
export function preparePayloadForOutput(payload) {
const displayKeys = collectThousandsDisplayKeys(payload);
return {
...payload,
apiMetrics: payload?.apiMetrics || buildApiMetrics(),
...(Object.prototype.hasOwnProperty.call(payload, "records")
? { records: formatDisplaySection(payload.records, displayKeys) }
: {}),
...(payload.summary && typeof payload.summary === "object"
? { summary: formatDisplaySection(payload.summary, displayKeys) }
: {}),
};
}
function normalizeOracleDateString(value) {
if (typeof value !== "string") return value;
const match = /^(\d{2})-([A-Z]{3})-(\d{2}|\d{4})$/.exec(value.trim().toUpperCase());
if (!match) return value;
const [, day, monthToken, yearToken] = match;
const month = ORACLE_MONTHS[monthToken];
if (!month) return value;
const year =
yearToken.length === 4
? yearToken
: Number(yearToken) >= 70
? `19${yearToken}`
: `20${yearToken}`;
return `${year}-${month}-${day}`;
}
export function normalizeCell(value) {
if (value === NULL_SENTINEL) return null;
return normalizeOracleDateString(value ?? null);
}
export function mapRows(fields, rows) {
return rows.map((row) =>
Object.fromEntries(fields.map((field, index) => [field, normalizeCell(row[index])]))
);
}
export function emitJson(args, payload, runtimeHome) {
const json = JSON.stringify(preparePayloadForOutput(payload), null, 2);
const outputFilePath = resolveOutputFilePath(args["output-file"], runtimeHome);
if (outputFilePath) {
return ensureParentDir(outputFilePath)
.then(() => fs.writeFile(outputFilePath, `${json}\n`, "utf8"))
.then(() => json);
}
return Promise.resolve(json);
}