@keystrokehq/posthog 0.0.1

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 (51) hide show
  1. package/README.md +237 -0
  2. package/dist/_official/index.d.mts +2 -0
  3. package/dist/_official/index.mjs +3 -0
  4. package/dist/_runtime/index.d.mts +7 -0
  5. package/dist/_runtime/index.mjs +3 -0
  6. package/dist/actions.d.mts +244 -0
  7. package/dist/actions.mjs +129 -0
  8. package/dist/annotations.d.mts +185 -0
  9. package/dist/annotations.mjs +141 -0
  10. package/dist/capture.d.mts +177 -0
  11. package/dist/capture.mjs +241 -0
  12. package/dist/client.d.mts +51 -0
  13. package/dist/client.mjs +200 -0
  14. package/dist/cohorts.d.mts +229 -0
  15. package/dist/cohorts.mjs +185 -0
  16. package/dist/connection.d.mts +2 -0
  17. package/dist/connection.mjs +3 -0
  18. package/dist/dashboards.d.mts +434 -0
  19. package/dist/dashboards.mjs +356 -0
  20. package/dist/decide.d.mts +74 -0
  21. package/dist/decide.mjs +75 -0
  22. package/dist/errors.d.mts +58 -0
  23. package/dist/errors.mjs +120 -0
  24. package/dist/events-management.d.mts +294 -0
  25. package/dist/events-management.mjs +242 -0
  26. package/dist/factory-DYDvHOGb.mjs +8 -0
  27. package/dist/feature-flags.d.mts +416 -0
  28. package/dist/feature-flags.mjs +317 -0
  29. package/dist/index.d.mts +1 -0
  30. package/dist/index.mjs +1 -0
  31. package/dist/insights.d.mts +409 -0
  32. package/dist/insights.mjs +346 -0
  33. package/dist/integration-CsCBBu4d.d.mts +53 -0
  34. package/dist/integration-Doy2Dwli.mjs +30 -0
  35. package/dist/organizations.d.mts +257 -0
  36. package/dist/organizations.mjs +219 -0
  37. package/dist/persons.d.mts +369 -0
  38. package/dist/persons.mjs +345 -0
  39. package/dist/projects.d.mts +348 -0
  40. package/dist/projects.mjs +287 -0
  41. package/dist/schemas.d.mts +351 -0
  42. package/dist/schemas.mjs +302 -0
  43. package/dist/session-recordings.d.mts +391 -0
  44. package/dist/session-recordings.mjs +308 -0
  45. package/dist/surveys.d.mts +287 -0
  46. package/dist/surveys.mjs +208 -0
  47. package/dist/triggers.d.mts +115 -0
  48. package/dist/triggers.mjs +330 -0
  49. package/dist/webhook-management.d.mts +188 -0
  50. package/dist/webhook-management.mjs +152 -0
  51. package/package.json +147 -0
@@ -0,0 +1,241 @@
1
+ import { createPosthogIngestClient } from "./client.mjs";
2
+ import { captureResponseSchema, propertiesBagSchema } from "./schemas.mjs";
3
+ import { t as posthogOperation } from "./factory-DYDvHOGb.mjs";
4
+ import { z } from "zod";
5
+
6
+ //#region src/capture.ts
7
+ /**
8
+ * posthog/capture.ts
9
+ *
10
+ * Ingest operations — single event, batch capture, identify, alias, group
11
+ * identify, set person properties, set person properties once. All require
12
+ * the project API key on the credential set (not the personal API key).
13
+ *
14
+ * Docs: https://posthog.com/docs/api/capture
15
+ */
16
+ const eventNameInput = {
17
+ event: z.string().min(1),
18
+ distinctId: z.string().min(1),
19
+ timestamp: z.iso.datetime().optional(),
20
+ uuid: z.string().optional(),
21
+ properties: propertiesBagSchema.optional()
22
+ };
23
+ /**
24
+ * Capture a single analytics event.
25
+ * Maps Sim archive tool S1 (`posthog_capture_event`).
26
+ */
27
+ const captureEvent = posthogOperation({
28
+ id: "posthog_capture_event",
29
+ name: "PostHog Capture Event",
30
+ description: "Capture a single analytics event via the PostHog /capture endpoint",
31
+ input: z.object(eventNameInput),
32
+ output: captureResponseSchema,
33
+ needsApproval: true,
34
+ run: async (input, credentials) => {
35
+ const client = createPosthogIngestClient(credentials);
36
+ return client.request({
37
+ method: "POST",
38
+ path: "/capture/",
39
+ body: {
40
+ api_key: client.projectApiKey(),
41
+ event: input.event,
42
+ distinct_id: input.distinctId,
43
+ ...input.properties ? { properties: input.properties } : {},
44
+ ...input.timestamp ? { timestamp: input.timestamp } : {},
45
+ ...input.uuid ? { uuid: input.uuid } : {}
46
+ }
47
+ });
48
+ }
49
+ });
50
+ /**
51
+ * Capture a batch of analytics events in one request.
52
+ * Maps Sim archive tool S2 (`posthog_capture_batch_events`).
53
+ */
54
+ const captureBatch = posthogOperation({
55
+ id: "posthog_capture_batch_events",
56
+ name: "PostHog Capture Batch",
57
+ description: "Capture up to 100 analytics events via the PostHog /batch endpoint",
58
+ input: z.object({ events: z.array(z.object({
59
+ event: z.string().min(1),
60
+ distinct_id: z.string().min(1),
61
+ properties: propertiesBagSchema.optional(),
62
+ timestamp: z.iso.datetime().optional(),
63
+ uuid: z.string().optional()
64
+ })).min(1) }),
65
+ output: captureResponseSchema,
66
+ needsApproval: true,
67
+ run: async (input, credentials) => {
68
+ const client = createPosthogIngestClient(credentials);
69
+ return client.request({
70
+ method: "POST",
71
+ path: "/batch/",
72
+ body: {
73
+ api_key: client.projectApiKey(),
74
+ batch: input.events
75
+ }
76
+ });
77
+ }
78
+ });
79
+ /**
80
+ * Identify a person — associates distinct_id with a set of properties.
81
+ * Maps Sim archive tool S3 (`posthog_identify_person`).
82
+ */
83
+ const identifyPerson = posthogOperation({
84
+ id: "posthog_identify_person",
85
+ name: "PostHog Identify Person",
86
+ description: "Associate a distinct_id with person properties via a $identify event",
87
+ input: z.object({
88
+ distinctId: z.string().min(1),
89
+ properties: propertiesBagSchema.optional(),
90
+ propertiesOnce: propertiesBagSchema.optional(),
91
+ timestamp: z.iso.datetime().optional()
92
+ }),
93
+ output: captureResponseSchema,
94
+ needsApproval: true,
95
+ run: async (input, credentials) => {
96
+ const client = createPosthogIngestClient(credentials);
97
+ const properties = {};
98
+ if (input.properties) properties.$set = input.properties;
99
+ if (input.propertiesOnce) properties.$set_once = input.propertiesOnce;
100
+ return client.request({
101
+ method: "POST",
102
+ path: "/capture/",
103
+ body: {
104
+ api_key: client.projectApiKey(),
105
+ event: "$identify",
106
+ distinct_id: input.distinctId,
107
+ properties,
108
+ ...input.timestamp ? { timestamp: input.timestamp } : {}
109
+ }
110
+ });
111
+ }
112
+ });
113
+ /**
114
+ * Alias a distinct_id to an existing user.
115
+ * Maps Sim archive tool S4 (`posthog_alias_person`).
116
+ */
117
+ const aliasPerson = posthogOperation({
118
+ id: "posthog_alias_person",
119
+ name: "PostHog Alias Person",
120
+ description: "Merge one distinct_id into another via a $create_alias event",
121
+ input: z.object({
122
+ distinctId: z.string().min(1),
123
+ alias: z.string().min(1),
124
+ timestamp: z.iso.datetime().optional()
125
+ }),
126
+ output: captureResponseSchema,
127
+ needsApproval: true,
128
+ run: async (input, credentials) => {
129
+ const client = createPosthogIngestClient(credentials);
130
+ return client.request({
131
+ method: "POST",
132
+ path: "/capture/",
133
+ body: {
134
+ api_key: client.projectApiKey(),
135
+ event: "$create_alias",
136
+ distinct_id: input.distinctId,
137
+ properties: { alias: input.alias },
138
+ ...input.timestamp ? { timestamp: input.timestamp } : {}
139
+ }
140
+ });
141
+ }
142
+ });
143
+ /**
144
+ * Identify a group (multi-tenant properties).
145
+ * Maps Sim archive tool S5 (`posthog_group_identify`).
146
+ */
147
+ const groupIdentify = posthogOperation({
148
+ id: "posthog_group_identify",
149
+ name: "PostHog Group Identify",
150
+ description: "Attach properties to a group (organization, project, etc.) via $groupidentify",
151
+ input: z.object({
152
+ distinctId: z.string().min(1),
153
+ groupType: z.string().min(1),
154
+ groupKey: z.string().min(1),
155
+ groupProperties: propertiesBagSchema.optional(),
156
+ timestamp: z.iso.datetime().optional()
157
+ }),
158
+ output: captureResponseSchema,
159
+ needsApproval: true,
160
+ run: async (input, credentials) => {
161
+ const client = createPosthogIngestClient(credentials);
162
+ return client.request({
163
+ method: "POST",
164
+ path: "/capture/",
165
+ body: {
166
+ api_key: client.projectApiKey(),
167
+ event: "$groupidentify",
168
+ distinct_id: input.distinctId,
169
+ properties: {
170
+ $group_type: input.groupType,
171
+ $group_key: input.groupKey,
172
+ $group_set: input.groupProperties ?? {}
173
+ },
174
+ ...input.timestamp ? { timestamp: input.timestamp } : {}
175
+ }
176
+ });
177
+ }
178
+ });
179
+ /**
180
+ * Set person properties (overwrites prior values).
181
+ * Maps Sim archive tool S6 (`posthog_set_person_properties`).
182
+ */
183
+ const setPersonProperties = posthogOperation({
184
+ id: "posthog_set_person_properties",
185
+ name: "PostHog Set Person Properties",
186
+ description: "Set (overwrite) properties on a person via a $set event",
187
+ input: z.object({
188
+ distinctId: z.string().min(1),
189
+ properties: propertiesBagSchema,
190
+ timestamp: z.iso.datetime().optional()
191
+ }),
192
+ output: captureResponseSchema,
193
+ needsApproval: true,
194
+ run: async (input, credentials) => {
195
+ const client = createPosthogIngestClient(credentials);
196
+ return client.request({
197
+ method: "POST",
198
+ path: "/capture/",
199
+ body: {
200
+ api_key: client.projectApiKey(),
201
+ event: "$set",
202
+ distinct_id: input.distinctId,
203
+ properties: { $set: input.properties },
204
+ ...input.timestamp ? { timestamp: input.timestamp } : {}
205
+ }
206
+ });
207
+ }
208
+ });
209
+ /**
210
+ * Set person properties only if not already set.
211
+ * Maps Sim archive tool S7 (`posthog_set_person_properties_once`).
212
+ */
213
+ const setPersonPropertiesOnce = posthogOperation({
214
+ id: "posthog_set_person_properties_once",
215
+ name: "PostHog Set Person Properties Once",
216
+ description: "Set properties on a person only if not already set ($set_once)",
217
+ input: z.object({
218
+ distinctId: z.string().min(1),
219
+ properties: propertiesBagSchema,
220
+ timestamp: z.iso.datetime().optional()
221
+ }),
222
+ output: captureResponseSchema,
223
+ needsApproval: true,
224
+ run: async (input, credentials) => {
225
+ const client = createPosthogIngestClient(credentials);
226
+ return client.request({
227
+ method: "POST",
228
+ path: "/capture/",
229
+ body: {
230
+ api_key: client.projectApiKey(),
231
+ event: "$set",
232
+ distinct_id: input.distinctId,
233
+ properties: { $set_once: input.properties },
234
+ ...input.timestamp ? { timestamp: input.timestamp } : {}
235
+ }
236
+ });
237
+ }
238
+ });
239
+
240
+ //#endregion
241
+ export { aliasPerson, captureBatch, captureEvent, groupIdentify, identifyPerson, setPersonProperties, setPersonPropertiesOnce };
@@ -0,0 +1,51 @@
1
+ import { t as PosthogCredentials } from "./integration-CsCBBu4d.mjs";
2
+ import { JsonRestMethod, JsonRestQueryValue } from "@keystrokehq/integration-authoring/http";
3
+
4
+ //#region src/client.d.ts
5
+ /**
6
+ * Derive the ingest host (for `/capture`, `/batch`, `/decide`) from the
7
+ * management host. For cloud regions we swap to the `*.i.posthog.com`
8
+ * ingest origin; for self-hosted installs we reuse the configured host.
9
+ */
10
+ declare function deriveIngestHost(managementHost: string): string;
11
+ interface PosthogRequestOptions {
12
+ readonly method: JsonRestMethod;
13
+ readonly path: string;
14
+ readonly body?: unknown;
15
+ readonly query?: Record<string, JsonRestQueryValue>;
16
+ readonly headers?: Record<string, string>;
17
+ }
18
+ interface PosthogManagementClient {
19
+ readonly request: <T = unknown>(options: PosthogRequestOptions) => Promise<T>;
20
+ /** Resolve the project id required by most `/api/projects/{id}/...` paths. */
21
+ readonly projectId: (override?: string | number) => string;
22
+ /**
23
+ * Walk a PostHog cursor-paginated list endpoint, yielding each page in
24
+ * order. Stops when `response.next` is null.
25
+ */
26
+ readonly paginate: <TItem>(initial: PosthogRequestOptions, parsePage?: (page: PaginatedResponse<TItem>) => PaginatedResponse<TItem>) => AsyncGenerator<PaginatedResponse<TItem>, void, void>;
27
+ /** Collect every page of a cursor-paginated list into a single array. */
28
+ readonly listAll: <TItem>(initial: PosthogRequestOptions) => Promise<TItem[]>;
29
+ }
30
+ interface PaginatedResponse<TItem> {
31
+ readonly next: string | null;
32
+ readonly previous: string | null;
33
+ readonly count: number;
34
+ readonly results: TItem[];
35
+ }
36
+ /**
37
+ * Build the management client. Uses the personal API key as a bearer
38
+ * token. Throws immediately if the caller attempts an ingest path to
39
+ * prevent accidental token mixing.
40
+ */
41
+ declare function createPosthogManagementClient(credentials: PosthogCredentials, fetchImpl?: typeof fetch): PosthogManagementClient;
42
+ interface PosthogIngestClient {
43
+ readonly request: <T = unknown>(options: PosthogRequestOptions) => Promise<T>;
44
+ /** Return the project API key, throwing a typed error if it is not set. */
45
+ readonly projectApiKey: () => string;
46
+ }
47
+ declare function createPosthogIngestClient(credentials: PosthogCredentials, fetchImpl?: typeof fetch): PosthogIngestClient;
48
+ type PosthogDecideClient = PosthogIngestClient;
49
+ declare function createPosthogDecideClient(credentials: PosthogCredentials, fetchImpl?: typeof fetch): PosthogDecideClient;
50
+ //#endregion
51
+ export { PaginatedResponse, PosthogDecideClient, PosthogIngestClient, PosthogManagementClient, PosthogRequestOptions, createPosthogDecideClient, createPosthogIngestClient, createPosthogManagementClient, deriveIngestHost };
@@ -0,0 +1,200 @@
1
+ import { PosthogClientError, classifyHttpFailure } from "./errors.mjs";
2
+ import { createJsonRestClient, isJsonRestError } from "@keystrokehq/integration-authoring/http";
3
+
4
+ //#region src/client.ts
5
+ /**
6
+ * posthog/client.ts
7
+ *
8
+ * Three narrowly-scoped client helpers. Each sees only the tokens and
9
+ * hosts it needs. Cross-token leakage is impossible at the module
10
+ * boundary because capture/decide and management endpoints live behind
11
+ * different factories that receive different credential projections.
12
+ *
13
+ * - `createPosthogManagementClient(credentials)` — bearer = personal API
14
+ * key; base = `POSTHOG_HOST`; covers `/api/**`.
15
+ * - `createPosthogIngestClient(credentials)` — no bearer; base = derived
16
+ * ingest host; covers `/capture/` and `/batch/`; enforces project key.
17
+ * - `createPosthogDecideClient(credentials)` — no bearer; base = derived
18
+ * ingest host; covers `/decide/`; enforces project key.
19
+ *
20
+ * Pagination helpers are exposed for cursor-style list endpoints that
21
+ * return `{ next, previous, count, results }`.
22
+ */
23
+ const US_CLOUD = "https://us.posthog.com";
24
+ const EU_CLOUD = "https://eu.posthog.com";
25
+ const US_INGEST = "https://us.i.posthog.com";
26
+ const EU_INGEST = "https://eu.i.posthog.com";
27
+ /**
28
+ * Derive the ingest host (for `/capture`, `/batch`, `/decide`) from the
29
+ * management host. For cloud regions we swap to the `*.i.posthog.com`
30
+ * ingest origin; for self-hosted installs we reuse the configured host.
31
+ */
32
+ function deriveIngestHost(managementHost) {
33
+ const normalized = stripTrailingSlash(managementHost);
34
+ if (normalized === US_CLOUD) return US_INGEST;
35
+ if (normalized === EU_CLOUD) return EU_INGEST;
36
+ return normalized;
37
+ }
38
+ function stripTrailingSlash(value) {
39
+ return value.endsWith("/") ? value.slice(0, -1) : value;
40
+ }
41
+ function resolveHost(credentials) {
42
+ return stripTrailingSlash(credentials.POSTHOG_HOST);
43
+ }
44
+ /**
45
+ * Wrap a raw `JsonRestClient` so every non-2xx failure is re-thrown as
46
+ * a structured `PosthogClientError`. We preserve the original error's
47
+ * status/headers/body while normalizing the shape for callers.
48
+ */
49
+ function wrapRequest(raw, errorPrefix) {
50
+ const request = async (options) => {
51
+ try {
52
+ return await raw.request(options);
53
+ } catch (err) {
54
+ if (isJsonRestError(err)) throw classifyHttpFailure({
55
+ status: err.status,
56
+ statusText: err.statusText,
57
+ body: err.body,
58
+ headers: err.headers,
59
+ errorPrefix
60
+ });
61
+ throw err;
62
+ }
63
+ };
64
+ return { request };
65
+ }
66
+ /**
67
+ * Build the management client. Uses the personal API key as a bearer
68
+ * token. Throws immediately if the caller attempts an ingest path to
69
+ * prevent accidental token mixing.
70
+ */
71
+ function createPosthogManagementClient(credentials, fetchImpl) {
72
+ const wrapped = wrapRequest(createJsonRestClient({
73
+ baseUrl: resolveHost(credentials),
74
+ errorPrefix: "PostHog management API error",
75
+ authHeaders: () => ({ Authorization: `Bearer ${credentials.POSTHOG_PERSONAL_API_KEY}` }),
76
+ ...fetchImpl ? { fetchImpl } : {}
77
+ }), "PostHog management API error");
78
+ const guarded = async (options) => {
79
+ if (isIngestPath(options.path)) throw new PosthogClientError({
80
+ kind: "bad_credential_shape",
81
+ message: `PostHog management client cannot call ingest path: ${options.path}`,
82
+ status: null,
83
+ providerCode: "WRONG_CLIENT",
84
+ detail: `Use createPosthogIngestClient or createPosthogDecideClient for ${options.path}`,
85
+ requestId: null,
86
+ retryable: false
87
+ });
88
+ return wrapped.request(options);
89
+ };
90
+ const projectId = (override) => {
91
+ if (override !== void 0 && override !== null && String(override).length > 0) return String(override);
92
+ const stored = credentials.POSTHOG_PROJECT_ID;
93
+ if (!stored) throw new PosthogClientError({
94
+ kind: "bad_credential_shape",
95
+ message: "PostHog project id is required. Provide POSTHOG_PROJECT_ID on the credential or pass it explicitly.",
96
+ status: null,
97
+ providerCode: "MISSING_PROJECT_ID",
98
+ detail: "POSTHOG_PROJECT_ID was not set on the credential and no explicit id was provided.",
99
+ requestId: null,
100
+ retryable: false
101
+ });
102
+ return stored;
103
+ };
104
+ async function* paginate(initial, parsePage) {
105
+ let next = null;
106
+ let current = initial;
107
+ while (current) {
108
+ const page = await guarded(current);
109
+ const parsed = parsePage ? parsePage(page) : page;
110
+ yield parsed;
111
+ next = parsed.next;
112
+ if (!next) current = null;
113
+ else {
114
+ const url = new URL(next);
115
+ current = {
116
+ method: "GET",
117
+ path: `${url.pathname}${url.search}`
118
+ };
119
+ }
120
+ }
121
+ }
122
+ const listAll = async (initial) => {
123
+ const all = [];
124
+ for await (const page of paginate(initial)) all.push(...page.results);
125
+ return all;
126
+ };
127
+ return {
128
+ request: guarded,
129
+ projectId,
130
+ paginate,
131
+ listAll
132
+ };
133
+ }
134
+ function createPosthogIngestClient(credentials, fetchImpl) {
135
+ return buildIngestLikeClient({
136
+ credentials,
137
+ fetchImpl,
138
+ errorPrefix: "PostHog ingest API error",
139
+ allowPath: isCapturePath,
140
+ wrongPathMessage: (path) => `PostHog ingest client cannot call non-capture path: ${path}`
141
+ });
142
+ }
143
+ function createPosthogDecideClient(credentials, fetchImpl) {
144
+ return buildIngestLikeClient({
145
+ credentials,
146
+ fetchImpl,
147
+ errorPrefix: "PostHog decide API error",
148
+ allowPath: isDecidePath,
149
+ wrongPathMessage: (path) => `PostHog decide client cannot call non-decide path: ${path}`
150
+ });
151
+ }
152
+ function buildIngestLikeClient(params) {
153
+ const wrapped = wrapRequest(createJsonRestClient({
154
+ baseUrl: deriveIngestHost(params.credentials.POSTHOG_HOST),
155
+ errorPrefix: params.errorPrefix,
156
+ authHeaders: () => ({}),
157
+ ...params.fetchImpl ? { fetchImpl: params.fetchImpl } : {}
158
+ }), params.errorPrefix);
159
+ const guarded = async (options) => {
160
+ if (!params.allowPath(options.path)) throw new PosthogClientError({
161
+ kind: "bad_credential_shape",
162
+ message: params.wrongPathMessage(options.path),
163
+ status: null,
164
+ providerCode: "WRONG_CLIENT",
165
+ detail: params.wrongPathMessage(options.path),
166
+ requestId: null,
167
+ retryable: false
168
+ });
169
+ return wrapped.request(options);
170
+ };
171
+ const projectApiKey = () => {
172
+ const key = params.credentials.POSTHOG_PROJECT_API_KEY;
173
+ if (!key) throw new PosthogClientError({
174
+ kind: "bad_credential_shape",
175
+ message: "PostHog project API key is required for capture/decide calls. Set POSTHOG_PROJECT_API_KEY on the credential set.",
176
+ status: null,
177
+ providerCode: "MISSING_PROJECT_API_KEY",
178
+ detail: "POSTHOG_PROJECT_API_KEY was not set on the credential set.",
179
+ requestId: null,
180
+ retryable: false
181
+ });
182
+ return key;
183
+ };
184
+ return {
185
+ request: guarded,
186
+ projectApiKey
187
+ };
188
+ }
189
+ function isIngestPath(path) {
190
+ return isCapturePath(path) || isDecidePath(path);
191
+ }
192
+ function isCapturePath(path) {
193
+ return path.startsWith("/capture") || path.startsWith("/batch");
194
+ }
195
+ function isDecidePath(path) {
196
+ return path.startsWith("/decide");
197
+ }
198
+
199
+ //#endregion
200
+ export { createPosthogDecideClient, createPosthogIngestClient, createPosthogManagementClient, deriveIngestHost };