@adriangalilea/utils 4.1.0 → 5.0.0

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
@@ -7,21 +7,36 @@ TypeScript utilities - logger, currency, offensive programming, file operations,
7
7
  ```ts
8
8
  import { createClient } from "@libsql/client"
9
9
  import { defineMetrics } from "@adriangalilea/utils/metrics"
10
- import { sqliteMetricsWriter } from "@adriangalilea/utils/metrics/sqlite"
10
+ import { libsqlDriver } from "@adriangalilea/utils/metrics/libsql"
11
+ import { metricsWriter } from "@adriangalilea/utils/metrics/sqlite"
11
12
 
12
- const db = createClient({ url: process.env.METRICS_DATABASE_URL!, authToken: process.env.METRICS_AUTH_TOKEN })
13
+ const driver = libsqlDriver(createClient({ url: process.env.METRICS_DATABASE_URL!, authToken: process.env.METRICS_AUTH_TOKEN }))
13
14
  const metrics = defineMetrics({
14
15
  installCopy: { kind: "counter", label: "install command copies", dimensions: { component: ["chat", "glass"] } },
15
- }, { write: sqliteMetricsWriter(db, "my-project") })
16
+ }, { write: metricsWriter(driver, "my-project") })
16
17
 
17
18
  await metrics.installCopy.bump({ dimensions: { component: "chat" } })
18
19
  ```
19
20
 
21
+ One SQLite dialect, many stores. `metrics/sqlite` holds the schema, the writer and
22
+ the readers over a `MetricsDriver`: two verbs, `query(statement)` for rows and
23
+ `transact(statements)` for an all-or-nothing write batch. `metrics/libsql` wraps a
24
+ Turso / libSQL client, `metrics/d1` wraps a Cloudflare D1 binding (`d1Driver(env.DB)`),
25
+ each with the driver's native calls and structural types, so no database client is
26
+ bundled. Any other SQLite driver implements the two verbs in a few lines (the test
27
+ does it over `node:sqlite`). A store that does not speak SQLite implements the
28
+ injected `write(measurement)` contract and its own readers returning the
29
+ `metrics/report` types.
30
+
20
31
  Provision the exported `METRICS_SCHEMA` once before collecting. `describe()` returns
21
- the declarations; the SQL writer stores labels beside daily counters so reports
22
- discover metrics without another hardcoded list. `readMetrics(db, { from, to,
32
+ the declarations; the writer stores labels beside daily counters so reports
33
+ discover metrics without another hardcoded list. `readMetrics(driver, { from, to,
23
34
  project? })` returns daily rows with labels and dimensions, using inclusive UTC dates.
24
- Readers propagate database errors rather than presenting missing data as zero.
35
+ `readAudience(driver, { from, to, project }, describe().overlaps)` answers who did it
36
+ from the opt-in per-user rows: per key, distinct actors, actors with more than one
37
+ sample on a single day, actors seen on more than one day, then each declared
38
+ overlap as `fromUsers` and `bothUsers`. Readers propagate database errors rather
39
+ than presenting missing data as zero.
25
40
  `summarizeMetrics(rows)` from `metrics/report` produces one generic report shape;
26
41
  `renderMetrics(rows, { daily? })` from `metrics/cli` renders it with the existing
27
42
  ANSI-aware `cli.table` helpers. Both discover every recorded metric from its
@@ -37,8 +52,8 @@ disappearing series, count changes and weighted timing-average changes. Percent
37
52
  change is null without a nonzero baseline; missing timing samples stay null.
38
53
  Changing a metric's kind or unit across the inputs is rejected. Missing observations
39
54
  are not proof that collection was running: deltas compare recorded data only.
40
- The SQL adapter accepts a libSQL-compatible client; D1 or another store can implement
41
- the injected `write(measurement)` contract instead. No database client is bundled.
55
+ The writer rejects changes to an existing key's kind or unit atomically, before
56
+ adding observations. Use a new key for a new meaning; labels and help can be edited.
42
57
 
43
58
  Measurements validate finite nonnegative samples, positive integer counts, and
44
59
  declared dimension values. Calls resolve even when validation or storage fails;
@@ -53,16 +68,15 @@ Enable it only with a deletion and retention policy; no identity is inferred.
53
68
  `overlaps: [["a", "b"]]` declares unordered audience overlap, not an ordered funnel.
54
69
  Daily totals support counts and averages, not percentile latency or event ordering.
55
70
 
56
- **4.0 migration:** import `DailyMetric` from `metrics/report`, not `metrics/sqlite`.
57
- Report types and renderers are store-independent; SQLite is one optional adapter.
58
- This removes the old type export rather than retaining a compatibility alias.
59
-
60
- **3.0 migration:** `bot/metrics` and its bot-barrel export are removed. Import
61
- `@adriangalilea/utils/metrics`; replace `write(key, count, sum, user)` with
62
- `write({ key, count, sum, user, day, dimensions, spec })`. Rename `funnels` to
63
- `overlaps` in declarations and schema consumers. Existing stores can adapt the new
64
- write object without moving historical data. Metric keys and dimensions are storage
65
- identifiers: introduce a new key when changing meaning rather than relabelling history.
71
+ **5.0 migration:** `sqliteMetricsWriter(client, project)` and `MetricsDatabase` are
72
+ gone. Wrap the client in a driver, `libsqlDriver(client)` or `d1Driver(binding)`, and
73
+ pass it to `metricsWriter(driver, project)`, `readMetrics(driver, …)` and the new
74
+ `readAudience(driver, …)`. A private store with its own tables moves its rows into
75
+ `METRICS_SCHEMA` (`project`, `key`, `dimensions` as `'{}'` when it had none, `day`,
76
+ `user` as text) and seeds `metric_definition` for the keys it already holds, or the
77
+ history stays invisible to `readMetrics` until each key's first write. Metric keys and
78
+ dimensions are storage identifiers: introduce a new key when changing meaning rather
79
+ than relabelling history.
66
80
 
67
81
  ## Installation
68
82
 
@@ -0,0 +1,16 @@
1
+ import type { MetricsDriver } from "./sqlite.js";
2
+ /** The slice of Cloudflare D1 the metrics driver touches, typed structurally: no workers-types dependency. */
3
+ export interface D1Statement {
4
+ bind(...values: unknown[]): D1Statement;
5
+ all<T = Record<string, unknown>>(): Promise<{
6
+ results: T[];
7
+ }>;
8
+ }
9
+ export interface D1Binding {
10
+ prepare(sql: string): D1Statement;
11
+ /** D1 runs a batch as one transaction: a failing statement rolls back the whole sequence. */
12
+ batch(statements: D1Statement[]): Promise<unknown>;
13
+ }
14
+ /** A D1 binding as a metrics driver. */
15
+ export declare function d1Driver(db: D1Binding): MetricsDriver;
16
+ //# sourceMappingURL=d1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"d1.d.ts","sourceRoot":"","sources":["../../src/metrics/d1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,8GAA8G;AAC9G,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC;IACxC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;CAC9D;AACD,MAAM,WAAW,SAAS;IACzB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IAClC,6FAA6F;IAC7F,KAAK,CAAC,UAAU,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnD;AAED,wCAAwC;AACxC,wBAAgB,QAAQ,CAAC,EAAE,EAAE,SAAS,GAAG,aAAa,CAYrD"}
@@ -0,0 +1,11 @@
1
+ /** A D1 binding as a metrics driver. */
2
+ export function d1Driver(db) {
3
+ return {
4
+ query: async ({ sql, args }) => (await db
5
+ .prepare(sql)
6
+ .bind(...args)
7
+ .all()).results,
8
+ transact: (statements) => db.batch(statements.map((s) => db.prepare(s.sql).bind(...s.args))),
9
+ };
10
+ }
11
+ //# sourceMappingURL=d1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"d1.js","sourceRoot":"","sources":["../../src/metrics/d1.ts"],"names":[],"mappings":"AAaA,wCAAwC;AACxC,MAAM,UAAU,QAAQ,CAAC,EAAa;IACrC,OAAO;QACN,KAAK,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAC9B,CACC,MAAM,EAAE;aACN,OAAO,CAAC,GAAG,CAAC;aACZ,IAAI,CAAC,GAAG,IAAI,CAAC;aACb,GAAG,EAAE,CACP,CAAC,OAAO;QACV,QAAQ,EAAE,CAAC,UAAU,EAAE,EAAE,CACxB,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;KACnE,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { MetricsDriver, SqlStatement } from "./sqlite.js";
2
+ /** The slice of `@libsql/client` the metrics driver touches, typed structurally: no client is bundled. */
3
+ export interface LibsqlClient {
4
+ execute(statement: SqlStatement): Promise<{
5
+ rows: Iterable<Record<string, unknown>>;
6
+ }>;
7
+ batch(statements: SqlStatement[], mode: "write"): Promise<unknown>;
8
+ }
9
+ /** A Turso / libSQL / sqld connection as a metrics driver; `batch` in write mode is one transaction. */
10
+ export declare function libsqlDriver(client: LibsqlClient): MetricsDriver;
11
+ //# sourceMappingURL=libsql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libsql.d.ts","sourceRoot":"","sources":["../../src/metrics/libsql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,0GAA0G;AAC1G,MAAM,WAAW,YAAY;IAC5B,OAAO,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC;QACzC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KACxC,CAAC,CAAC;IACH,KAAK,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAED,wGAAwG;AACxG,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,aAAa,CAKhE"}
@@ -0,0 +1,8 @@
1
+ /** A Turso / libSQL / sqld connection as a metrics driver; `batch` in write mode is one transaction. */
2
+ export function libsqlDriver(client) {
3
+ return {
4
+ query: async (statement) => (await client.execute(statement)).rows,
5
+ transact: (statements) => client.batch(statements, "write"),
6
+ };
7
+ }
8
+ //# sourceMappingURL=libsql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libsql.js","sourceRoot":"","sources":["../../src/metrics/libsql.ts"],"names":[],"mappings":"AAUA,wGAAwG;AACxG,MAAM,UAAU,YAAY,CAAC,MAAoB;IAChD,OAAO;QACN,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;QAClE,QAAQ,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC;KAC3D,CAAC;AACH,CAAC"}
@@ -11,6 +11,29 @@ export interface DailyMetric {
11
11
  count: number;
12
12
  sum: number;
13
13
  }
14
+ /** Per key, from opt-in per-user rows: keys nobody touched in the window are absent. */
15
+ export interface AudienceMetric {
16
+ project: string;
17
+ key: string;
18
+ /** Distinct actors. */
19
+ uniques: number;
20
+ /** Actors with more than one sample on a single day. */
21
+ repeatUsers: number;
22
+ /** Actors seen on more than one day. */
23
+ returningUsers: number;
24
+ }
25
+ /** Unordered: how many of `from`'s actors also touched `to`, in the same window. */
26
+ export interface AudienceOverlap {
27
+ project: string;
28
+ from: string;
29
+ to: string;
30
+ fromUsers: number;
31
+ bothUsers: number;
32
+ }
33
+ export interface Audience {
34
+ metrics: AudienceMetric[];
35
+ overlaps: AudienceOverlap[];
36
+ }
14
37
  export interface MetricTotal {
15
38
  project: string;
16
39
  key: string;
@@ -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,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,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,wFAAwF;AACxF,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,oFAAoF;AACpF,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACxB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC5B;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"}
@@ -74,6 +74,8 @@ export function summarizeMetrics(rows) {
74
74
  sum: 0,
75
75
  average: null,
76
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`);
77
79
  total.count += row.count;
78
80
  total.sum += row.sum;
79
81
  total.average =
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"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"}
@@ -1,25 +1,41 @@
1
1
  import type { Measurement } from "./index.js";
2
- import type { DailyMetric } from "./report.js";
3
- /** Structural libSQL interface; callers own connections and credentials. */
4
- export interface MetricsDatabase {
5
- execute(statement: {
6
- sql: string;
7
- args: Array<string | number>;
8
- }): Promise<{
9
- rows: Iterable<Record<string, unknown>>;
10
- }>;
11
- batch(statements: Array<{
12
- sql: string;
13
- args: Array<string | number>;
14
- }>, mode: "write"): Promise<unknown>;
2
+ import type { Audience, DailyMetric } from "./report.js";
3
+ export type SqlValue = string | number;
4
+ export interface SqlStatement {
5
+ sql: string;
6
+ args: SqlValue[];
7
+ }
8
+ /**
9
+ * The SQLite dialect below needs exactly two verbs from a store. `metrics/libsql` and
10
+ * `metrics/d1` implement them with each driver's native calls; any driver that speaks
11
+ * SQLite (node:sqlite, bun:sqlite, better-sqlite3) does the same in a few lines.
12
+ */
13
+ export interface MetricsDriver {
14
+ /** The rows of one read statement. */
15
+ query(statement: SqlStatement): Promise<Iterable<Record<string, unknown>>>;
16
+ /** Every statement or none: a constraint failure in any of them rolls the batch back. */
17
+ transact(statements: SqlStatement[]): Promise<unknown>;
15
18
  }
16
19
  /** Run explicitly during provisioning, never on a user's request. */
17
20
  export declare const METRICS_SCHEMA: readonly ["CREATE TABLE IF NOT EXISTS metric_definition (project TEXT NOT NULL, key TEXT NOT NULL, kind TEXT NOT NULL, label TEXT NOT NULL, help TEXT NOT NULL, unit TEXT NOT NULL, PRIMARY KEY(project, key))", "CREATE TABLE IF NOT EXISTS metric_daily (project TEXT NOT NULL, key TEXT NOT NULL, dimensions TEXT NOT NULL, day TEXT NOT NULL, count INTEGER NOT NULL CHECK(count >= 0), sum REAL NOT NULL CHECK(sum >= 0), PRIMARY KEY(project, key, dimensions, day))", "CREATE TABLE IF NOT EXISTS metric_user_daily (project TEXT NOT NULL, key TEXT NOT NULL, dimensions TEXT NOT NULL, day TEXT NOT NULL, user TEXT NOT NULL, count INTEGER NOT NULL CHECK(count >= 0), sum REAL NOT NULL CHECK(sum >= 0), PRIMARY KEY(project, key, dimensions, day, user))", "CREATE INDEX IF NOT EXISTS metric_user_identity ON metric_user_daily(project, user)"];
18
- export declare function sqliteMetricsWriter(db: MetricsDatabase, project: string): (m: Measurement) => Promise<void>;
21
+ export declare function metricsWriter(driver: MetricsDriver, project: string): (m: Measurement) => Promise<void>;
19
22
  /** Inclusive UTC dates. Errors propagate: unavailable data must never read as zero. */
20
- export declare function readMetrics(db: MetricsDatabase, range: {
23
+ export declare function readMetrics(driver: MetricsDriver, range: {
21
24
  from: string;
22
25
  to: string;
23
26
  project?: string;
24
27
  }): Promise<DailyMetric[]>;
28
+ /**
29
+ * Who did it, over the opt-in per-user rows of one project, all dimensions folded: per key,
30
+ * distinct actors, actors with more than one sample on a single day, actors seen on more
31
+ * than one day; then the declared unordered overlaps. Keys nobody touched are absent.
32
+ */
33
+ export declare function readAudience(driver: MetricsDriver, range: {
34
+ from: string;
35
+ to: string;
36
+ project: string;
37
+ }, overlaps: ReadonlyArray<{
38
+ from: string;
39
+ to: string;
40
+ }>): Promise<Audience>;
25
41
  //# sourceMappingURL=sqlite.d.ts.map
@@ -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,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AACvC,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,EAAE,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,sCAAsC;IACtC,KAAK,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3E,yFAAyF;IACzF,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvD;AAED,qEAAqE;AACrE,eAAO,MAAM,cAAc,g0BAKjB,CAAC;AAiBX,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,IAErD,GAAG,WAAW,mBAoC5B;AAED,uFAAuF;AACvF,wBAAsB,WAAW,CAChC,MAAM,EAAE,aAAa,EACrB,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,CAmBxB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CACjC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACpD,QAAQ,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GACnD,OAAO,CAAC,QAAQ,CAAC,CA0CnB"}
@@ -5,14 +5,29 @@ export const METRICS_SCHEMA = [
5
5
  `CREATE TABLE IF NOT EXISTS metric_user_daily (project TEXT NOT NULL, key TEXT NOT NULL, dimensions TEXT NOT NULL, day TEXT NOT NULL, user TEXT NOT NULL, count INTEGER NOT NULL CHECK(count >= 0), sum REAL NOT NULL CHECK(sum >= 0), PRIMARY KEY(project, key, dimensions, day, user))`,
6
6
  `CREATE INDEX IF NOT EXISTS metric_user_identity ON metric_user_daily(project, user)`,
7
7
  ];
8
- export function sqliteMetricsWriter(db, project) {
9
- if (!/^[a-z][a-z0-9-]*$/.test(project))
8
+ const PROJECT = /^[a-z][a-z0-9-]*$/;
9
+ const DAY = /^\d{4}-\d{2}-\d{2}$/;
10
+ function assertProject(project) {
11
+ if (!PROJECT.test(project))
10
12
  throw new Error("metrics: invalid project");
13
+ }
14
+ function assertRange(range) {
15
+ for (const day of [range.from, range.to]) {
16
+ if (!DAY.test(day) || new Date(day).toISOString().slice(0, 10) !== day)
17
+ throw new Error("metrics: invalid UTC date");
18
+ }
19
+ if (range.from > range.to)
20
+ throw new Error("metrics: reversed date range");
21
+ }
22
+ export function metricsWriter(driver, project) {
23
+ assertProject(project);
11
24
  return async (m) => {
12
25
  const dimensions = JSON.stringify(m.dimensions);
13
26
  const statements = [
14
27
  {
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`,
28
+ // NOT NULL makes a changed kind/unit fail the whole atomic batch, including counts.
29
+ // Labels/help may evolve, but historical measurements must retain their meaning.
30
+ 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
31
  args: [
17
32
  project,
18
33
  m.key,
@@ -40,23 +55,19 @@ export function sqliteMetricsWriter(db, project) {
40
55
  m.sum,
41
56
  ],
42
57
  });
43
- await db.batch(statements, "write");
58
+ await driver.transact(statements);
44
59
  };
45
60
  }
46
61
  /** Inclusive UTC dates. Errors propagate: unavailable data must never read as zero. */
47
- export async function readMetrics(db, range) {
48
- for (const day of [range.from, range.to]) {
49
- if (!/^\d{4}-\d{2}-\d{2}$/.test(day) ||
50
- new Date(day).toISOString().slice(0, 10) !== day)
51
- throw new Error("metrics: invalid UTC date");
52
- }
53
- if (range.from > range.to)
54
- throw new Error("metrics: reversed date range");
55
- const result = await db.execute({
62
+ export async function readMetrics(driver, range) {
63
+ assertRange(range);
64
+ if (range.project !== undefined)
65
+ assertProject(range.project);
66
+ const rows = await driver.query({
56
67
  sql: `SELECT d.*, s.label, s.kind, s.help, s.unit FROM metric_daily d JOIN metric_definition s USING(project, key) WHERE day >= ? AND day <= ? ${range.project ? "AND project = ?" : ""} ORDER BY project, key, dimensions, day`,
57
68
  args: [range.from, range.to, ...(range.project ? [range.project] : [])],
58
69
  });
59
- return Array.from(result.rows, (r) => ({
70
+ return Array.from(rows, (r) => ({
60
71
  project: String(r.project),
61
72
  key: String(r.key),
62
73
  label: String(r.label),
@@ -69,4 +80,50 @@ export async function readMetrics(db, range) {
69
80
  sum: Number(r.sum),
70
81
  }));
71
82
  }
83
+ /**
84
+ * Who did it, over the opt-in per-user rows of one project, all dimensions folded: per key,
85
+ * distinct actors, actors with more than one sample on a single day, actors seen on more
86
+ * than one day; then the declared unordered overlaps. Keys nobody touched are absent.
87
+ */
88
+ export async function readAudience(driver, range, overlaps) {
89
+ assertRange(range);
90
+ assertProject(range.project);
91
+ const window = [range.project, range.from, range.to];
92
+ const perKey = await driver.query({
93
+ sql: `WITH per_day AS (SELECT key, user, day, SUM(count) AS count FROM metric_user_daily WHERE project = ? AND day >= ? AND day <= ? GROUP BY key, user, day), per_user AS (SELECT key, user, COUNT(*) AS days, MAX(count) AS peak FROM per_day GROUP BY key, user) SELECT key, COUNT(*) AS uniques, SUM(CASE WHEN peak > 1 THEN 1 ELSE 0 END) AS repeat_users, SUM(CASE WHEN days > 1 THEN 1 ELSE 0 END) AS returning_users FROM per_user GROUP BY key ORDER BY key`,
94
+ args: [...window],
95
+ });
96
+ const metrics = Array.from(perKey, (r) => ({
97
+ project: range.project,
98
+ key: String(r.key),
99
+ uniques: Number(r.uniques),
100
+ repeatUsers: Number(r.repeat_users),
101
+ returningUsers: Number(r.returning_users),
102
+ }));
103
+ const shared = [];
104
+ const actors = `SELECT DISTINCT user FROM metric_user_daily WHERE project = ? AND key = ? AND day >= ? AND day <= ?`;
105
+ for (const pair of overlaps) {
106
+ const [row] = Array.from(await driver.query({
107
+ sql: `WITH a AS (${actors}), b AS (${actors}) SELECT (SELECT COUNT(*) FROM a) AS from_users, (SELECT COUNT(*) FROM a WHERE user IN (SELECT user FROM b)) AS both_users`,
108
+ args: [
109
+ range.project,
110
+ pair.from,
111
+ range.from,
112
+ range.to,
113
+ range.project,
114
+ pair.to,
115
+ range.from,
116
+ range.to,
117
+ ],
118
+ }));
119
+ shared.push({
120
+ project: range.project,
121
+ from: pair.from,
122
+ to: pair.to,
123
+ fromUsers: Number(row?.from_users ?? 0),
124
+ bothUsers: Number(row?.both_users ?? 0),
125
+ });
126
+ }
127
+ return { metrics, overlaps: shared };
128
+ }
72
129
  //# sourceMappingURL=sqlite.js.map
@@ -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.1.0",
3
+ "version": "5.0.0",
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",
@@ -192,6 +192,14 @@
192
192
  "types": "./dist/metrics/sqlite.d.ts",
193
193
  "default": "./dist/metrics/sqlite.js"
194
194
  },
195
+ "./metrics/libsql": {
196
+ "types": "./dist/metrics/libsql.d.ts",
197
+ "default": "./dist/metrics/libsql.js"
198
+ },
199
+ "./metrics/d1": {
200
+ "types": "./dist/metrics/d1.d.ts",
201
+ "default": "./dist/metrics/d1.js"
202
+ },
195
203
  "./metrics/report": {
196
204
  "types": "./dist/metrics/report.d.ts",
197
205
  "default": "./dist/metrics/report.js"