@hanzo/event 0.3.20 → 0.3.22

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/dist/index.cjs CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var events = require('@hanzo/events');
4
+
3
5
  // src/attribution.ts
4
6
  var SOCIAL_HOSTS = [
5
7
  "facebook.",
@@ -82,70 +84,13 @@ var PRODUCT_PROJECT = Object.freeze({
82
84
  site: "019f9b1e-5785-7359-ad0b-f75db8e58c99"
83
85
  // hanzo.ai (marketing; product `site`)
84
86
  });
85
- function dsnForProduct(product) {
86
- if (!product) return void 0;
87
+ function dsnForProduct(product, key) {
88
+ if (!product || !key) return void 0;
87
89
  const projectId = PRODUCT_PROJECT[product];
88
90
  if (!projectId) return void 0;
89
- return `https://${HANZO_PUBLISHABLE_KEY}@api.hanzo.ai/v1/sentry/${projectId}`;
90
- }
91
- var HANZO_PUBLISHABLE_KEY = "pk-live-c88649f1085fb6ad441d8a0072933a9b";
92
- function defaultPublishableKey(host) {
93
- return host === void 0 || host === "https://api.hanzo.ai" ? HANZO_PUBLISHABLE_KEY : void 0;
91
+ return `https://${key}@api.hanzo.ai/v1/sentry/${projectId}`;
94
92
  }
95
93
 
96
- // src/events.ts
97
- var EVENTS = {
98
- // Signup funnel: view -> submit -> verify -> completed -> first action.
99
- SIGNUP_VIEWED: "signup_viewed",
100
- SIGNUP_SUBMITTED: "signup_submitted",
101
- SIGNUP_VERIFIED: "signup_verified",
102
- SIGNUP_COMPLETED: "signup_completed",
103
- /** A RETURNING user authenticated — the non-signup half of the IAM callback.
104
- * Keeping it distinct is what stops returning logins from inflating signups. */
105
- LOGIN_COMPLETED: "login_completed",
106
- /** Activation: the first moment of real value. ONE event for every product —
107
- * the product-specific moment is the `action` property (api_call, app_live,
108
- * chat_reply), never a new event name. */
109
- FIRST_ACTION: "first_action",
110
- // Waitlist + referral.
111
- WAITLIST_JOINED: "waitlist_joined",
112
- WAITLIST_SHARED: "waitlist_shared",
113
- REFERRAL_USED: "referral_used",
114
- REFERRAL_CLAIMED: "referral_claimed",
115
- // Upgrade-intent + purchase.
116
- PRICING_VIEWED: "pricing_viewed",
117
- PLAN_CLICKED: "plan_clicked",
118
- CHECKOUT_STARTED: "checkout_started",
119
- ORDER_COMPLETED: "order_completed",
120
- // Feature usage — generic + the common key surfaces across products.
121
- FEATURE_USED: "feature_used",
122
- API_KEY_CREATED: "api_key_created",
123
- APP_CREATED: "app_created",
124
- PROJECT_CREATED: "project_created",
125
- AGENT_CREATED: "agent_created",
126
- CHAT_STARTED: "chat_started",
127
- CHAT_MESSAGE_SENT: "chat_message_sent",
128
- /** The user switched model/endpoint — the single strongest quality signal a
129
- * chat surface emits (a switch usually follows a bad answer). */
130
- MODEL_SWITCHED: "model_switched",
131
- TASK_STARTED: "task_started",
132
- TASK_COMPLETED: "task_completed",
133
- // Build → ship. `build_*` is a MODEL producing an artifact; `deploy_*` is that
134
- // artifact going live. Intent (build_started) is never the same event as the
135
- // artifact existing (app_created) — conflating them makes the funnel lie.
136
- BUILD_STARTED: "build_started",
137
- /** A model finished producing an artifact (an app build, a chat reply, an agent
138
- * run). Carries `durationMs` — the outcome event owns its own duration, so no
139
- * paired start event is needed. */
140
- GENERATION_COMPLETED: "generation_completed",
141
- GENERATION_FAILED: "generation_failed",
142
- DEPLOY_STARTED: "deploy_started",
143
- DEPLOY_SUCCEEDED: "deploy_succeeded",
144
- DEPLOY_FAILED: "deploy_failed"
145
- };
146
- var PAGEVIEW = "$pageview";
147
- var EXCEPTION = "$exception";
148
-
149
94
  // src/scrub.ts
150
95
  var REDACTED = "[redacted]";
151
96
  var EMAIL_MARK = "[email]";
@@ -374,7 +319,7 @@ function uuidv7Time(id) {
374
319
  }
375
320
 
376
321
  // src/version.ts
377
- var VERSION = "0.3.20";
322
+ var VERSION = "0.3.21";
378
323
 
379
324
  // src/sentry.ts
380
325
  var MAX_FRAMES = 50;
@@ -825,27 +770,24 @@ var Analytics = class {
825
770
  enabled: true,
826
771
  captureErrors: true,
827
772
  ...config,
828
- // The publishable key resolves the SAME way the DSN below does, and now
829
- // ends the SAME way too — in a baked default, so declaring nothing is
830
- // enough. Most specific first:
773
+ // The publishable key resolves from ONE live source, never a literal baked
774
+ // beside the code. Most specific first:
831
775
  // 1. an explicit `ingestKey` in config;
832
776
  // 2. NEXT_PUBLIC_PUBLISHABLE_KEY, the inlined build-time env the fleet
833
- // carries end to end (KMS `deploy/PUBLISHABLE_KEY` -> the PUBLISHABLE_KEY
834
- // build-arg -> the NEXT_PUBLIC_ prefix Next inlines);
835
- // 3. the hanzo org key baked in `dsn.ts`, on the hanzo cloud only.
777
+ // carries end to end KMS `deploy/PUBLISHABLE_KEY` -> the PUBLISHABLE_KEY
778
+ // build-arg -> the NEXT_PUBLIC_ prefix Next inlines.
836
779
  //
837
- // (3) is why this is `publishable_key for all`: a hanzo surface that passes
838
- // no key in code and inlines no env still emits attributed, exactly as
839
- // declaring `product` is enough for the DSN. Without it that surface sent
840
- // its beacons to `$public` which drops every track/identify/group and
841
- // still answers 200 silent in the page and invisible until you read the
842
- // warehouse and find the host missing entirely. A white-label surface on
843
- // its own cloud (a non-default host) gets no default, so the org this
844
- // attributes to is never the wrong one.
845
- ingestKey: config.ingestKey ?? readEnv("NEXT_PUBLIC_PUBLISHABLE_KEY") ?? defaultPublishableKey(config.host ?? DEFAULT_HOST)
780
+ // A surface that provides neither has no key, and its anonymous traffic
781
+ // files under `$public` (which drops track/identify/group and answers 200);
782
+ // the fix is to give it the KMS-sourced env, not to hardcode the org key
783
+ // here. The key is a credential-class value: its home is KMS, and the ONE
784
+ // build reads it from there.
785
+ ingestKey: config.ingestKey ?? readEnv("NEXT_PUBLIC_PUBLISHABLE_KEY")
846
786
  };
847
787
  this.transport = config.transport ?? new DefaultTransport();
848
- this.dsn = parseDsn(config.dsn ?? readEnvDsn() ?? dsnForProduct(this.cfg.product));
788
+ this.dsn = parseDsn(
789
+ config.dsn ?? readEnvDsn() ?? dsnForProduct(this.cfg.product, this.cfg.ingestKey)
790
+ );
849
791
  }
850
792
  /** errorPlaneEnabled reports whether captured exceptions can actually reach the
851
793
  * error host. False means a DSN was never configured — the documented
@@ -900,7 +842,7 @@ var Analytics = class {
900
842
  /** pageview records a $pageview for the current (or given) location. */
901
843
  pageview(path, properties) {
902
844
  const p = path ?? (isBrowser() ? window.location.pathname : void 0);
903
- this.enqueue("pageview", PAGEVIEW, { path: p, properties });
845
+ this.enqueue("pageview", events.PAGEVIEW, { path: p, properties });
904
846
  }
905
847
  /** capture records a named product event with optional properties. Commerce
906
848
  * fields (productId/quantity/revenue/currency) may be passed for order events. */
@@ -933,7 +875,7 @@ var Analytics = class {
933
875
  const handled = context?.handled ?? true;
934
876
  const ex = normalizeError2(err);
935
877
  ex.handled = handled;
936
- this.enqueue("event", EXCEPTION, {
878
+ this.enqueue("event", events.EXCEPTION, {
937
879
  error: ex,
938
880
  properties: {
939
881
  ...context?.properties,
@@ -1103,11 +1045,11 @@ var FUNNELS = {
1103
1045
  products: ["site"],
1104
1046
  join: "person",
1105
1047
  steps: [
1106
- s(PAGEVIEW, "Landed"),
1107
- s(EVENTS.SIGNUP_VIEWED, "Opened signup"),
1108
- s(EVENTS.SIGNUP_SUBMITTED, "Redirected to Hanzo ID"),
1109
- s(EVENTS.SIGNUP_COMPLETED, "Account created"),
1110
- s(EVENTS.FIRST_ACTION, "First action")
1048
+ s(events.PAGEVIEW, "Landed"),
1049
+ s(events.EVENTS.SIGNUP_VIEWED, "Opened signup"),
1050
+ s(events.EVENTS.SIGNUP_SUBMITTED, "Redirected to Hanzo ID"),
1051
+ s(events.EVENTS.SIGNUP_COMPLETED, "Account created"),
1052
+ s(events.EVENTS.FIRST_ACTION, "First action")
1111
1053
  ]
1112
1054
  },
1113
1055
  /** The developer activation path: an account is worth nothing until a key has
@@ -1118,9 +1060,9 @@ var FUNNELS = {
1118
1060
  products: ["site", "cloud"],
1119
1061
  join: "person",
1120
1062
  steps: [
1121
- s(EVENTS.SIGNUP_COMPLETED, "Account created"),
1122
- s(EVENTS.API_KEY_CREATED, "Key minted"),
1123
- s(EVENTS.FIRST_ACTION, "First successful API call", {
1063
+ s(events.EVENTS.SIGNUP_COMPLETED, "Account created"),
1064
+ s(events.EVENTS.API_KEY_CREATED, "Key minted"),
1065
+ s(events.EVENTS.FIRST_ACTION, "First successful API call", {
1124
1066
  property: "action",
1125
1067
  equals: "api_call"
1126
1068
  })
@@ -1132,10 +1074,10 @@ var FUNNELS = {
1132
1074
  products: ["site", "app", "console"],
1133
1075
  join: "person",
1134
1076
  steps: [
1135
- s(EVENTS.PRICING_VIEWED, "Viewed pricing"),
1136
- s(EVENTS.PLAN_CLICKED, "Chose a plan"),
1137
- s(EVENTS.CHECKOUT_STARTED, "Started checkout"),
1138
- s(EVENTS.ORDER_COMPLETED, "Paid")
1077
+ s(events.EVENTS.PRICING_VIEWED, "Viewed pricing"),
1078
+ s(events.EVENTS.PLAN_CLICKED, "Chose a plan"),
1079
+ s(events.EVENTS.CHECKOUT_STARTED, "Started checkout"),
1080
+ s(events.EVENTS.ORDER_COMPLETED, "Paid")
1139
1081
  ]
1140
1082
  },
1141
1083
  /** hanzo.app: describe → build → deploy → live URL. The whole product thesis
@@ -1145,11 +1087,11 @@ var FUNNELS = {
1145
1087
  products: ["app"],
1146
1088
  join: "person",
1147
1089
  steps: [
1148
- s(PAGEVIEW, "Landed"),
1149
- s(EVENTS.BUILD_STARTED, "Described an app"),
1150
- s(EVENTS.GENERATION_COMPLETED, "Got a working build"),
1151
- s(EVENTS.DEPLOY_STARTED, "Hit publish"),
1152
- s(EVENTS.DEPLOY_SUCCEEDED, "Live URL")
1090
+ s(events.PAGEVIEW, "Landed"),
1091
+ s(events.EVENTS.BUILD_STARTED, "Described an app"),
1092
+ s(events.EVENTS.GENERATION_COMPLETED, "Got a working build"),
1093
+ s(events.EVENTS.DEPLOY_STARTED, "Hit publish"),
1094
+ s(events.EVENTS.DEPLOY_SUCCEEDED, "Live URL")
1153
1095
  ]
1154
1096
  },
1155
1097
  /** hanzo.chat: visit → first message → answer. `generation_completed` is what
@@ -1159,10 +1101,10 @@ var FUNNELS = {
1159
1101
  products: ["chat"],
1160
1102
  join: "person",
1161
1103
  steps: [
1162
- s(PAGEVIEW, "Landed"),
1163
- s(EVENTS.CHAT_STARTED, "Started a conversation"),
1164
- s(EVENTS.CHAT_MESSAGE_SENT, "Sent a message"),
1165
- s(EVENTS.GENERATION_COMPLETED, "Got an answer")
1104
+ s(events.PAGEVIEW, "Landed"),
1105
+ s(events.EVENTS.CHAT_STARTED, "Started a conversation"),
1106
+ s(events.EVENTS.CHAT_MESSAGE_SENT, "Sent a message"),
1107
+ s(events.EVENTS.GENERATION_COMPLETED, "Got an answer")
1166
1108
  ]
1167
1109
  },
1168
1110
  /** The cross-surface handoff: the hanzo.ai composer forwards its prompt to
@@ -1174,15 +1116,15 @@ var FUNNELS = {
1174
1116
  products: ["site", "chat"],
1175
1117
  join: "aggregate",
1176
1118
  steps: [
1177
- s(EVENTS.CHAT_STARTED, "Submitted the hanzo.ai composer", {
1119
+ s(events.EVENTS.CHAT_STARTED, "Submitted the hanzo.ai composer", {
1178
1120
  property: "source",
1179
1121
  equals: "composer"
1180
1122
  }),
1181
- s(EVENTS.CHAT_STARTED, "Landed in hanzo.chat", {
1123
+ s(events.EVENTS.CHAT_STARTED, "Landed in hanzo.chat", {
1182
1124
  property: "referrerProduct",
1183
1125
  equals: "site"
1184
1126
  }),
1185
- s(EVENTS.GENERATION_COMPLETED, "Got an answer")
1127
+ s(events.EVENTS.GENERATION_COMPLETED, "Got an answer")
1186
1128
  ]
1187
1129
  }
1188
1130
  };
@@ -1195,14 +1137,14 @@ var GOALS = {
1195
1137
  // Signup: the conversion is signup_completed, along the site signup funnel.
1196
1138
  signup: {
1197
1139
  label: "Signup",
1198
- event: EVENTS.SIGNUP_COMPLETED,
1140
+ event: events.EVENTS.SIGNUP_COMPLETED,
1199
1141
  funnelId: "signup",
1200
1142
  funnel: eventsOf("signup")
1201
1143
  },
1202
1144
  // Sale: a completed order qualified as a plan purchase (kind=plan).
1203
1145
  sale: {
1204
1146
  label: "Sale",
1205
- event: EVENTS.ORDER_COMPLETED,
1147
+ event: events.EVENTS.ORDER_COMPLETED,
1206
1148
  funnelId: "upgrade",
1207
1149
  funnel: eventsOf("upgrade"),
1208
1150
  filter: { property: "kind", equals: "plan" }
@@ -1210,7 +1152,7 @@ var GOALS = {
1210
1152
  // Upgrade intent: a plan click; pricing_viewed is the top of its funnel.
1211
1153
  upgradeIntent: {
1212
1154
  label: "Upgrade Intent",
1213
- event: EVENTS.PLAN_CLICKED,
1155
+ event: events.EVENTS.PLAN_CLICKED,
1214
1156
  funnelId: "upgrade",
1215
1157
  funnel: eventsOf("upgrade")
1216
1158
  },
@@ -1218,7 +1160,7 @@ var GOALS = {
1218
1160
  // valuable thing (a successful API call, a live app, a chat answer).
1219
1161
  activation: {
1220
1162
  label: "Activation",
1221
- event: EVENTS.FIRST_ACTION,
1163
+ event: events.EVENTS.FIRST_ACTION,
1222
1164
  funnelId: "apiActivation",
1223
1165
  funnel: eventsOf("apiActivation")
1224
1166
  }
@@ -1250,13 +1192,22 @@ var COHORTS = {
1250
1192
  * reformat of one copy is a diff against the other.
1251
1193
  */
1252
1194
 
1195
+ Object.defineProperty(exports, "EVENTS", {
1196
+ enumerable: true,
1197
+ get: function () { return events.EVENTS; }
1198
+ });
1199
+ Object.defineProperty(exports, "EXCEPTION", {
1200
+ enumerable: true,
1201
+ get: function () { return events.EXCEPTION; }
1202
+ });
1203
+ Object.defineProperty(exports, "PAGEVIEW", {
1204
+ enumerable: true,
1205
+ get: function () { return events.PAGEVIEW; }
1206
+ });
1253
1207
  exports.Analytics = Analytics;
1254
1208
  exports.COHORTS = COHORTS;
1255
- exports.EVENTS = EVENTS;
1256
- exports.EXCEPTION = EXCEPTION;
1257
1209
  exports.FUNNELS = FUNNELS;
1258
1210
  exports.GOALS = GOALS;
1259
- exports.PAGEVIEW = PAGEVIEW;
1260
1211
  exports.PRODUCTS = PRODUCTS;
1261
1212
  exports.PRODUCT_PROJECT = PRODUCT_PROJECT;
1262
1213
  exports.VERSION = VERSION;