Merge PostHog self-hosted into a single PostHog provider
Fold POSTHOG_SELF_HOSTED into POSTHOG: one provider now covers Cloud (OAuth + region-pinned API key) and self-hosted (API key + instance URL), since both already share the driver, name resolver, and PostHogConnectorSettings{BaseURL}. The API-key form picks a deployment (Cloud US/EU or self-hosted URL); the resolver requires exactly one of region/instanceUrl.
Drop the POSTHOG_SELF_HOSTED enum value, registration, migration, and logo mapping. Extract the deployment selector into a dedicated PostHogDeploymentField component. Point the driver tests at us.posthog.com instead of the legacy app.posthog.com host.
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -43,6 +43,10 @@ import type { AddAccessSourceDialogCreateAPIKeyConnectorMutation } from "#/__gen
|
||||
import type { AddAccessSourceDialogCreateClientCredentialsConnectorMutation } from "#/__generated__/core/AddAccessSourceDialogCreateClientCredentialsConnectorMutation.graphql";
|
||||
|
||||
import { createAccessSourceMutation } from "./accessSourceMutations";
|
||||
import {
|
||||
isPostHogDeploymentSelected,
|
||||
PostHogDeploymentField,
|
||||
} from "./PostHogDeploymentField";
|
||||
|
||||
export const addAccessSourceDialogConnectorProviderInfoFragment = graphql`
|
||||
fragment AddAccessSourceDialogConnectorProviderInfoFragment on ConnectorProviderInfo @relay(plural: true) {
|
||||
@@ -124,8 +128,6 @@ function mapAPIKeyExtraSettingToField(
|
||||
break;
|
||||
case "POSTHOG":
|
||||
if (settingKey === "region") return "posthogRegion";
|
||||
break;
|
||||
case "POSTHOG_SELF_HOSTED":
|
||||
if (settingKey === "instanceUrl") return "posthogInstanceUrl";
|
||||
break;
|
||||
}
|
||||
@@ -503,6 +505,43 @@ export function AddAccessSourceDialog({
|
||||
);
|
||||
};
|
||||
|
||||
// PostHog renders a dedicated deployment selector (Cloud region or
|
||||
// self-hosted URL); every other provider falls back to generic fields.
|
||||
const renderAPIKeyExtraSettings = () => {
|
||||
if (!activeProvider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (activeProvider.provider === "POSTHOG") {
|
||||
return (
|
||||
<PostHogDeploymentField
|
||||
values={extraSettingValues}
|
||||
onChange={setExtraSettingValues}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return activeProvider.extraSettings.map((setting) => {
|
||||
const value = extraSettingValues[setting.key] ?? "";
|
||||
return (
|
||||
<Field
|
||||
key={setting.key}
|
||||
label={__(setting.label)}
|
||||
value={value}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setExtraSettingValues(prev => ({ ...prev, [setting.key]: e.target.value }))}
|
||||
required={setting.required}
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// PostHog's extra settings are individually optional (region OR instance
|
||||
// URL), so the generic required-field check can't gate it.
|
||||
const postHogAPIKeyValid
|
||||
= activeProvider?.provider !== "POSTHOG"
|
||||
|| isPostHogDeploymentSelected(extraSettingValues);
|
||||
|
||||
const apiKeyExtraSettingsValid = activeProvider
|
||||
? hasRequiredExtraSettings(activeProvider.extraSettings, extraSettingValues)
|
||||
: true;
|
||||
@@ -586,40 +625,7 @@ export function AddAccessSourceDialog({
|
||||
required
|
||||
autoFocus
|
||||
/>
|
||||
{activeProvider?.extraSettings.map((setting) => {
|
||||
const value = extraSettingValues[setting.key] ?? "";
|
||||
const setValue = (next: string) =>
|
||||
setExtraSettingValues(prev => ({ ...prev, [setting.key]: next }));
|
||||
|
||||
// The "region" setting is a fixed US/EU choice; every other
|
||||
// extra setting is a free-text field.
|
||||
if (setting.key === "region") {
|
||||
return (
|
||||
<div key={setting.key} className="space-y-1.5">
|
||||
<label className="text-sm font-medium">{__(setting.label)}</label>
|
||||
<Select
|
||||
value={value}
|
||||
onValueChange={setValue}
|
||||
placeholder={__("Select a region")}
|
||||
>
|
||||
<Option value="US">{__("United States (US)")}</Option>
|
||||
<Option value="EU">{__("Europe (EU)")}</Option>
|
||||
</Select>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Field
|
||||
key={setting.key}
|
||||
label={__(setting.label)}
|
||||
value={value}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setValue(e.target.value)}
|
||||
required={setting.required}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{renderAPIKeyExtraSettings()}
|
||||
</DialogContent>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
@@ -628,6 +634,7 @@ export function AddAccessSourceDialog({
|
||||
isConnectingAPIKey
|
||||
|| !apiKeyValue.trim()
|
||||
|| !apiKeyExtraSettingsValid
|
||||
|| !postHogAPIKeyValid
|
||||
}
|
||||
>
|
||||
{isConnectingAPIKey ? __("Connecting...") : __("Connect")}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { Field, Option, Select } from "@probo/ui";
|
||||
|
||||
// PostHog is a single provider spanning Cloud (region us/eu) and self-hosted
|
||||
// (instance URL). The API-key form surfaces this as one deployment choice;
|
||||
// the two settings are mutually exclusive, so picking one clears the other.
|
||||
|
||||
type PostHogDeploymentFieldProps = {
|
||||
values: Record<string, string>;
|
||||
onChange: (values: Record<string, string>) => void;
|
||||
};
|
||||
|
||||
export function PostHogDeploymentField({
|
||||
values,
|
||||
onChange,
|
||||
}: PostHogDeploymentFieldProps) {
|
||||
const { __ } = useTranslate();
|
||||
|
||||
const region = values.region ?? "";
|
||||
let deployment = "";
|
||||
if (region === "US" || region === "EU") {
|
||||
deployment = region;
|
||||
} else if ("instanceUrl" in values) {
|
||||
deployment = "SELF_HOSTED";
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-sm font-medium">{__("Deployment")}</label>
|
||||
<Select
|
||||
value={deployment}
|
||||
onValueChange={(val: string) =>
|
||||
onChange(val === "SELF_HOSTED" ? { instanceUrl: "" } : { region: val })}
|
||||
placeholder={__("Select a deployment")}
|
||||
>
|
||||
<Option value="US">{__("PostHog Cloud (US)")}</Option>
|
||||
<Option value="EU">{__("PostHog Cloud (EU)")}</Option>
|
||||
<Option value="SELF_HOSTED">{__("Self-hosted")}</Option>
|
||||
</Select>
|
||||
</div>
|
||||
{deployment === "SELF_HOSTED" && (
|
||||
<Field
|
||||
label={__("Instance URL")}
|
||||
value={values.instanceUrl ?? ""}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
onChange({ instanceUrl: e.target.value })}
|
||||
required
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// isPostHogDeploymentSelected reports whether a valid PostHog deployment has
|
||||
// been chosen: a Cloud region (us/eu) or a non-empty self-hosted instance URL.
|
||||
export function isPostHogDeploymentSelected(
|
||||
values: Record<string, string>,
|
||||
): boolean {
|
||||
return (
|
||||
values.region === "US"
|
||||
|| values.region === "EU"
|
||||
|| !!values.instanceUrl?.trim()
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user