@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.
- package/README.md +237 -0
- package/dist/_official/index.d.mts +2 -0
- package/dist/_official/index.mjs +3 -0
- package/dist/_runtime/index.d.mts +7 -0
- package/dist/_runtime/index.mjs +3 -0
- package/dist/actions.d.mts +244 -0
- package/dist/actions.mjs +129 -0
- package/dist/annotations.d.mts +185 -0
- package/dist/annotations.mjs +141 -0
- package/dist/capture.d.mts +177 -0
- package/dist/capture.mjs +241 -0
- package/dist/client.d.mts +51 -0
- package/dist/client.mjs +200 -0
- package/dist/cohorts.d.mts +229 -0
- package/dist/cohorts.mjs +185 -0
- package/dist/connection.d.mts +2 -0
- package/dist/connection.mjs +3 -0
- package/dist/dashboards.d.mts +434 -0
- package/dist/dashboards.mjs +356 -0
- package/dist/decide.d.mts +74 -0
- package/dist/decide.mjs +75 -0
- package/dist/errors.d.mts +58 -0
- package/dist/errors.mjs +120 -0
- package/dist/events-management.d.mts +294 -0
- package/dist/events-management.mjs +242 -0
- package/dist/factory-DYDvHOGb.mjs +8 -0
- package/dist/feature-flags.d.mts +416 -0
- package/dist/feature-flags.mjs +317 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -0
- package/dist/insights.d.mts +409 -0
- package/dist/insights.mjs +346 -0
- package/dist/integration-CsCBBu4d.d.mts +53 -0
- package/dist/integration-Doy2Dwli.mjs +30 -0
- package/dist/organizations.d.mts +257 -0
- package/dist/organizations.mjs +219 -0
- package/dist/persons.d.mts +369 -0
- package/dist/persons.mjs +345 -0
- package/dist/projects.d.mts +348 -0
- package/dist/projects.mjs +287 -0
- package/dist/schemas.d.mts +351 -0
- package/dist/schemas.mjs +302 -0
- package/dist/session-recordings.d.mts +391 -0
- package/dist/session-recordings.mjs +308 -0
- package/dist/surveys.d.mts +287 -0
- package/dist/surveys.mjs +208 -0
- package/dist/triggers.d.mts +115 -0
- package/dist/triggers.mjs +330 -0
- package/dist/webhook-management.d.mts +188 -0
- package/dist/webhook-management.mjs +152 -0
- package/package.json +147 -0
package/dist/capture.mjs
ADDED
|
@@ -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 };
|
package/dist/client.mjs
ADDED
|
@@ -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 };
|