@hanzo/event 0.3.38 → 0.3.40
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/LICENSE.md +21 -0
- package/dist/core.d.ts +13 -0
- package/dist/core.d.ts.map +1 -1
- package/dist/index.cjs +9 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +9 -2
- package/dist/index.mjs.map +1 -1
- package/dist/react.cjs +4 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.mjs +4 -1
- package/dist/react.mjs.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/package.json +16 -16
- package/src/core.ts +17 -0
- package/src/index.ts +8 -1
- package/src/stream.test.ts +14 -2
- package/src/version.ts +9 -1
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION
|
|
1
|
+
export declare const VERSION: string;
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,OAAO,EAAE,MAAgB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/event",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.40",
|
|
4
4
|
"description": "Hanzo Event — the ONE telemetry client. Emits pageview/event/identify/group to the Hanzo Cloud event stream (POST /v1/event), AND reports errors to Sentry as real Sentry envelopes — the error plane needs a DSN, without one nothing reaches Sentry. First-touch attribution, beacon-on-unload, auto error capture, client-side secret/PII scrubbing, a shared event + goal vocabulary. Subsumes @sentry.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -36,13 +36,6 @@
|
|
|
36
36
|
"funnel",
|
|
37
37
|
"hanzo"
|
|
38
38
|
],
|
|
39
|
-
"scripts": {
|
|
40
|
-
"build": "tsup && tsc --emitDeclarationOnly --declaration --outDir dist && node ../../scripts/dts.mjs",
|
|
41
|
-
"dev": "tsup --watch",
|
|
42
|
-
"test": "vitest run",
|
|
43
|
-
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
44
|
-
"clean": "rm -rf dist"
|
|
45
|
-
},
|
|
46
39
|
"exports": {
|
|
47
40
|
".": {
|
|
48
41
|
"import": {
|
|
@@ -74,14 +67,21 @@
|
|
|
74
67
|
}
|
|
75
68
|
},
|
|
76
69
|
"devDependencies": {
|
|
77
|
-
"@types/node": "
|
|
78
|
-
"@types/react": "
|
|
79
|
-
"react": "
|
|
80
|
-
"tsup": "
|
|
81
|
-
"typescript": "
|
|
82
|
-
"vitest": "
|
|
70
|
+
"@types/node": "26.4.0",
|
|
71
|
+
"@types/react": "19.2.18",
|
|
72
|
+
"react": "19.2.8",
|
|
73
|
+
"tsup": "^8.5.1",
|
|
74
|
+
"typescript": "7.0.2",
|
|
75
|
+
"vitest": "^4.1.11"
|
|
83
76
|
},
|
|
84
77
|
"dependencies": {
|
|
85
|
-
"@hanzo/events": "
|
|
78
|
+
"@hanzo/events": "0.2.2"
|
|
79
|
+
},
|
|
80
|
+
"scripts": {
|
|
81
|
+
"build": "tsup && tsc --emitDeclarationOnly --declaration --outDir dist && node ../../scripts/dts.mjs",
|
|
82
|
+
"dev": "tsup --watch",
|
|
83
|
+
"test": "vitest run",
|
|
84
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
85
|
+
"clean": "rm -rf dist"
|
|
86
86
|
}
|
|
87
|
-
}
|
|
87
|
+
}
|
package/src/core.ts
CHANGED
|
@@ -699,6 +699,23 @@ function registry(): Map<string, Analytics> {
|
|
|
699
699
|
return fresh
|
|
700
700
|
}
|
|
701
701
|
|
|
702
|
+
/** resetClients drops the page's clients, so the next `createAnalytics` for a
|
|
703
|
+
* stream builds a fresh one.
|
|
704
|
+
*
|
|
705
|
+
* A real page loads once and never needs this. A TEST RUNNER is what it exists
|
|
706
|
+
* for: one document, many mounts, each meant to be its own page. The second one
|
|
707
|
+
* gets a client that already counted this location, so its pageview is
|
|
708
|
+
* correctly suppressed and the suite reads it as "nothing was emitted".
|
|
709
|
+
*
|
|
710
|
+
* It is exported so a suite calls this instead of reaching for the slot itself.
|
|
711
|
+
* A consumer that deletes the registry from its own code path takes the
|
|
712
|
+
* guarantee with it: `<Provider/>` unmount/remount is not a new page, and the
|
|
713
|
+
* fresh client it would get counts the same view again. */
|
|
714
|
+
export function resetClients(): void {
|
|
715
|
+
const g = globalThis as unknown as Record<symbol, Map<string, Analytics> | undefined>
|
|
716
|
+
delete g[CLIENTS]
|
|
717
|
+
}
|
|
718
|
+
|
|
702
719
|
/** createAnalytics returns the client for a stream, building it on first ask.
|
|
703
720
|
* This is the ONE way to get a client: `new Analytics` bypasses the registry
|
|
704
721
|
* and is for tests and for a deliberately separate instance. */
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,14 @@
|
|
|
7
7
|
//
|
|
8
8
|
// React apps use the './react' entry for the provider + hooks + error boundary.
|
|
9
9
|
|
|
10
|
-
export {
|
|
10
|
+
export {
|
|
11
|
+
Analytics,
|
|
12
|
+
createAnalytics,
|
|
13
|
+
resetClients,
|
|
14
|
+
VERSION,
|
|
15
|
+
getCohort,
|
|
16
|
+
getFirstTouch,
|
|
17
|
+
} from './core'
|
|
11
18
|
export { parseDsn, buildSentryEvent, buildEnvelope, framesFromStack } from './sentry'
|
|
12
19
|
export { uuidv7, uuidv7Time } from './uid'
|
|
13
20
|
export { PRODUCT_PROJECT, dsnForProduct } from './dsn'
|
package/src/stream.test.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// Authorization at all (401, ingest_key_required) — because the library asked
|
|
9
9
|
// first and had no key. Both batches held a $pageview for the same page.
|
|
10
10
|
import { describe, it, expect, beforeEach } from 'vitest'
|
|
11
|
-
import { Analytics, createAnalytics } from './core'
|
|
11
|
+
import { Analytics, createAnalytics, resetClients } from './core'
|
|
12
12
|
import { PAGEVIEW } from './events'
|
|
13
13
|
import type { Transport, WireEvent } from './types'
|
|
14
14
|
|
|
@@ -57,7 +57,7 @@ const app = () =>
|
|
|
57
57
|
|
|
58
58
|
beforeEach(() => {
|
|
59
59
|
tx = new FakeTransport()
|
|
60
|
-
|
|
60
|
+
resetClients() // each `it` is its own page load
|
|
61
61
|
window.history.replaceState(null, '', '/pricing')
|
|
62
62
|
})
|
|
63
63
|
|
|
@@ -135,6 +135,18 @@ describe('one stream, one client', () => {
|
|
|
135
135
|
expect(createAnalytics({ product: 'site', host: HOST })).not.toBe(own)
|
|
136
136
|
})
|
|
137
137
|
|
|
138
|
+
// The registry is page state, and only a new page may drop it. A consumer that
|
|
139
|
+
// dropped it from its own code — @hanzogui/telemetry did this on every provider
|
|
140
|
+
// unmount — gives the next caller a client that has never seen this page, and
|
|
141
|
+
// the view is counted a second time. So the reset is named here, where a test
|
|
142
|
+
// runner can say "new page" and nothing else can say it by accident.
|
|
143
|
+
it('drops the page clients on reset, and only then', () => {
|
|
144
|
+
const before = createAnalytics({ product: 'site', host: HOST })
|
|
145
|
+
expect(createAnalytics({ product: 'site', host: HOST })).toBe(before)
|
|
146
|
+
resetClients()
|
|
147
|
+
expect(createAnalytics({ product: 'site', host: HOST })).not.toBe(before)
|
|
148
|
+
})
|
|
149
|
+
|
|
138
150
|
// The package publishes two entries and the react one carries its own copy of
|
|
139
151
|
// this module, so on a page that imports both there are two module scopes. A
|
|
140
152
|
// registry held in module scope is per-copy and would not dedupe the only case
|
package/src/version.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
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
|
-
|
|
4
|
+
//
|
|
5
|
+
// Read from package.json rather than restated, because a version restated is a
|
|
6
|
+
// version that drifts: 0.3.38 and 0.3.39 both shipped while this file still said
|
|
7
|
+
// 0.3.37, so every event those builds sent named a library that was two releases
|
|
8
|
+
// behind. `resolveJsonModule` inlines the literal at build time, and tsup shakes
|
|
9
|
+
// the rest of the manifest out.
|
|
10
|
+
import { version } from '../package.json'
|
|
11
|
+
|
|
12
|
+
export const VERSION: string = version
|