@adriangalilea/utils 4.0.0 → 4.1.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 CHANGED
@@ -26,6 +26,19 @@ Readers propagate database errors rather than presenting missing data as zero.
26
26
  `renderMetrics(rows, { daily? })` from `metrics/cli` renders it with the existing
27
27
  ANSI-aware `cli.table` helpers. Both discover every recorded metric from its
28
28
  declaration metadata. No product-specific metric list belongs in a renderer.
29
+
30
+ For period comparisons, `metricWindows(days, { now?, includeToday? })` from
31
+ `metrics/report` returns adjacent equal-length `current` and `previous` UTC ranges.
32
+ By default both contain completed days; `includeToday` marks the current window
33
+ `partial`. Fetch those ranges through your adapter, then call
34
+ `compareMetrics(currentRows, previousRows)` and
35
+ `renderMetricComparison(comparisons)` from `metrics/cli`. Comparisons include
36
+ disappearing series, count changes and weighted timing-average changes. Percent
37
+ change is null without a nonzero baseline; missing timing samples stay null.
38
+ Changing a metric's kind or unit across the inputs is rejected. Missing observations
39
+ are not proof that collection was running: deltas compare recorded data only.
40
+ The SQL writer rejects changes to an existing key's kind or unit atomically, before
41
+ adding observations. Use a new key for a new meaning; labels and help can be edited.
29
42
  The SQL adapter accepts a libSQL-compatible client; D1 or another store can implement
30
43
  the injected `write(measurement)` contract instead. No database client is bundled.
31
44
 
@@ -1,4 +1,6 @@
1
- import { type DailyMetric } from "./report.js";
1
+ import { type DailyMetric, type MetricComparison } from "./report.js";
2
+ /** Neutral deltas: increasing a metric does not necessarily mean improvement. */
3
+ export declare function renderMetricComparison(comparisons: readonly MetricComparison[]): string;
2
4
  /** Render declarations stored beside observations; adding a metric requires no panel edit. */
3
5
  export declare function renderMetrics(rows: readonly DailyMetric[], options?: {
4
6
  daily?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/metrics/cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAoB,MAAM,aAAa,CAAC;AAEjE,8FAA8F;AAC9F,wBAAgB,aAAa,CAC5B,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,MAAM,CAoDR"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/metrics/cli.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,WAAW,EAEhB,KAAK,gBAAgB,EAErB,MAAM,aAAa,CAAC;AAErB,iFAAiF;AACjF,wBAAgB,sBAAsB,CACrC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GACtC,MAAM,CA2DR;AAED,8FAA8F;AAC9F,wBAAgB,aAAa,CAC5B,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,MAAM,CAoDR"}
@@ -1,5 +1,59 @@
1
1
  import { table, ui } from "../cli/index.js";
2
- import { summarizeMetrics } from "./report.js";
2
+ import { summarizeMetrics, } from "./report.js";
3
+ /** Neutral deltas: increasing a metric does not necessarily mean improvement. */
4
+ export function renderMetricComparison(comparisons) {
5
+ if (!comparisons.length)
6
+ return "No recorded measurements in either window.";
7
+ const number = (n) => new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 }).format(n);
8
+ const signed = (n) => `${n > 0 ? "+" : ""}${number(n)}`;
9
+ const delta = (value) => `${signed(value.absolute)} (${value.percent === null ? "no baseline" : `${signed(value.percent)}%`})`;
10
+ const groups = new Map();
11
+ for (const row of comparisons) {
12
+ const key = JSON.stringify([row.project, row.key]);
13
+ const group = groups.get(key) ?? [];
14
+ group.push(row);
15
+ groups.set(key, group);
16
+ }
17
+ return [...groups.values()]
18
+ .map((group) => {
19
+ const timing = group[0].kind === "timing";
20
+ const average = (n) => n == null ? "—" : `${number(n)} ${group[0].unit}`.trim();
21
+ return [
22
+ ui.head(`${group[0].project} · ${group[0].label}${timing ? " (samples)" : ""}`),
23
+ table(group.map((r) => [
24
+ Object.entries(r.dimensions)
25
+ .map(([k, v]) => `${k}=${v}`)
26
+ .join(" · ") || "all",
27
+ number(r.current?.count ?? 0),
28
+ number(r.previous?.count ?? 0),
29
+ delta(r.countChange),
30
+ ...(timing
31
+ ? [
32
+ average(r.current?.average),
33
+ average(r.previous?.average),
34
+ r.averageChange ? delta(r.averageChange) : "—",
35
+ ]
36
+ : []),
37
+ ]), {
38
+ head: [
39
+ "breakdown",
40
+ "current",
41
+ "previous",
42
+ "change",
43
+ ...(timing ? ["avg current", "avg previous", "avg change"] : []),
44
+ ],
45
+ align: [
46
+ "l",
47
+ "r",
48
+ "r",
49
+ "r",
50
+ ...(timing ? ["r", "r", "r"] : []),
51
+ ],
52
+ }),
53
+ ].join("\n");
54
+ })
55
+ .join("\n\n");
56
+ }
3
57
  /** Render declarations stored beside observations; adding a metric requires no panel edit. */
4
58
  export function renderMetrics(rows, options = {}) {
5
59
  if (!rows.length)
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/metrics/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/metrics/cli.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,40 @@ export interface MetricTotal {
22
22
  sum: number;
23
23
  average: number | null;
24
24
  }
25
+ export interface MetricChange {
26
+ absolute: number;
27
+ /** Null when a percentage has no nonzero baseline. */
28
+ percent: number | null;
29
+ }
30
+ export interface MetricComparison {
31
+ project: string;
32
+ key: string;
33
+ label: string;
34
+ kind: string;
35
+ unit: string;
36
+ dimensions: Record<string, string>;
37
+ current: MetricTotal | null;
38
+ previous: MetricTotal | null;
39
+ countChange: MetricChange;
40
+ averageChange: MetricChange | null;
41
+ }
42
+ /** Adjacent equal-length UTC windows; completed days by default. */
43
+ export declare function metricWindows(days: number, options?: {
44
+ now?: Date;
45
+ includeToday?: boolean;
46
+ }): {
47
+ current: {
48
+ from: string;
49
+ to: string;
50
+ };
51
+ previous: {
52
+ from: string;
53
+ to: string;
54
+ };
55
+ partial: boolean;
56
+ };
57
+ /** Compare recorded observations; absent series have zero counts, never zero latency. */
58
+ export declare function compareMetrics(current: readonly DailyMetric[], previous: readonly DailyMetric[]): MetricComparison[];
25
59
  /** One report shape for terminal and web. No product names or metric lists. */
26
60
  export declare function summarizeMetrics(rows: readonly DailyMetric[]): MetricTotal[];
27
61
  //# sourceMappingURL=report.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAAE,CAiC5E"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,YAAY,CAAC;IAC1B,aAAa,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;EAkBpD;AASD,yFAAyF;AACzF,wBAAgB,cAAc,CAC7B,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,QAAQ,EAAE,SAAS,WAAW,EAAE,GAC9B,gBAAgB,EAAE,CA4CpB;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAAE,CAqC5E"}
@@ -1,3 +1,62 @@
1
+ /** Adjacent equal-length UTC windows; completed days by default. */
2
+ export function metricWindows(days, options = {}) {
3
+ if (!Number.isInteger(days) || days < 1 || days > 3660)
4
+ throw new Error("metrics: window must be 1–3660 days");
5
+ const day = 86_400_000;
6
+ const today = Date.parse((options.now ?? new Date()).toISOString().slice(0, 10));
7
+ const end = today - (options.includeToday ? 0 : day);
8
+ const iso = (value) => new Date(value).toISOString().slice(0, 10);
9
+ return {
10
+ current: { from: iso(end - (days - 1) * day), to: iso(end) },
11
+ previous: {
12
+ from: iso(end - (2 * days - 1) * day),
13
+ to: iso(end - days * day),
14
+ },
15
+ partial: options.includeToday === true,
16
+ };
17
+ }
18
+ const seriesKey = (row) => JSON.stringify([
19
+ row.project,
20
+ row.key,
21
+ Object.entries(row.dimensions).sort(([a], [b]) => a.localeCompare(b)),
22
+ ]);
23
+ /** Compare recorded observations; absent series have zero counts, never zero latency. */
24
+ export function compareMetrics(current, previous) {
25
+ const now = new Map(summarizeMetrics(current).map((row) => [seriesKey(row), row]));
26
+ const before = new Map(summarizeMetrics(previous).map((row) => [seriesKey(row), row]));
27
+ const change = (a, b) => ({
28
+ absolute: a - b,
29
+ percent: b === 0 ? (a === 0 ? 0 : null) : ((a - b) / b) * 100,
30
+ });
31
+ return [...new Set([...now.keys(), ...before.keys()])]
32
+ .map((key) => {
33
+ const a = now.get(key) ?? null;
34
+ const b = before.get(key) ?? null;
35
+ const metadata = a ?? b;
36
+ if (!metadata)
37
+ throw new Error("metrics: missing comparison series");
38
+ if (a && b && (a.kind !== b.kind || a.unit !== b.unit))
39
+ throw new Error(`metrics: changed meaning for ${metadata.project}.${metadata.key}; use a new key`);
40
+ return {
41
+ project: metadata.project,
42
+ key: metadata.key,
43
+ label: metadata.label,
44
+ kind: metadata.kind,
45
+ unit: metadata.unit,
46
+ dimensions: metadata.dimensions,
47
+ current: a,
48
+ previous: b,
49
+ countChange: change(a?.count ?? 0, b?.count ?? 0),
50
+ averageChange: a?.average != null && b?.average != null
51
+ ? change(a.average, b.average)
52
+ : null,
53
+ };
54
+ })
55
+ .sort((a, b) => a.project.localeCompare(b.project) ||
56
+ a.key.localeCompare(b.key) ||
57
+ Math.abs(b.countChange.absolute) - Math.abs(a.countChange.absolute) ||
58
+ seriesKey(a).localeCompare(seriesKey(b)));
59
+ }
1
60
  /** One report shape for terminal and web. No product names or metric lists. */
2
61
  export function summarizeMetrics(rows) {
3
62
  const totals = new Map();
@@ -15,6 +74,8 @@ export function summarizeMetrics(rows) {
15
74
  sum: 0,
16
75
  average: null,
17
76
  };
77
+ if (total.kind !== row.kind || total.unit !== row.unit)
78
+ throw new Error(`metrics: changed meaning for ${row.project}.${row.key}; use a new key`);
18
79
  total.count += row.count;
19
80
  total.sum += row.sum;
20
81
  total.average =
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"AA0BA,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,IAA4B;IAC5D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC9C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CACpC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CACrE,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;YAChC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,UAAU;YACV,KAAK,EAAE,CAAC;YACR,GAAG,EAAE,CAAC;YACN,OAAO,EAAE,IAAI;SACb,CAAC;QACF,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC;QACzB,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;QACrB,KAAK,CAAC,OAAO;YACZ,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC;gBACzC,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK;gBACzB,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACR,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC;QAClC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1B,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;QACjB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CACzE,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/metrics/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC/B,OAAO,CAAC,SAAS,EAAE;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;KAC7B,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;KAAE,CAAC,CAAC;IACzD,KAAK,CACJ,UAAU,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;KAAE,CAAC,EAChE,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,OAAO,CAAC,CAAC;CACpB;AAED,qEAAqE;AACrE,eAAO,MAAM,cAAc,g0BAKjB,CAAC;AAEX,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,IAGzD,GAAG,WAAW,mBAkC5B;AAED,uFAAuF;AACvF,wBAAsB,WAAW,CAChC,EAAE,EAAE,eAAe,EACnB,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAAC,WAAW,EAAE,CAAC,CAyBxB"}
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/metrics/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC/B,OAAO,CAAC,SAAS,EAAE;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;KAC7B,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;KAAE,CAAC,CAAC;IACzD,KAAK,CACJ,UAAU,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;KAAE,CAAC,EAChE,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,OAAO,CAAC,CAAC;CACpB;AAED,qEAAqE;AACrE,eAAO,MAAM,cAAc,g0BAKjB,CAAC;AAEX,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,IAGzD,GAAG,WAAW,mBAoC5B;AAED,uFAAuF;AACvF,wBAAsB,WAAW,CAChC,EAAE,EAAE,eAAe,EACnB,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAAC,WAAW,EAAE,CAAC,CAyBxB"}
@@ -12,7 +12,9 @@ export function sqliteMetricsWriter(db, project) {
12
12
  const dimensions = JSON.stringify(m.dimensions);
13
13
  const statements = [
14
14
  {
15
- sql: `INSERT INTO metric_definition VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT(project, key) DO UPDATE SET kind=excluded.kind, label=excluded.label, help=excluded.help, unit=excluded.unit`,
15
+ // NOT NULL makes a changed kind/unit fail the whole atomic batch, including counts.
16
+ // Labels/help may evolve, but historical measurements must retain their meaning.
17
+ sql: `INSERT INTO metric_definition VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT(project, key) DO UPDATE SET kind=CASE WHEN kind=excluded.kind THEN kind ELSE NULL END, label=excluded.label, help=excluded.help, unit=CASE WHEN unit=excluded.unit THEN unit ELSE NULL END`,
16
18
  args: [
17
19
  project,
18
20
  m.key,
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/metrics/sqlite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/metrics/sqlite.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adriangalilea/utils",
3
- "version": "4.0.0",
3
+ "version": "4.1.1",
4
4
  "description": "TypeScript utilities - logger, currency, formatter, GramIO bot plugins, and more",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",