@burn0/burn0 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +341 -2
- package/dist/{chunk-ZHAS7BCI.mjs → chunk-KKYHE4ZV.mjs} +146 -125
- package/dist/cli/index.js +528 -269
- package/dist/index.js +145 -124
- package/dist/index.mjs +1 -1
- package/dist/register.js +145 -124
- package/dist/register.mjs +1 -1
- package/package.json +20 -3
- package/scripts/postinstall.js +27 -5
- package/dist/chunk-DJ72YN4C.mjs.map +0 -1
- package/dist/chunk-ZHAS7BCI.mjs.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/register.js.map +0 -1
- package/dist/register.mjs.map +0 -1
- package/dist/track.js.map +0 -1
- package/dist/track.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -465,13 +465,16 @@ function createDispatcher(mode2, deps) {
|
|
|
465
465
|
break;
|
|
466
466
|
case "dev-cloud":
|
|
467
467
|
deps.logEvent?.(event);
|
|
468
|
+
deps.writeLedger?.(event);
|
|
468
469
|
deps.addToBatch?.(event);
|
|
469
470
|
break;
|
|
470
471
|
case "prod-cloud":
|
|
472
|
+
deps.logEvent?.(event);
|
|
473
|
+
deps.writeLedger?.(event);
|
|
471
474
|
deps.addToBatch?.(event);
|
|
472
475
|
break;
|
|
473
476
|
case "prod-local":
|
|
474
|
-
deps.
|
|
477
|
+
deps.logEvent?.(event);
|
|
475
478
|
break;
|
|
476
479
|
case "test-enabled":
|
|
477
480
|
deps.logEvent?.(event);
|
|
@@ -702,114 +705,114 @@ function estimateLocalCost(event) {
|
|
|
702
705
|
}
|
|
703
706
|
|
|
704
707
|
// src/transport/logger.ts
|
|
705
|
-
var DIM = "\x1B[2m";
|
|
706
708
|
var RESET = "\x1B[0m";
|
|
707
|
-
var CYAN = "\x1B[36m";
|
|
708
709
|
var GREEN = "\x1B[32m";
|
|
709
|
-
var YELLOW = "\x1B[33m";
|
|
710
|
-
var WHITE = "\x1B[37m";
|
|
711
710
|
var BOLD = "\x1B[1m";
|
|
712
711
|
var ORANGE = "\x1B[38;2;250;93;25m";
|
|
713
712
|
var GRAY = "\x1B[90m";
|
|
714
|
-
var headerPrinted = false;
|
|
715
|
-
var sessionTotal = 0;
|
|
716
|
-
var eventCount = 0;
|
|
717
|
-
function formatTokens(count) {
|
|
718
|
-
if (count >= 1e6) return `${(count / 1e6).toFixed(1)}M`;
|
|
719
|
-
if (count >= 1e3) return `${(count / 1e3).toFixed(1)}K`;
|
|
720
|
-
return count.toString();
|
|
721
|
-
}
|
|
722
713
|
function formatCost(cost) {
|
|
723
714
|
if (cost >= 1) return `$${cost.toFixed(2)}`;
|
|
724
715
|
if (cost >= 0.01) return `$${cost.toFixed(4)}`;
|
|
725
716
|
return `$${cost.toFixed(6)}`;
|
|
726
717
|
}
|
|
727
|
-
function
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
`);
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
718
|
+
function formatDuration(ms) {
|
|
719
|
+
const seconds = Math.floor(ms / 1e3);
|
|
720
|
+
if (seconds < 60) return `${seconds}s`;
|
|
721
|
+
const minutes = Math.floor(seconds / 60);
|
|
722
|
+
const remainingSeconds = seconds % 60;
|
|
723
|
+
if (minutes < 60) return `${minutes}m ${remainingSeconds}s`;
|
|
724
|
+
const hours = Math.floor(minutes / 60);
|
|
725
|
+
const remainingMinutes = minutes % 60;
|
|
726
|
+
return `${hours}h ${remainingMinutes}m`;
|
|
727
|
+
}
|
|
728
|
+
function formatServiceBreakdown(perServiceCosts2, maxWidth) {
|
|
729
|
+
const sorted = Object.entries(perServiceCosts2).filter(([, cost]) => cost > 0).sort((a, b) => b[1] - a[1]);
|
|
730
|
+
if (sorted.length === 0) return "";
|
|
731
|
+
const parts = [];
|
|
732
|
+
let currentWidth = 0;
|
|
733
|
+
let shown = 0;
|
|
734
|
+
for (let i = 0; i < sorted.length && shown < 3; i++) {
|
|
735
|
+
const [name, cost] = sorted[i];
|
|
736
|
+
const part = `${name}: ${formatCost(cost)}`;
|
|
737
|
+
if (currentWidth + part.length + 3 > maxWidth && shown > 0) {
|
|
738
|
+
break;
|
|
739
|
+
}
|
|
740
|
+
parts.push(part);
|
|
741
|
+
currentWidth += part.length + 3;
|
|
742
|
+
shown++;
|
|
743
|
+
}
|
|
744
|
+
const remaining = sorted.length - shown;
|
|
745
|
+
if (remaining > 0) {
|
|
746
|
+
parts.push(`+${remaining} more`);
|
|
747
|
+
}
|
|
748
|
+
return parts.join(" \xB7 ");
|
|
749
|
+
}
|
|
750
|
+
function createTicker(init) {
|
|
751
|
+
let sessionCost = 0;
|
|
752
|
+
let sessionCalls = 0;
|
|
753
|
+
const sessionStartTime = Date.now();
|
|
754
|
+
let todayCost2 = init.todayCost;
|
|
755
|
+
let todayCalls2 = init.todayCalls;
|
|
756
|
+
const perServiceCosts2 = { ...init.perServiceCosts };
|
|
757
|
+
let exitPrinted = false;
|
|
758
|
+
let pricedCalls = 0;
|
|
759
|
+
let lastLineLen = 0;
|
|
760
|
+
function render() {
|
|
761
|
+
if (!process.stderr.isTTY) return;
|
|
762
|
+
if (todayCalls2 === 0) return;
|
|
763
|
+
let content;
|
|
764
|
+
if (pricedCalls === 0 && todayCost2 === 0) {
|
|
765
|
+
content = ` burn0 \u25B8 ${todayCalls2} calls today`;
|
|
766
|
+
} else {
|
|
767
|
+
const breakdown = formatServiceBreakdown(perServiceCosts2, 40);
|
|
768
|
+
const breakdownPart = breakdown ? ` \u2500\u2500 ${breakdown}` : "";
|
|
769
|
+
content = ` burn0 \u25B8 ${formatCost(todayCost2)} today (${todayCalls2} calls)${breakdownPart}`;
|
|
770
|
+
}
|
|
771
|
+
const pad = lastLineLen > content.length ? " ".repeat(lastLineLen - content.length) : "";
|
|
772
|
+
lastLineLen = content.length;
|
|
773
|
+
let colored;
|
|
774
|
+
if (pricedCalls === 0 && todayCost2 === 0) {
|
|
775
|
+
colored = ` ${ORANGE}${BOLD}burn0 \u25B8${RESET} ${GRAY}${todayCalls2} calls today${RESET}`;
|
|
776
|
+
} else {
|
|
777
|
+
const breakdown = formatServiceBreakdown(perServiceCosts2, 40);
|
|
778
|
+
const breakdownPart = breakdown ? ` ${GRAY}\u2500\u2500${RESET} ${breakdown}` : "";
|
|
779
|
+
colored = ` ${ORANGE}${BOLD}burn0 \u25B8${RESET} ${GREEN}${formatCost(todayCost2)}${RESET} ${GRAY}today (${todayCalls2} calls)${RESET}${breakdownPart}`;
|
|
780
|
+
}
|
|
781
|
+
process.stderr.write(`\r${colored}${pad}`);
|
|
782
|
+
}
|
|
783
|
+
function tick(event) {
|
|
784
|
+
const estimate = estimateLocalCost(event);
|
|
785
|
+
todayCalls2++;
|
|
786
|
+
sessionCalls++;
|
|
787
|
+
if (estimate.type === "priced" && estimate.cost > 0) {
|
|
788
|
+
todayCost2 += estimate.cost;
|
|
789
|
+
sessionCost += estimate.cost;
|
|
790
|
+
pricedCalls++;
|
|
791
|
+
perServiceCosts2[event.service] = (perServiceCosts2[event.service] ?? 0) + estimate.cost;
|
|
792
|
+
}
|
|
793
|
+
render();
|
|
794
|
+
}
|
|
795
|
+
function printExitSummary() {
|
|
796
|
+
if (!process.stderr.isTTY) return;
|
|
797
|
+
if (sessionCalls === 0) return;
|
|
798
|
+
if (exitPrinted) return;
|
|
799
|
+
exitPrinted = true;
|
|
800
|
+
const duration = formatDuration(Date.now() - sessionStartTime);
|
|
801
|
+
let line;
|
|
802
|
+
if (pricedCalls === 0 && sessionCost === 0) {
|
|
803
|
+
line = `
|
|
804
|
+
${ORANGE}${BOLD}burn0 \u25B8${RESET} ${GRAY}session: ${sessionCalls} calls (${duration})${RESET} ${GRAY}\u2500\u2500${RESET} ${GRAY}today: ${todayCalls2} calls${RESET}
|
|
805
|
+
`;
|
|
806
|
+
} else {
|
|
807
|
+
const monthlyEst = todayCost2 > 0 ? formatCost(todayCost2 * 30) : null;
|
|
808
|
+
const projPart = monthlyEst ? ` ${GRAY}\u2500\u2500${RESET} ${GRAY}~${GREEN}${monthlyEst}${RESET}${GRAY}/mo${RESET}` : "";
|
|
809
|
+
line = `
|
|
810
|
+
${ORANGE}${BOLD}burn0 \u25B8${RESET} ${GRAY}session:${RESET} ${GREEN}${formatCost(sessionCost)}${RESET} ${GRAY}(${sessionCalls} calls, ${duration})${RESET} ${GRAY}\u2500\u2500${RESET} ${GRAY}today:${RESET} ${GREEN}${formatCost(todayCost2)}${RESET}${projPart}
|
|
811
|
+
`;
|
|
812
|
+
}
|
|
813
|
+
process.stderr.write(line);
|
|
812
814
|
}
|
|
815
|
+
return { tick, printExitSummary };
|
|
813
816
|
}
|
|
814
817
|
|
|
815
818
|
// src/index.ts
|
|
@@ -818,12 +821,36 @@ var apiKey = getApiKey();
|
|
|
818
821
|
var mode = detectMode({ isTTY: isTTY(), apiKey });
|
|
819
822
|
var { track, startSpan, enrichEvent } = createTracker();
|
|
820
823
|
var originalFetch2 = globalThis.fetch;
|
|
821
|
-
if (mode !== "test-disabled") {
|
|
824
|
+
if (mode !== "test-disabled" && mode !== "prod-local") {
|
|
822
825
|
fetchPricing(BURN0_API_URL, originalFetch2).catch(() => {
|
|
823
826
|
});
|
|
824
827
|
}
|
|
825
|
-
var
|
|
826
|
-
|
|
828
|
+
var ledger = new LocalLedger(process.cwd());
|
|
829
|
+
function getTodayDateStr() {
|
|
830
|
+
const d = /* @__PURE__ */ new Date();
|
|
831
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
832
|
+
}
|
|
833
|
+
var todayCost = 0;
|
|
834
|
+
var todayCalls = 0;
|
|
835
|
+
var perServiceCosts = {};
|
|
836
|
+
try {
|
|
837
|
+
const todayStr = getTodayDateStr();
|
|
838
|
+
const allEvents = ledger.read();
|
|
839
|
+
for (const event of allEvents) {
|
|
840
|
+
const eventDate = new Date(event.timestamp);
|
|
841
|
+
const eventDateStr = `${eventDate.getFullYear()}-${String(eventDate.getMonth() + 1).padStart(2, "0")}-${String(eventDate.getDate()).padStart(2, "0")}`;
|
|
842
|
+
if (eventDateStr === todayStr) {
|
|
843
|
+
todayCalls++;
|
|
844
|
+
const estimate = estimateLocalCost(event);
|
|
845
|
+
if (estimate.type === "priced" && estimate.cost > 0) {
|
|
846
|
+
todayCost += estimate.cost;
|
|
847
|
+
perServiceCosts[event.service] = (perServiceCosts[event.service] ?? 0) + estimate.cost;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
} catch {
|
|
852
|
+
}
|
|
853
|
+
var ticker = createTicker({ todayCost, todayCalls, perServiceCosts });
|
|
827
854
|
var batch = null;
|
|
828
855
|
if ((mode === "dev-cloud" || mode === "prod-cloud") && apiKey) {
|
|
829
856
|
batch = new BatchBuffer({
|
|
@@ -836,17 +863,20 @@ if ((mode === "dev-cloud" || mode === "prod-cloud") && apiKey) {
|
|
|
836
863
|
}
|
|
837
864
|
});
|
|
838
865
|
}
|
|
866
|
+
var shouldWriteLedger = mode !== "test-disabled" && mode !== "prod-local";
|
|
839
867
|
var dispatch = createDispatcher(mode, {
|
|
840
|
-
logEvent,
|
|
841
|
-
writeLedger:
|
|
842
|
-
addToBatch: batch ? (e) => batch.add(e) : void 0
|
|
843
|
-
accumulate: (e) => accumulatedEvents.push(e)
|
|
868
|
+
logEvent: (e) => ticker.tick(e),
|
|
869
|
+
writeLedger: shouldWriteLedger ? (e) => ledger.write(e) : void 0,
|
|
870
|
+
addToBatch: batch ? (e) => batch.add(e) : void 0
|
|
844
871
|
});
|
|
845
872
|
var preloaded = checkImportOrder();
|
|
846
873
|
if (preloaded.length > 0) {
|
|
847
|
-
console.warn(`[burn0] Warning: These SDKs were imported before burn0 and may not be tracked: ${preloaded.join(", ")}. Move \`import 'burn0'\` to the top of your entry file.`);
|
|
874
|
+
console.warn(`[burn0] Warning: These SDKs were imported before burn0 and may not be tracked: ${preloaded.join(", ")}. Move \`import '@burn0/burn0'\` to the top of your entry file.`);
|
|
848
875
|
}
|
|
849
|
-
if (
|
|
876
|
+
if (mode === "prod-local") {
|
|
877
|
+
console.warn("[burn0] No API key \u2014 costs not tracked. Get one free at burn0.dev/api");
|
|
878
|
+
}
|
|
879
|
+
if (canPatch() && mode !== "test-disabled" && mode !== "prod-local") {
|
|
850
880
|
const onEvent = (event) => {
|
|
851
881
|
const enriched = enrichEvent(event);
|
|
852
882
|
dispatch(enriched);
|
|
@@ -855,25 +885,16 @@ if (canPatch() && mode !== "test-disabled") {
|
|
|
855
885
|
patchHttp(onEvent);
|
|
856
886
|
markPatched();
|
|
857
887
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
console.log(formatProcessSummary(accumulatedEvents, uptimeSeconds));
|
|
864
|
-
}
|
|
865
|
-
});
|
|
866
|
-
}
|
|
867
|
-
if (batch) {
|
|
868
|
-
const exitFlush = () => {
|
|
888
|
+
var exitHandled = false;
|
|
889
|
+
process.on("exit", () => {
|
|
890
|
+
if (exitHandled) return;
|
|
891
|
+
exitHandled = true;
|
|
892
|
+
if (batch) {
|
|
869
893
|
batch.flush();
|
|
870
894
|
batch.destroy();
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
process.on("SIGINT", exitFlush);
|
|
875
|
-
process.on("SIGHUP", exitFlush);
|
|
876
|
-
}
|
|
895
|
+
}
|
|
896
|
+
ticker.printExitSummary();
|
|
897
|
+
});
|
|
877
898
|
var restore = createRestorer({ unpatchFetch, unpatchHttp, resetGuard });
|
|
878
899
|
// Annotate the CommonJS export names for ESM import in node:
|
|
879
900
|
0 && (module.exports = {
|