hazo_umetrics 1.2.1 → 1.4.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.
Files changed (38) hide show
  1. package/CHANGE_LOG.md +46 -1
  2. package/README.md +162 -1
  3. package/SETUP_CHECKLIST.md +47 -6
  4. package/config/hazo_umetrics_config.ini.sample +16 -5
  5. package/dist/api/index.d.ts +17 -0
  6. package/dist/api/index.d.ts.map +1 -1
  7. package/dist/api/index.js +126 -2
  8. package/dist/lib/index.d.ts +1 -0
  9. package/dist/lib/index.d.ts.map +1 -1
  10. package/dist/lib/index.js +1 -0
  11. package/dist/server/actions.d.ts +44 -0
  12. package/dist/server/actions.d.ts.map +1 -1
  13. package/dist/server/actions.js +95 -13
  14. package/dist/server/behavior.d.ts +83 -1
  15. package/dist/server/behavior.d.ts.map +1 -1
  16. package/dist/server/behavior.js +195 -0
  17. package/dist/server/connect.d.ts +11 -0
  18. package/dist/server/connect.d.ts.map +1 -0
  19. package/dist/server/connect.js +58 -0
  20. package/dist/server/types.d.ts +9 -1
  21. package/dist/server/types.d.ts.map +1 -1
  22. package/dist/ui/actions_panel.d.ts.map +1 -1
  23. package/dist/ui/actions_panel.js +98 -7
  24. package/dist/ui/analytics_panel.d.ts +9 -1
  25. package/dist/ui/analytics_panel.d.ts.map +1 -1
  26. package/dist/ui/analytics_panel.js +55 -7
  27. package/dist/ui/datapoint_panel.d.ts +19 -0
  28. package/dist/ui/datapoint_panel.d.ts.map +1 -0
  29. package/dist/ui/datapoint_panel.js +71 -0
  30. package/dist/ui/index.d.ts +2 -0
  31. package/dist/ui/index.d.ts.map +1 -1
  32. package/dist/ui/index.js +2 -0
  33. package/dist/ui/journey_panel.d.ts +51 -0
  34. package/dist/ui/journey_panel.d.ts.map +1 -0
  35. package/dist/ui/journey_panel.js +95 -0
  36. package/migrations/db_setup_postgres.sql +27 -10
  37. package/migrations/db_setup_sqlite.sql +27 -10
  38. package/package.json +5 -1
package/CHANGE_LOG.md CHANGED
@@ -1,9 +1,54 @@
1
1
  # hazo_umetrics — Change Log
2
2
 
3
- ## 1.3.0 — Analytics dashboard + behavioral fixes
3
+ ## 1.4.0 — Bulk catalog edits, per-action datapoints, user-journey viz, real user identity
4
+
5
+ **New features (minor bump — no breaking changes):**
6
+
7
+ ### New: Bulk multiselect in Action Catalog
8
+ - `updateActionDefBulk(adapter, {app_id, action_keys, patch})` — update many actions at once.
9
+ - `applyLinksBulk(adapter, {app_id, action_keys, add_related, remove_related})` — cartesian add/remove related links.
10
+ - `POST /actions/bulk` API: set status, key-event flag, parent, and related actions across N actions in one request. Permission: `metrics.manage`.
11
+ - UI: checkbox column + `BulkActionBar` (status select, key-event toggles, parent picker, related add/remove) appear above the tree when ≥1 action selected.
12
+
13
+ ### New: Per-action datapoint schema
14
+ - `datapoint_schema JSONB/TEXT` column on `hazo_umetrics_action_def` (migration: `ALTER TABLE hazo_umetrics_action_def ADD COLUMN datapoint_schema JSONB NOT NULL DEFAULT '[]'` for PG; `TEXT` for SQLite).
15
+ - `DatapointField`, `DatapointSchema` types exported from `hazo_umetrics`.
16
+ - JSON textarea in the Action Catalog edit form to declare which `dimensions` keys are meaningful.
17
+ - `datapointStats(adapter, opts)` — aggregates dimension values (numeric histograms + categorical top lists).
18
+ - `GET /analytics/datapoints?app_id=&action_key=` — returns `{action_key, total_events, keys[]}`.
19
+ - `DatapointPanel` component: action picker + per-key cards (histogram bars for numeric, ranked list for categorical).
20
+
21
+ ### New: User-journey aggregation + graph
22
+ - `userJourney(adapter, opts)` — groups events by session, computes per-step timing, emits `JourneyGraph` (nodes + edges with avgMs).
23
+ - `GET /analytics/journey?app_id=[&user_id=][&session_id=]` — returns `{sessions, graph}`.
24
+ - `JourneyPanel` component: dagre LR graph via `hazo_canvas` (optional peer dep) with edge timing labels; falls back to ordered step list when canvas unavailable.
25
+ - `hazo_canvas` ≥1.9.1 required for timing labels on dagre edges (`direction:'LR'`).
26
+
27
+ ### New: Host-injected user identity
28
+ - `resolveUserProfiles?: ResolveUserProfiles` prop on `AnalyticsPanel` and `JourneyPanel`.
29
+ - UserFilter dropdown now shows `name / email / avatar` when resolver is wired; falls back to truncated UUID.
30
+ - JourneyPanel session headers show resolved name/email/avatar.
31
+ - Test-app: `POST /api/hazo_umetrics/user_profiles` route wires `hazo_auth` `get_profiles` as an example host implementation.
32
+
33
+ ### hazo_canvas 1.9.1
34
+ - Dagre edge `label` field now rendered as a midpoint `kind:'text'` child (timing labels for journey viz).
35
+
36
+ ---
37
+
38
+ ## 1.3.0 — Analytics dashboard + behavioral fixes + createUmetricsConnect
4
39
 
5
40
  **New features + bug fixes (no breaking changes):**
6
41
 
42
+ ### New: `createUmetricsConnect` — dedicated DB factory
43
+ - `createUmetricsConnect(opts?)` builds a `HazoConnectAdapter` from `HAZO_UMETRICS_DATABASE_*`
44
+ env vars (type / URL / API key / SQLite path), with INI `[database]` as fallback. Returns a
45
+ cached adapter on no-arg calls; creates fresh when opts are passed.
46
+ - Exported from main `hazo_umetrics` entry: `import { createUmetricsConnect } from 'hazo_umetrics'`
47
+ - `UmetricsConnectOptions` type exported alongside the factory.
48
+ - Enables wiring umetrics to a **separate DB** from the host app in one line:
49
+ `createStatHandlers({ getAdapter: createUmetricsConnect })`
50
+ - Updated `config/hazo_umetrics_config.ini.sample` `[database]` section with dedicated env-var docs.
51
+
7
52
  ### New: `topActions` behavior aggregation
8
53
  - `topActions` function in `src/server/behavior.ts` — ranks all `action.*` events by frequency, no `user_id` required. Answers "what is the most common action?" without needing session segmentation.
9
54
  - Exposed as `metric=top_actions` in `GET /api/hazo_umetrics/analytics/behavior`.
package/README.md CHANGED
@@ -125,6 +125,128 @@ trackAction('timer.complete', { url: '/timer' });
125
125
 
126
126
  Auto-tracked on mount: page views (`ui.pageview.*`), clicks (`ui.click.*`), errors (`ui.error.*`), dwell time (`ui.dwell.*`).
127
127
 
128
+ ## Bulk Action Catalog edits
129
+
130
+ ```ts
131
+ // POST /api/hazo_umetrics/actions/bulk
132
+ // Body: { app_id, action_keys, patch?, add_related?, remove_related? }
133
+ // Permission: metrics.manage
134
+ // Response: { ok: true, data: { updated: string[], missing: string[], links: { added, removed } } }
135
+
136
+ // Set status on many actions at once
137
+ await fetch('/api/hazo_umetrics/actions/bulk', {
138
+ method: 'POST',
139
+ body: JSON.stringify({
140
+ app_id: 'my-app',
141
+ action_keys: ['timer.start', 'timer.complete'],
142
+ patch: { status: 'active', is_key_event: true },
143
+ }),
144
+ });
145
+
146
+ // Add related links in bulk (cartesian: every key in action_keys ↔ every key in add_related)
147
+ await fetch('/api/hazo_umetrics/actions/bulk', {
148
+ method: 'POST',
149
+ body: JSON.stringify({
150
+ app_id: 'my-app',
151
+ action_keys: ['timer.start'],
152
+ add_related: ['timer.complete', 'timer.pause'],
153
+ }),
154
+ });
155
+ ```
156
+
157
+ `action_keys` must be a non-empty array — an empty array returns 400. Both `patch` and `add_related`/`remove_related` can be combined in one request.
158
+
159
+ ## Per-action datapoint schema
160
+
161
+ Declare which `dimensions` keys are analytically meaningful for a given action:
162
+
163
+ ```ts
164
+ // PATCH the action to set a datapoint_schema
165
+ await fetch('/api/hazo_umetrics/actions?app_id=my-app', {
166
+ method: 'PATCH',
167
+ body: JSON.stringify({
168
+ app_id: 'my-app',
169
+ action_key: 'timer.complete',
170
+ patch: {
171
+ datapoint_schema: [
172
+ { key: 'duration_ms', label: 'Duration (ms)', type: 'number' },
173
+ { key: 'mode', label: 'Timer mode', type: 'string' },
174
+ ],
175
+ },
176
+ }),
177
+ });
178
+ ```
179
+
180
+ Types exported from `hazo_umetrics`: `DatapointField`, `DatapointSchema`.
181
+
182
+ Once a schema is set, the `DatapointPanel` UI component shows per-key cards: histogram bars for `type:'number'` keys, ranked frequency lists for `type:'string'` keys.
183
+
184
+ ## Journey analytics
185
+
186
+ ```ts
187
+ // GET /api/hazo_umetrics/analytics/journey?app_id=<id>[&user_id=<id>][&session_id=<id>]
188
+ // Permission: metrics.view
189
+ // Response: { ok: true, data: { sessions: Session[], graph: JourneyGraph } }
190
+ ```
191
+
192
+ `sessions` is an ordered list of per-session step arrays with timing. `graph.nodes` and `graph.edges` provide the aggregated action-transition graph for all sessions (or filtered by user/session). Each edge carries `avgMs` (mean inter-step latency).
193
+
194
+ ```tsx
195
+ import { JourneyPanel } from 'hazo_umetrics/ui';
196
+
197
+ // Embedded panel — fetches journey data from /api/hazo_umetrics/analytics/journey
198
+ <JourneyPanel
199
+ appId="my-app"
200
+ resolveUserProfiles={resolveUserProfiles} // optional — enriches session headers
201
+ />
202
+ ```
203
+
204
+ `JourneyPanel` renders a dagre LR graph via `hazo_canvas` when installed (`npm install hazo_canvas@^1.9.1`). Without `hazo_canvas`, it falls back to an ordered step list. Dagre edge timing labels require `hazo_canvas ≥ 1.9.1`.
205
+
206
+ ## Datapoint analytics
207
+
208
+ ```ts
209
+ // GET /api/hazo_umetrics/analytics/datapoints?app_id=<id>&action_key=<key>
210
+ // Permission: metrics.view
211
+ // Response: { ok: true, data: { action_key, total_events, keys: DatapointKeyStats[] } }
212
+ ```
213
+
214
+ Each entry in `keys` describes one dimension: `{ key, type, total, histogram | topValues }`. Use the `DatapointPanel` component to render these automatically.
215
+
216
+ ## resolveUserProfiles — wiring user identity
217
+
218
+ `AnalyticsPanel` and `JourneyPanel` both accept an optional `resolveUserProfiles` prop that enriches user IDs with real names, emails, and avatars:
219
+
220
+ ```ts
221
+ import type { ResolveUserProfiles } from 'hazo_umetrics/ui';
222
+
223
+ const resolveUserProfiles: ResolveUserProfiles = async (ids) => {
224
+ const r = await fetch('/api/my-app/user_profiles', {
225
+ method: 'POST',
226
+ body: JSON.stringify({ ids }),
227
+ headers: { 'Content-Type': 'application/json' },
228
+ });
229
+ const j = await r.json();
230
+ return j.profiles ?? [];
231
+ };
232
+
233
+ // Each profile: { user_id, email?, name?, profile_picture_url? }
234
+ ```
235
+
236
+ **Wiring with `hazo_auth` (gotimer / kinstripe pattern):**
237
+
238
+ ```ts
239
+ // app/api/hazo_umetrics/user_profiles/route.ts
240
+ import { authConnect } from '@/lib/db';
241
+ import { hazo_get_user_profiles } from 'hazo_auth/server-lib';
242
+
243
+ export async function POST(req: Request) {
244
+ const { ids } = await req.json();
245
+ const result = await hazo_get_user_profiles(authConnect, ids);
246
+ return Response.json({ profiles: result.profiles ?? [] });
247
+ }
248
+ ```
249
+
128
250
  ## API route factories
129
251
 
130
252
  ```ts
@@ -139,7 +261,46 @@ const expHandlers = createExperimentHandlers({ getAdapter: () => myAdapter });
139
261
 
140
262
  ## DB setup
141
263
 
142
- Run `db_setup_sqlite.sql` (SQLite) or `db_setup_postgres.sql` (PostgreSQL) once. Creates 7 tables, all prefixed `hazo_umetrics_`.
264
+ Run `db_setup_sqlite.sql` (SQLite) or `db_setup_postgres.sql` (PostgreSQL) once against your **umetrics DB**. Creates 7 tables, all prefixed `hazo_umetrics_`.
265
+
266
+ > Run the migration against the **dedicated umetrics database**, not the host app's main DB.
267
+ > If you use `createUmetricsConnect()` (recommended), the umetrics DB is the one pointed to
268
+ > by `HAZO_UMETRICS_DATABASE_URL`.
269
+
270
+ ## Separate database for umetrics
271
+
272
+ `hazo_umetrics` data (events, stats, flags, experiments) should live in its own database,
273
+ **separate from the host app's main DB**. This keeps analytics writes from competing with
274
+ product data, lets you point multiple apps at one shared analytics store, and lets you
275
+ scale each independently.
276
+
277
+ Use `createUmetricsConnect()` to build a dedicated adapter in one line:
278
+
279
+ ```ts
280
+ import { createUmetricsConnect } from 'hazo_umetrics';
281
+
282
+ // Reads HAZO_UMETRICS_DATABASE_URL + HAZO_UMETRICS_DATABASE_API_KEY from env.
283
+ // Falls back to ./umetrics.sqlite when type=sqlite.
284
+ export const getUmetricsAdapter = createUmetricsConnect;
285
+ ```
286
+
287
+ Then inject it into every route factory:
288
+
289
+ ```ts
290
+ const handlers = createStatHandlers({ getAdapter: createUmetricsConnect });
291
+ ```
292
+
293
+ ### Env vars
294
+
295
+ | Variable | Required | Description |
296
+ |---|---|---|
297
+ | `HAZO_UMETRICS_DATABASE_URL` | PostgREST only | Base URL of the umetrics PostgREST server |
298
+ | `HAZO_UMETRICS_DATABASE_API_KEY` | PostgREST only | Bearer token for the umetrics PostgREST server |
299
+ | `HAZO_UMETRICS_DATABASE_TYPE` | No | `postgrest` (default) or `sqlite` |
300
+ | `HAZO_UMETRICS_DATABASE_PATH` | SQLite only | Path to the SQLite file (default: `./umetrics.sqlite`) |
301
+
302
+ These are independent of the host app's `POSTGREST_URL` / `POSTGREST_API_KEY` — the
303
+ analytics DB can be a completely different PostgREST instance (or a local SQLite file for dev).
143
304
 
144
305
  ## Config
145
306
 
@@ -17,6 +17,30 @@ npm install hazo_core hazo_connect hazo_auth hazo_secure hazo_audit hazo_api haz
17
17
  > `hazo_dataviz` is required when you render `MetricsPanel`/`StatTrend` — its `LineChart`
18
18
  > draws the trend chart (moved out of `hazo_ui` in the 4.0.0 chart migration).
19
19
 
20
+ ## ALTER TABLE for 1.4.0 (existing deployments only)
21
+
22
+ If you are upgrading an **existing** deployment from a version before 1.4.0, run these statements against your umetrics database before upgrading the package:
23
+
24
+ ```sql
25
+ -- PostgreSQL:
26
+ ALTER TABLE hazo_umetrics_action_def ADD COLUMN IF NOT EXISTS datapoint_schema JSONB NOT NULL DEFAULT '[]';
27
+
28
+ -- SQLite (does not support IF NOT EXISTS on ALTER TABLE — skip if column already exists):
29
+ ALTER TABLE hazo_umetrics_action_def ADD COLUMN datapoint_schema TEXT NOT NULL DEFAULT '[]';
30
+ ```
31
+
32
+ Fresh installations (using `db_setup_sqlite.sql` / `db_setup_postgres.sql` from 1.4.0+) already include this column — no ALTER TABLE needed.
33
+
34
+ **Optional — journey graph (hazo_canvas peer dep):**
35
+
36
+ `JourneyPanel` renders an interactive dagre LR graph when `hazo_canvas` is installed. Without it, the panel falls back to a plain ordered step list. Install only if you use `JourneyPanel`:
37
+
38
+ ```bash
39
+ npm install hazo_canvas@^1.9.1
40
+ ```
41
+
42
+ ---
43
+
20
44
  ## 2. Run DB migrations
21
45
 
22
46
  **SQLite:**
@@ -33,7 +57,24 @@ db.close();
33
57
 
34
58
  **PostgreSQL:** Run `node_modules/hazo_umetrics/db_setup_postgres.sql` against your database.
35
59
 
36
- ## 3. Set env vars for cookie signing
60
+ ## 3. Set env vars for the umetrics database
61
+
62
+ `createUmetricsConnect()` reads these variables to connect to the dedicated umetrics DB:
63
+
64
+ ```bash
65
+ # PostgREST mode (production / staging)
66
+ HAZO_UMETRICS_DATABASE_URL=https://your-umetrics-postgrest.example.com
67
+ HAZO_UMETRICS_DATABASE_API_KEY=<bearer-token>
68
+
69
+ # SQLite mode (local dev — omit DATABASE_URL to fall back to ./umetrics.sqlite)
70
+ # HAZO_UMETRICS_DATABASE_TYPE=sqlite
71
+ # HAZO_UMETRICS_DATABASE_PATH=./umetrics.sqlite
72
+ ```
73
+
74
+ > Run `db_setup_postgres.sql` (or `db_setup_sqlite.sql`) against this **umetrics DB**, not
75
+ > the host app's main database.
76
+
77
+ ## 4. Set env vars for cookie signing
37
78
 
38
79
  ```bash
39
80
  # Generate a 32-byte key: node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
@@ -41,11 +82,11 @@ HAZO_UMETRICS_COOKIE_KEY_CURRENT=v1
41
82
  HAZO_UMETRICS_COOKIE_KEY_v1=<base64-encoded 32-byte key>
42
83
  ```
43
84
 
44
- ## 4. Add config file (optional)
85
+ ## 5. Add config file (optional)
45
86
 
46
87
  Copy `node_modules/hazo_umetrics/config/hazo_umetrics_config.ini.sample` to your app's config directory as `hazo_umetrics_config.ini` and fill in `[ga4]` when ready for M1.
47
88
 
48
- ## 5. Mount API routes (Next.js)
89
+ ## 6. Mount API routes (Next.js)
49
90
 
50
91
  ```ts
51
92
  // app/api/hazo_umetrics/stats/route.ts
@@ -58,7 +99,7 @@ export async function GET(req: Request) { return handlers.getStat(req); }
58
99
  export async function POST(req: Request) { return handlers.recordStat(req); }
59
100
  ```
60
101
 
61
- ## 6. Wrap your app in HazoMetricsProvider (client)
102
+ ## 7. Wrap your app in HazoMetricsProvider (client)
62
103
 
63
104
  ```tsx
64
105
  // app/layout.tsx
@@ -73,7 +114,7 @@ export default function RootLayout({ children }) {
73
114
  }
74
115
  ```
75
116
 
76
- ## 7. Configure Tailwind (if you use hazo_umetrics UI components)
117
+ ## 8. Configure Tailwind (if you use hazo_umetrics UI components)
77
118
 
78
119
  `MetricsPanel` uses shadcn token utilities (`bg-background`, `text-muted-foreground`, `border`, etc.) from `hazo_ui`. Without the token definitions the dialog panel will render transparent. In your `globals.css`:
79
120
 
@@ -112,7 +153,7 @@ export default function RootLayout({ children }) {
112
153
 
113
154
  (Adjust `@import` and `@source` depth to match your project's distance from `node_modules`.)
114
155
 
115
- ## 8. Smoke test
156
+ ## 9. Smoke test
116
157
 
117
158
  ```ts
118
159
  import { recordStat, getLatestStat } from 'hazo_umetrics';
@@ -8,14 +8,25 @@
8
8
  app_id = my_app
9
9
 
10
10
  [database]
11
- ; Set type = postgrest to use a PostgREST HTTP adapter (recommended for production).
12
- ; Set type = sqlite for local development without a Postgres instance.
11
+ ; Dedicated hazo_umetrics database separate from the host app's main DB.
12
+ ; Use createUmetricsConnect() from hazo_umetrics to wire this adapter.
13
+ ;
14
+ ; type: postgrest (default) | sqlite
15
+ ; Env-var override: HAZO_UMETRICS_DATABASE_TYPE
13
16
  ; type = postgrest
17
+ ;
18
+ ; PostgREST mode (recommended for production):
19
+ ; base_url — the PostgREST server base URL
20
+ ; Env-var override: HAZO_UMETRICS_DATABASE_URL
14
21
  ; base_url = http://your-postgrest-host:4444
15
- ; api_key comes from POSTGREST_API_KEY env var do not store it here.
22
+ ; api_key bearer token (env only, never store in INI)
23
+ ; Set: HAZO_UMETRICS_DATABASE_API_KEY=<your-token>
24
+ ;
25
+ ; SQLite mode (local development without a Postgres instance):
26
+ ; database_path — path to the SQLite file (default: ./umetrics.sqlite)
27
+ ; Env-var override: HAZO_UMETRICS_DATABASE_PATH
16
28
  ; type = sqlite
17
- ; driver = better-sqlite3
18
- ; database_path = ./umetrics_test.sqlite
29
+ ; database_path = ./umetrics.sqlite
19
30
 
20
31
  [env]
21
32
  ; Uncomment to hard-code the environment name (overrides HAZO_ENV / NODE_ENV).
@@ -106,6 +106,13 @@ export declare function createActionHandlers(options: ApiFactoryOptions): {
106
106
  * Emits an audit entry 'action.catalog.update'.
107
107
  */
108
108
  updateAction(req: Request): Promise<Response>;
109
+ /**
110
+ * POST /...
111
+ * Body: { app_id, action_keys, patch?, add_related?, remove_related? }
112
+ * Bulk-updates multiple action defs and/or their links. Requires metrics.manage.
113
+ * Emits a single audit entry 'action.catalog.bulk_update' per call.
114
+ */
115
+ bulkUpdateActions(req: Request): Promise<Response>;
109
116
  };
110
117
  export declare function createActivityHandlers(options: ApiFactoryOptions): {
111
118
  /**
@@ -145,5 +152,15 @@ export declare function createBehaviorHandlers(options: ApiFactoryOptions): {
145
152
  * Returns events bucketed by day. Requires metrics.view.
146
153
  */
147
154
  getEventsOverTime(req: Request): Promise<Response>;
155
+ /**
156
+ * GET /...?app_id=<id>&action_key=<key>[&since=<iso>][&until=<iso>][&buckets=<n>][&top_n=<n>]
157
+ * Returns datapoint dimension stats for an action. Requires metrics.view.
158
+ */
159
+ getDatapoints(req: Request): Promise<Response>;
160
+ /**
161
+ * GET /...?app_id=<id>[&user_id=<id>][&session_id=<id>][&since=<iso>]
162
+ * Returns user journey sessions and aggregated graph. Requires metrics.view.
163
+ */
164
+ getJourney(req: Request): Promise<Response>;
148
165
  };
149
166
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"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"}
package/dist/api/index.js CHANGED
@@ -8,8 +8,8 @@ import { createCrudService } from 'hazo_connect/server';
8
8
  import { recordStat as _recordStat, getLatestStat as _getLatestStat, getStatSeries as _getStatSeries, } from '../server/stats.js';
9
9
  import { resolveVariant } from '../server/flags.js';
10
10
  import { getActivitySummary as _getActivitySummary, getActivityTrend as _getActivityTrend, } from '../server/activity.js';
11
- import { ensureActionDef as _ensureActionDef, listActions as _listActions, getActionTree as _getActionTree, updateActionDef as _updateActionDef, getLinks as _getLinks, addLink as _addLink, removeLink as _removeLink, } from '../server/actions.js';
12
- import { topActions as _topActions, firstSessionActions as _firstSessionActions, postReloginActions as _postReloginActions, actionsBeforeGoal as _actionsBeforeGoal, topErrors as _topErrors, tabDwell as _tabDwell, frequentActionsReturning as _frequentActionsReturning, eventsOverTime as _eventsOverTime, } from '../server/behavior.js';
11
+ import { ensureActionDef as _ensureActionDef, listActions as _listActions, getActionTree as _getActionTree, updateActionDef as _updateActionDef, updateActionDefBulk as _updateActionDefBulk, applyLinksBulk as _applyLinksBulk, getLinks as _getLinks, addLink as _addLink, removeLink as _removeLink, } from '../server/actions.js';
12
+ import { topActions as _topActions, firstSessionActions as _firstSessionActions, postReloginActions as _postReloginActions, actionsBeforeGoal as _actionsBeforeGoal, topErrors as _topErrors, tabDwell as _tabDwell, frequentActionsReturning as _frequentActionsReturning, eventsOverTime as _eventsOverTime, datapointStats as _datapointStats, userJourney as _userJourney, } from '../server/behavior.js';
13
13
  // ---------------------------------------------------------------------------
14
14
  // Default auth — dynamically imports hazo_auth/server-lib to avoid the
15
15
  // server-only guard firing at module-evaluation time (e.g. in test runners).
@@ -516,6 +516,67 @@ export function createActionHandlers(options) {
516
516
  });
517
517
  return jsonOk({ action: updated });
518
518
  },
519
+ /**
520
+ * POST /...
521
+ * Body: { app_id, action_keys, patch?, add_related?, remove_related? }
522
+ * Bulk-updates multiple action defs and/or their links. Requires metrics.manage.
523
+ * Emits a single audit entry 'action.catalog.bulk_update' per call.
524
+ */
525
+ async bulkUpdateActions(req) {
526
+ let body;
527
+ try {
528
+ body = (await req.json());
529
+ }
530
+ catch {
531
+ return jsonError('BAD_REQUEST', 'Invalid JSON body', 400);
532
+ }
533
+ const { app_id, action_keys, patch, add_related, remove_related } = body;
534
+ if (!app_id) {
535
+ return jsonError('BAD_REQUEST', 'app_id is required', 400);
536
+ }
537
+ if (!Array.isArray(action_keys) || action_keys.length === 0) {
538
+ return jsonError('BAD_REQUEST', 'action_keys must be a non-empty array', 400);
539
+ }
540
+ const gate = await gateAuth(req, {
541
+ required_permissions: ['metrics.manage'],
542
+ app_id,
543
+ getAuth,
544
+ });
545
+ if (!gate.ok)
546
+ return gate.response;
547
+ const adapter = await options.getAdapter();
548
+ const keys = action_keys;
549
+ let updated = [];
550
+ let missing = [];
551
+ let linksAdded = 0;
552
+ let linksRemoved = 0;
553
+ if (patch && Object.keys(patch).length > 0) {
554
+ const result = await _updateActionDefBulk(adapter, {
555
+ app_id,
556
+ action_keys: keys,
557
+ patch: patch,
558
+ });
559
+ updated = result.updated;
560
+ missing = result.missing;
561
+ }
562
+ if ((add_related && add_related.length > 0) || (remove_related && remove_related.length > 0)) {
563
+ const result = await _applyLinksBulk(adapter, {
564
+ app_id,
565
+ action_keys: keys,
566
+ add_related,
567
+ remove_related,
568
+ });
569
+ linksAdded = result.added;
570
+ linksRemoved = result.removed;
571
+ }
572
+ await options.onAudit?.({
573
+ action: 'action.catalog.bulk_update',
574
+ actor_id: gate.userId,
575
+ app_id,
576
+ details: { action_keys: keys, patch, add_related, remove_related },
577
+ });
578
+ return jsonOk({ updated, missing, links: { added: linksAdded, removed: linksRemoved } });
579
+ },
519
580
  };
520
581
  }
521
582
  // ---------------------------------------------------------------------------
@@ -744,5 +805,68 @@ export function createBehaviorHandlers(options) {
744
805
  const data = await _eventsOverTime(adapter, { app_id, since, userIds, limit: 10000, catalogMap, includeArchived, keyEventsOnly });
745
806
  return jsonOk({ data });
746
807
  },
808
+ /**
809
+ * GET /...?app_id=<id>&action_key=<key>[&since=<iso>][&until=<iso>][&buckets=<n>][&top_n=<n>]
810
+ * Returns datapoint dimension stats for an action. Requires metrics.view.
811
+ */
812
+ async getDatapoints(req) {
813
+ const url = new URL(req.url);
814
+ const app_id = url.searchParams.get('app_id') ?? '';
815
+ const action_key = url.searchParams.get('action_key') ?? '';
816
+ const since = url.searchParams.get('since') ?? undefined;
817
+ const until = url.searchParams.get('until') ?? undefined;
818
+ const bucketsParam = url.searchParams.get('buckets');
819
+ const buckets = bucketsParam != null ? parseInt(bucketsParam, 10) : undefined;
820
+ const topNParam = url.searchParams.get('top_n');
821
+ const topN = topNParam != null ? parseInt(topNParam, 10) : undefined;
822
+ const gate = await gateAuth(req, {
823
+ required_permissions: ['metrics.view'],
824
+ app_id: app_id || undefined,
825
+ getAuth,
826
+ });
827
+ if (!gate.ok)
828
+ return gate.response;
829
+ if (!app_id || !action_key) {
830
+ return jsonError('BAD_REQUEST', 'app_id and action_key are required', 400);
831
+ }
832
+ const adapter = await options.getAdapter();
833
+ const catalog = await _listActions(adapter, { app_id });
834
+ const matchingAction = catalog.find((a) => a.action_key === action_key);
835
+ const result = await _datapointStats(adapter, {
836
+ app_id,
837
+ action_key,
838
+ since,
839
+ until,
840
+ buckets,
841
+ topN,
842
+ schema: matchingAction?.datapoint_schema,
843
+ });
844
+ return jsonOk(result);
845
+ },
846
+ /**
847
+ * GET /...?app_id=<id>[&user_id=<id>][&session_id=<id>][&since=<iso>]
848
+ * Returns user journey sessions and aggregated graph. Requires metrics.view.
849
+ */
850
+ async getJourney(req) {
851
+ const url = new URL(req.url);
852
+ const app_id = url.searchParams.get('app_id') ?? '';
853
+ const user_id = url.searchParams.get('user_id') ?? undefined;
854
+ const session_id = url.searchParams.get('session_id') ?? undefined;
855
+ const since = url.searchParams.get('since') ?? undefined;
856
+ const gate = await gateAuth(req, {
857
+ required_permissions: ['metrics.view'],
858
+ app_id: app_id || undefined,
859
+ getAuth,
860
+ });
861
+ if (!gate.ok)
862
+ return gate.response;
863
+ if (!app_id)
864
+ return jsonError('BAD_REQUEST', 'app_id is required', 400);
865
+ const adapter = await options.getAdapter();
866
+ const catalog = await _listActions(adapter, { app_id });
867
+ const catalogMap = new Map(catalog.map((a) => [a.action_key, { label: a.label, datapoint_schema: a.datapoint_schema }]));
868
+ const result = await _userJourney(adapter, { app_id, user_id, session_id, since, catalogMap });
869
+ return jsonOk(result);
870
+ },
747
871
  };
748
872
  }
@@ -7,4 +7,5 @@ export * from '../server/ga4.js';
7
7
  export * from '../server/experiments.js';
8
8
  export * from '../server/activity.js';
9
9
  export * from '../server/behavior.js';
10
+ export * from '../server/connect.js';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AACA,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AACA,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC"}
package/dist/lib/index.js CHANGED
@@ -8,3 +8,4 @@ export * from '../server/ga4.js';
8
8
  export * from '../server/experiments.js';
9
9
  export * from '../server/activity.js';
10
10
  export * from '../server/behavior.js';
11
+ export * from '../server/connect.js';
@@ -1,5 +1,21 @@
1
1
  import type { HazoConnectAdapter } from 'hazo_connect/server';
2
2
  import type { ActionDef, ActionDefPatch, ActionNode, ActionLink } from './types.js';
3
+ type ActionDefRow = {
4
+ action_key: string;
5
+ app_id: string;
6
+ scope_id: string;
7
+ label: string;
8
+ description: string;
9
+ parent_key: string | null;
10
+ url: string | null;
11
+ is_key_event: number | boolean;
12
+ status: string;
13
+ datapoint_schema: string;
14
+ created_at: string;
15
+ updated_at: string;
16
+ [key: string]: unknown;
17
+ };
18
+ export declare function applyPatch(_existing: ActionDef, patch: ActionDefPatch): Partial<ActionDefRow>;
3
19
  /**
4
20
  * Insert-if-absent a draft def row. No-op after first sight (seen-set cached).
5
21
  * Called by the ingestion layer on every `action.*` event.
@@ -63,4 +79,32 @@ export declare function removeLink(adapter: HazoConnectAdapter, params: {
63
79
  action_key: string;
64
80
  related_key: string;
65
81
  }): Promise<void>;
82
+ /**
83
+ * Updates mutable fields across multiple action defs in one call.
84
+ * Returns lists of updated keys and missing (not found) keys.
85
+ */
86
+ export declare function updateActionDefBulk(adapter: HazoConnectAdapter, params: {
87
+ app_id: string;
88
+ action_keys: string[];
89
+ patch: ActionDefPatch;
90
+ }): Promise<{
91
+ updated: string[];
92
+ missing: string[];
93
+ }>;
94
+ /**
95
+ * Applies link additions and removals across multiple action keys (Cartesian product).
96
+ * For each action_key × each add_related key: calls addLink (idempotent, self-link guarded).
97
+ * For each action_key × each remove_related key: calls removeLink.
98
+ * Returns counts of added (non-null addLink results) and removed (all removeLink calls).
99
+ */
100
+ export declare function applyLinksBulk(adapter: HazoConnectAdapter, params: {
101
+ app_id: string;
102
+ action_keys: string[];
103
+ add_related?: string[];
104
+ remove_related?: string[];
105
+ }): Promise<{
106
+ added: number;
107
+ removed: number;
108
+ }>;
109
+ export {};
66
110
  //# sourceMappingURL=actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/server/actions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAoEpF;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE;IACN,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,GACA,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CAAC,SAAS,EAAE,CAAC,CAUtB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CAAC,UAAU,EAAE,CAAC,CAwBvB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE;IACN,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,cAAc,CAAC;CACvB,GACA,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAwB3B;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAsBD;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C,OAAO,CAAC,UAAU,EAAE,CAAC,CAoBvB;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACrF,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAsC5B;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAClE,OAAO,CAAC,IAAI,CAAC,CAiBf"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/server/actions.ts"],"names":[],"mappings":"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"}