@sanity/personalization-plugin 2.0.0 → 2.1.0-growthbook.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 +15 -15
- package/dist/index.d.mts +205 -1
- package/dist/index.d.ts +205 -1
- package/dist/index.js +94 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +96 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/components/ExperimentContext.tsx +8 -5
- package/src/components/Secrets.tsx +47 -0
- package/src/fieldExperiments.tsx +3 -1
- package/src/growthbookFieldExperiments.tsx +51 -0
- package/src/index.ts +1 -0
- package/src/types.ts +182 -1
- package/src/utils/growthbook.ts +78 -0
package/dist/index.mjs
CHANGED
|
@@ -2,29 +2,33 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
|
2
2
|
import { useClient, useWorkspace, useFormValue, defineDocumentFieldAction, set, unset, useDocumentOperation, isReference, isImage, isDocumentSchemaType, definePlugin, isObjectInputProps, defineType, defineField } from "sanity";
|
|
3
3
|
import { Stack, Inline, Button, Select as Select$1 } from "@sanity/ui";
|
|
4
4
|
import { uuid } from "@sanity/uuid";
|
|
5
|
-
import { createContext, useMemo, useContext, useCallback, forwardRef,
|
|
5
|
+
import { createContext, useState, useMemo, useContext, useCallback, forwardRef, useEffect } from "react";
|
|
6
6
|
import equal from "fast-deep-equal";
|
|
7
7
|
import { suspend } from "suspend-react";
|
|
8
8
|
import { GiSoapExperiment } from "react-icons/gi";
|
|
9
|
+
import { useSecrets, SettingsView } from "@sanity/studio-secrets";
|
|
9
10
|
const CONFIG_DEFAULT = {
|
|
10
11
|
fields: [],
|
|
11
12
|
apiVersion: "2024-11-07"
|
|
12
13
|
}, ExperimentContext = createContext({
|
|
13
14
|
...CONFIG_DEFAULT,
|
|
14
|
-
experiments: []
|
|
15
|
+
experiments: [],
|
|
16
|
+
setSecret: () => {
|
|
17
|
+
},
|
|
18
|
+
secret: void 0
|
|
15
19
|
});
|
|
16
20
|
function useExperimentContext() {
|
|
17
21
|
return useContext(ExperimentContext);
|
|
18
22
|
}
|
|
19
23
|
function ExperimentProvider(props) {
|
|
20
|
-
const { experimentFieldPluginConfig } = props, client = useClient({ apiVersion: experimentFieldPluginConfig.apiVersion }), workspace = useWorkspace(), experiments = Array.isArray(experimentFieldPluginConfig.experiments) ? experimentFieldPluginConfig.experiments : suspend(
|
|
24
|
+
const { experimentFieldPluginConfig } = props, [secret, setSecret] = useState(), client = useClient({ apiVersion: experimentFieldPluginConfig.apiVersion }), workspace = useWorkspace(), experiments = Array.isArray(experimentFieldPluginConfig.experiments) ? experimentFieldPluginConfig.experiments : suspend(
|
|
21
25
|
// eslint-disable-next-line require-await
|
|
22
|
-
async () => typeof experimentFieldPluginConfig.experiments == "function" ? experimentFieldPluginConfig.experiments(client) : experimentFieldPluginConfig.experiments,
|
|
23
|
-
[workspace],
|
|
26
|
+
async () => typeof experimentFieldPluginConfig.experiments == "function" ? experimentFieldPluginConfig.experiments(client, secret) : experimentFieldPluginConfig.experiments,
|
|
27
|
+
[workspace, secret],
|
|
24
28
|
{ equal }
|
|
25
29
|
), context = useMemo(
|
|
26
|
-
() => ({ ...experimentFieldPluginConfig, experiments }),
|
|
27
|
-
[experimentFieldPluginConfig, experiments]
|
|
30
|
+
() => ({ ...experimentFieldPluginConfig, experiments, secret, setSecret }),
|
|
31
|
+
[experimentFieldPluginConfig, experiments, secret, setSecret]
|
|
28
32
|
);
|
|
29
33
|
return /* @__PURE__ */ jsx(ExperimentContext.Provider, { value: context, children: props.renderDefault(props) });
|
|
30
34
|
}
|
|
@@ -6649,9 +6653,93 @@ const createFieldType = ({
|
|
|
6649
6653
|
}
|
|
6650
6654
|
}
|
|
6651
6655
|
};
|
|
6656
|
+
}), namespace = "growthbook", pluginConfigKeys = [
|
|
6657
|
+
{
|
|
6658
|
+
key: "apiKey",
|
|
6659
|
+
title: "Your secret API key"
|
|
6660
|
+
}
|
|
6661
|
+
], Secrets = (props) => {
|
|
6662
|
+
const { secrets, loading } = useSecrets(namespace), { setSecret } = useExperimentContext(), [showSettings, setShowSettings] = useState(!1);
|
|
6663
|
+
return useEffect(() => {
|
|
6664
|
+
if (!loading)
|
|
6665
|
+
return !secrets && !loading ? (setSecret(void 0), setShowSettings(!0)) : (setSecret(secrets.apiKey), setShowSettings(!1));
|
|
6666
|
+
}, [secrets, loading, setSecret]), showSettings ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6667
|
+
/* @__PURE__ */ jsx(
|
|
6668
|
+
SettingsView,
|
|
6669
|
+
{
|
|
6670
|
+
title: "Growthbook secret",
|
|
6671
|
+
namespace,
|
|
6672
|
+
keys: pluginConfigKeys,
|
|
6673
|
+
onClose: () => {
|
|
6674
|
+
setShowSettings(!1);
|
|
6675
|
+
}
|
|
6676
|
+
}
|
|
6677
|
+
),
|
|
6678
|
+
props.renderDefault(props)
|
|
6679
|
+
] }) : props.renderDefault(props);
|
|
6680
|
+
}, getBooleanConversion = (value) => value === "true" ? "variant" : value === "false" ? "control" : value, getExperiments = async ({
|
|
6681
|
+
client,
|
|
6682
|
+
environment,
|
|
6683
|
+
baseUrl,
|
|
6684
|
+
project,
|
|
6685
|
+
convertBooleans
|
|
6686
|
+
}) => {
|
|
6687
|
+
const secret = await client.fetch("*[_id == 'secrets.growthbook'][0].secrets.apiKey");
|
|
6688
|
+
if (!secret) return [];
|
|
6689
|
+
const featureExperiments = [];
|
|
6690
|
+
let hasMore = !0, offset = 0;
|
|
6691
|
+
const url = new URL(baseUrl ?? "https://api.growthbook.io/api/v1/features");
|
|
6692
|
+
for (project && url.searchParams.set("projectId", project); hasMore; ) {
|
|
6693
|
+
url.searchParams.set("offset", offset.toString());
|
|
6694
|
+
const response = await fetch(url, {
|
|
6695
|
+
headers: {
|
|
6696
|
+
Authorization: `Bearer ${secret}`
|
|
6697
|
+
}
|
|
6698
|
+
}), { features, hasMore: responseHasMore, nextOffset } = await response.json();
|
|
6699
|
+
hasMore = responseHasMore, offset = nextOffset, features && features.forEach((feature) => {
|
|
6700
|
+
if (feature.archived)
|
|
6701
|
+
return;
|
|
6702
|
+
const experiments = feature.environments[environment]?.rules.filter(
|
|
6703
|
+
(experiment) => experiment.type === "experiment-ref" || experiment.type === "experiment"
|
|
6704
|
+
);
|
|
6705
|
+
if (!experiments)
|
|
6706
|
+
return;
|
|
6707
|
+
const variations = /* @__PURE__ */ new Set();
|
|
6708
|
+
experiments.forEach((experiment) => {
|
|
6709
|
+
experiment?.variations.forEach((variant) => {
|
|
6710
|
+
variations.add({
|
|
6711
|
+
id: convertBooleans ? getBooleanConversion(variant.value) : variant.value,
|
|
6712
|
+
label: convertBooleans ? getBooleanConversion(variant.value) : variant.value
|
|
6713
|
+
});
|
|
6714
|
+
});
|
|
6715
|
+
});
|
|
6716
|
+
const value = { id: feature.id, label: feature.id, variants: [...variations] };
|
|
6717
|
+
featureExperiments.push(value);
|
|
6718
|
+
});
|
|
6719
|
+
}
|
|
6720
|
+
return featureExperiments;
|
|
6721
|
+
}, growthbookFieldLevel = definePlugin((config) => {
|
|
6722
|
+
const { fields, environment, project, convertBooleans, baseUrl } = config;
|
|
6723
|
+
return {
|
|
6724
|
+
name: "sanity-growthbook-personalistaion-plugin-field-level-experiments",
|
|
6725
|
+
plugins: [
|
|
6726
|
+
fieldLevelExperiments({
|
|
6727
|
+
fields,
|
|
6728
|
+
experiments: (client) => getExperiments({ client, environment, baseUrl, project, convertBooleans })
|
|
6729
|
+
})
|
|
6730
|
+
],
|
|
6731
|
+
form: {
|
|
6732
|
+
components: {
|
|
6733
|
+
input: (props) => !(props.id === "root" && isObjectInputProps(props)) || !flattenSchemaType(props.schemaType).map(
|
|
6734
|
+
(field) => field.type.name
|
|
6735
|
+
).some((name) => name.startsWith("experiment")) ? props.renderDefault(props) : Secrets(props)
|
|
6736
|
+
}
|
|
6737
|
+
}
|
|
6738
|
+
};
|
|
6652
6739
|
});
|
|
6653
6740
|
export {
|
|
6654
6741
|
fieldLevelExperiments,
|
|
6655
|
-
flattenSchemaType
|
|
6742
|
+
flattenSchemaType,
|
|
6743
|
+
growthbookFieldLevel
|
|
6656
6744
|
};
|
|
6657
6745
|
//# sourceMappingURL=index.mjs.map
|