@hogsend/core 0.18.0 → 0.19.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hogsend/core",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -32,7 +32,7 @@
32
32
  "drizzle-orm": "^0.45.2",
33
33
  "iana-db-timezones": "^0.3.0",
34
34
  "zod": "^4.4.3",
35
- "@hogsend/db": "^0.18.0"
35
+ "@hogsend/db": "^0.19.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "latest",
@@ -1,20 +1,113 @@
1
+ /**
2
+ * The provider-neutral ANALYTICS contract — the analytics sibling of
3
+ * {@link EmailProvider}. PostHog is one implementation
4
+ * (`@hogsend/plugin-posthog`'s `createPostHogProvider`), not the
5
+ * architecture: the engine speaks only this contract, so the event stream /
6
+ * person store can be Segment, Amplitude, Mixpanel, or the consumer's own
7
+ * service without touching engine code.
8
+ *
9
+ * A provider owns exactly three wires plus identity:
10
+ *
11
+ * - **person READ** — `getPersonProperties` (the identity PULL): per-user
12
+ * timezone resolution at journey enrollment and property conditions. On
13
+ * most platforms this requires a PRIVILEGED credential (e.g. PostHog's
14
+ * personal API key with `person:read`) because the public capture key is
15
+ * write-only by design.
16
+ * - **person WRITE** — `setPersonProperties`: trait propagation (contact →
17
+ * analytics person). On most platforms this rides the public capture
18
+ * pipeline (e.g. PostHog `$set`/`$set_once`) and needs NO extra credential.
19
+ * - **event capture** — `capture`: fire an event under a distinct id.
20
+ *
21
+ * Lifecycle fan-out (email/contact/journey/bucket events) does NOT flow
22
+ * through this contract — it rides outbound DESTINATIONS on the durable
23
+ * delivery spine. This contract is the request/response side: reads the
24
+ * engine needs inline, plus best-effort writes.
25
+ */
26
+
1
27
  /**
2
28
  * The minimal READ contract for the identity PULL: fetching a person's
3
- * properties by distinct id. This is the only role the engine still requires of
4
- * the injected analytics service at the hot path — per-user timezone resolution
29
+ * properties by distinct id. This is the only role the engine REQUIRES of the
30
+ * injected analytics provider at the hot path — per-user timezone resolution
5
31
  * at journey enrollment (`getPersonProperties` in `define-journey` /
6
- * `lib/timezone.ts`). It is intentionally narrow: the email/contact/journey/
7
- * bucket lifecycle fan-out now flows through outbound DESTINATIONS on the
8
- * durable spine, NOT through this provider.
9
- *
10
- * `PostHogService` satisfies `IdentityProvider` (it declares
11
- * `getPersonProperties` plus the deprecated capture/identify shims). Code that
12
- * only needs the PULL can depend on this narrower alias.
32
+ * `lib/timezone.ts`). Code that only needs the PULL can depend on this
33
+ * narrower alias.
13
34
  */
14
35
  export interface IdentityProvider {
15
36
  getPersonProperties(distinctId: string): Promise<Record<string, unknown>>;
16
37
  }
17
38
 
39
+ /**
40
+ * Person-property write payload: `set` overwrites, `setOnce` only-if-absent,
41
+ * `unset` removes keys (e.g. the bucket mirror clears membership flags on
42
+ * leave — `unset` rather than `set: false` so both "key = true" and "key is
43
+ * set" cohort idioms behave correctly).
44
+ */
45
+ export interface PersonPropertiesWrite {
46
+ set?: Record<string, unknown>;
47
+ setOnce?: Record<string, unknown>;
48
+ unset?: string[];
49
+ }
50
+
51
+ /** What an {@link AnalyticsProvider} can actually do, given its credentials. */
52
+ export interface AnalyticsCapabilities {
53
+ /**
54
+ * True when the provider is configured for person READS (e.g. PostHog has a
55
+ * personal API key with `person:read`). When false, `getPersonProperties`
56
+ * soft-fails to `{}` and the engine's fallbacks (contact properties →
57
+ * client default timezone) take over.
58
+ */
59
+ personReads: boolean;
60
+ /** True when person WRITES are available (usually the capture pipeline). */
61
+ personWrites: boolean;
62
+ /** True when the provider supports the `hogsend connect` OAuth flow. */
63
+ oauth?: boolean;
64
+ }
65
+
66
+ export interface AnalyticsProviderMeta {
67
+ /** Registry key, e.g. `"posthog"`, `"segment"`. */
68
+ id: string;
69
+ name: string;
70
+ description?: string;
71
+ }
72
+
73
+ /**
74
+ * The full provider contract. All methods are best-effort wires: a provider
75
+ * must soft-fail (resolve `{}` / no-op) rather than throw on missing
76
+ * credentials or upstream errors — the engine treats analytics as
77
+ * non-load-bearing.
78
+ */
79
+ export interface AnalyticsProvider extends IdentityProvider {
80
+ meta: AnalyticsProviderMeta;
81
+ capabilities: AnalyticsCapabilities;
82
+
83
+ /** Person WRITE — propagate traits onto the person profile. */
84
+ setPersonProperties(
85
+ opts: { distinctId: string } & PersonPropertiesWrite,
86
+ ): Promise<void>;
87
+
88
+ /** Event capture under a distinct id. Fire-and-forget semantics. */
89
+ capture(opts: CaptureOptions): void;
90
+
91
+ /** Flush/teardown any buffered capture queue. */
92
+ shutdown?(): Promise<void>;
93
+ }
94
+
95
+ /**
96
+ * Identity helper for authoring providers — exists for symmetry with
97
+ * `defineEmailProvider` / `defineWebhookSource` and to give consumers a
98
+ * single obvious entry point with full type inference.
99
+ */
100
+ export function defineAnalyticsProvider(
101
+ provider: AnalyticsProvider,
102
+ ): AnalyticsProvider {
103
+ return provider;
104
+ }
105
+
106
+ /**
107
+ * @deprecated PostHog-shaped service interface, predating the neutral
108
+ * {@link AnalyticsProvider}. Still accepted by `createHogsendClient` (an
109
+ * adapter wraps it) — prefer passing an `AnalyticsProvider`.
110
+ */
18
111
  export interface PostHogService extends IdentityProvider {
19
112
  // getPersonProperties is inherited from IdentityProvider (the identity PULL).
20
113