@hanzo/event 0.3.15 → 0.3.17

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/src/core.test.ts CHANGED
@@ -360,26 +360,26 @@ describe('Analytics capture', () => {
360
360
  // The failure this closes is silent: a surface with no key attributes nothing
361
361
  // for a logged-out visitor, the door refuses the write, and the page shows no
362
362
  // sign of it. The key must resolve from the env exactly as the DSN does.
363
- process.env.NEXT_PUBLIC_EVENT_INGEST_KEY = 'pk-live-from-env'
363
+ process.env.NEXT_PUBLIC_PUBLISHABLE_KEY = 'pk-live-from-env'
364
364
  try {
365
365
  const a = mk() // no key in config
366
366
  a.capture('x')
367
367
  a.flush(true)
368
368
  expect(tx.sent[0].ingestKey).toBe('pk-live-from-env')
369
369
  } finally {
370
- delete process.env.NEXT_PUBLIC_EVENT_INGEST_KEY
370
+ delete process.env.NEXT_PUBLIC_PUBLISHABLE_KEY
371
371
  }
372
372
  })
373
373
 
374
374
  it('prefers an explicit ingest key over the build env', () => {
375
- process.env.NEXT_PUBLIC_EVENT_INGEST_KEY = 'pk-live-from-env'
375
+ process.env.NEXT_PUBLIC_PUBLISHABLE_KEY = 'pk-live-from-env'
376
376
  try {
377
377
  const a = mk({ ingestKey: 'pk-live-explicit' })
378
378
  a.capture('x')
379
379
  a.flush(true)
380
380
  expect(tx.sent[0].ingestKey).toBe('pk-live-explicit')
381
381
  } finally {
382
- delete process.env.NEXT_PUBLIC_EVENT_INGEST_KEY
382
+ delete process.env.NEXT_PUBLIC_PUBLISHABLE_KEY
383
383
  }
384
384
  })
385
385
 
@@ -394,7 +394,7 @@ describe('Analytics capture', () => {
394
394
  // The leak this closes: one console bundle is served to several brands, and a
395
395
  // pk- names ONE org. If an env-sourced key displaced the bearer, every
396
396
  // signed-in user's events would re-file under whichever org minted the key.
397
- process.env.NEXT_PUBLIC_EVENT_INGEST_KEY = 'pk-live-one-org'
397
+ process.env.NEXT_PUBLIC_PUBLISHABLE_KEY = 'pk-live-one-org'
398
398
  try {
399
399
  const a = mk({ getToken: () => 'jwt-of-a-real-person' })
400
400
  a.capture('x')
@@ -402,12 +402,12 @@ describe('Analytics capture', () => {
402
402
  expect(tx.sent[0].token).toBe('jwt-of-a-real-person')
403
403
  expect(tx.sent[0].ingestKey).toBeUndefined()
404
404
  } finally {
405
- delete process.env.NEXT_PUBLIC_EVENT_INGEST_KEY
405
+ delete process.env.NEXT_PUBLIC_PUBLISHABLE_KEY
406
406
  }
407
407
  })
408
408
 
409
409
  it('an anonymous visitor still rides the key', () => {
410
- process.env.NEXT_PUBLIC_EVENT_INGEST_KEY = 'pk-live-one-org'
410
+ process.env.NEXT_PUBLIC_PUBLISHABLE_KEY = 'pk-live-one-org'
411
411
  try {
412
412
  const a = mk({ getToken: () => undefined }) // logged out
413
413
  a.capture('x')
@@ -415,7 +415,7 @@ describe('Analytics capture', () => {
415
415
  expect(tx.sent[0].ingestKey).toBe('pk-live-one-org')
416
416
  expect(tx.sent[0].token).toBeUndefined()
417
417
  } finally {
418
- delete process.env.NEXT_PUBLIC_EVENT_INGEST_KEY
418
+ delete process.env.NEXT_PUBLIC_PUBLISHABLE_KEY
419
419
  }
420
420
  })
421
421
 
package/src/core.ts CHANGED
@@ -123,7 +123,14 @@ function normalizeError(err: unknown): Exception {
123
123
  return { type: n.name, message: n.message, stack: n.stack }
124
124
  }
125
125
 
126
- const isBrowser = () => typeof window !== 'undefined'
126
+ // React Native defines a `window` but no `document` (and no `window.location`),
127
+ // so `typeof window !== 'undefined'` alone took the browser path there and
128
+ // `init()` threw on `window.location.search`. Requiring `document` makes RN read
129
+ // as non-browser: `init()` returns early (skips attribution + the visibility/
130
+ // unload listeners RN doesn't have), while `capture()`/`flush()` — which are NOT
131
+ // gated on this and post through plain `fetch` — still emit. So the client is
132
+ // inert-safe under SSR/Node and live on RN, without a second transport.
133
+ const isBrowser = () => typeof window !== 'undefined' && typeof document !== 'undefined'
127
134
 
128
135
  /** serializeBatch stringifies a batch, salvaging what it can. `properties` is
129
136
  * arbitrary caller data — a DOM node, a React synthetic event, an axios error are
@@ -234,9 +241,9 @@ export class Analytics {
234
241
  // The publishable key resolves the SAME way the DSN below does: an explicit
235
242
  // config wins, else the inlined build-time env.
236
243
  //
237
- // NEXT_PUBLIC_EVENT_INGEST_KEY is that env, and it is the name the fleet
238
- // ALREADY carries end to end — KMS holds deploy/EVENT_INGEST_KEY, each
239
- // Dockerfile takes it as the EVENT_INGEST_KEY build-arg and re-exports it
244
+ // NEXT_PUBLIC_PUBLISHABLE_KEY is that env, and it is the name the fleet
245
+ // ALREADY carries end to end — KMS holds deploy/PUBLISHABLE_KEY, each
246
+ // Dockerfile takes it as the PUBLISHABLE_KEY build-arg and re-exports it
240
247
  // with the NEXT_PUBLIC_ prefix Next needs to inline it. Reading anything
241
248
  // else here would add a fourth spelling of one value.
242
249
  //
@@ -246,7 +253,7 @@ export class Analytics {
246
253
  // unattributed write is refused (401 ingest_key_required), which is silent
247
254
  // in the page and invisible until you read the warehouse and find the host
248
255
  // missing entirely.
249
- ingestKey: config.ingestKey ?? readEnv('NEXT_PUBLIC_EVENT_INGEST_KEY'),
256
+ ingestKey: config.ingestKey ?? readEnv('NEXT_PUBLIC_PUBLISHABLE_KEY'),
250
257
  }
251
258
  this.transport = config.transport ?? new DefaultTransport()
252
259
  // Error plane, most specific source first: an explicit DSN wins, then the
package/src/hz.test.ts CHANGED
@@ -230,8 +230,8 @@ describe('hz.js', () => {
230
230
  // keyed static surface therefore sent UNATTRIBUTED writes, which the door
231
231
  // refuses — silently, because nothing here reads the response.
232
232
 
233
- it('presents the ingest key as a bearer on fetch', () => {
234
- const r = runSnippet({ attrs: { 'data-ingest-key': 'pk-abc123' } })
233
+ it('presents the publishable key as a bearer on fetch', () => {
234
+ const r = runSnippet({ attrs: { 'data-publishable-key': 'pk-abc123' } })
235
235
  r.api!.flush()
236
236
  const post = r.posts.at(-1)!
237
237
  expect(post.via).toBe('fetch')
@@ -239,7 +239,7 @@ describe('hz.js', () => {
239
239
  expect(post.url).toBe('https://api.hanzo.ai/v1/event')
240
240
  })
241
241
 
242
- it('presents the ingest key in the query on a headerless beacon', () => {
242
+ it('still reads the retiring data-ingest-key, on a headerless beacon', () => {
243
243
  const r = runSnippet({ attrs: { 'data-ingest-key': 'pk-abc123' }, beacon: true })
244
244
  r.api!.flush()
245
245
  const post = r.posts.at(-1)!
package/src/types.ts CHANGED
@@ -120,11 +120,11 @@ export interface AnalyticsConfig {
120
120
  * a reading principal — so it is safe to ship in a bundle. Mint one per org with
121
121
  * POST /v1/keys {"type":"publishable"}.
122
122
  *
123
- * Omit it and the client reads NEXT_PUBLIC_EVENT_INGEST_KEY from the inlined
123
+ * Omit it and the client reads NEXT_PUBLIC_PUBLISHABLE_KEY from the inlined
124
124
  * build env, the same way `dsn` falls back — so a surface declares BOTH planes
125
125
  * in its build and neither needs code to switch on. That is the ONE spelling
126
- * the fleet already carries: KMS holds deploy/EVENT_INGEST_KEY, and each
127
- * Dockerfile takes EVENT_INGEST_KEY as a build-arg and re-exports it with the
126
+ * the fleet already carries: KMS holds deploy/PUBLISHABLE_KEY, and each
127
+ * Dockerfile takes PUBLISHABLE_KEY as a build-arg and re-exports it with the
128
128
  * NEXT_PUBLIC_ prefix that makes Next inline it.
129
129
  *
130
130
  * A surface with no key at all still reports for whoever is SIGNED IN (the
package/src/version.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  // The library version, stamped on every event (`libraryVersion`) and on the
2
2
  // Sentry `sdk` block. It lives alone so `sentry.ts` can read it without importing
3
3
  // `core.ts` — core imports sentry, so the reverse would be an import cycle.
4
- export const VERSION = '0.3.15'
4
+ export const VERSION = '0.3.17'