@sanity/personalization-plugin 2.1.0 → 2.2.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/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: !0 });
3
- var jsxRuntime = require("react/jsx-runtime"), sanity = require("sanity"), ui = require("@sanity/ui"), uuid = require("@sanity/uuid"), react = require("react"), equal = require("fast-deep-equal"), suspendReact = require("suspend-react"), gi = require("react-icons/gi");
3
+ var jsxRuntime = require("react/jsx-runtime"), sanity = require("sanity"), ui = require("@sanity/ui"), uuid = require("@sanity/uuid"), react = require("react"), equal = require("fast-deep-equal"), suspendReact = require("suspend-react"), gi = require("react-icons/gi"), studioSecrets = require("@sanity/studio-secrets");
4
4
  function _interopDefaultCompat(e) {
5
5
  return e && typeof e == "object" && "default" in e ? e : { default: e };
6
6
  }
@@ -15,20 +15,23 @@ const CONFIG_DEFAULT = {
15
15
  experimentId: "experimentId"
16
16
  }, ExperimentContext = react.createContext({
17
17
  ...CONFIG_DEFAULT,
18
- experiments: []
18
+ experiments: [],
19
+ setSecret: () => {
20
+ },
21
+ secret: void 0
19
22
  });
20
23
  function useExperimentContext() {
21
24
  return react.useContext(ExperimentContext);
22
25
  }
23
26
  function ExperimentProvider(props) {
24
- const { experimentFieldPluginConfig } = props, client = sanity.useClient({ apiVersion: experimentFieldPluginConfig.apiVersion }), workspace = sanity.useWorkspace(), experiments = Array.isArray(experimentFieldPluginConfig.experiments) ? experimentFieldPluginConfig.experiments : suspendReact.suspend(
27
+ const { experimentFieldPluginConfig } = props, [secret, setSecret] = react.useState(), client = sanity.useClient({ apiVersion: experimentFieldPluginConfig.apiVersion }), workspace = sanity.useWorkspace(), experiments = Array.isArray(experimentFieldPluginConfig.experiments) ? experimentFieldPluginConfig.experiments : suspendReact.suspend(
25
28
  // eslint-disable-next-line require-await
26
- async () => typeof experimentFieldPluginConfig.experiments == "function" ? experimentFieldPluginConfig.experiments(client) : experimentFieldPluginConfig.experiments,
27
- [workspace],
29
+ async () => typeof experimentFieldPluginConfig.experiments == "function" ? experimentFieldPluginConfig.experiments(client, secret) : experimentFieldPluginConfig.experiments,
30
+ [workspace, secret],
28
31
  { equal: equal__default.default }
29
32
  ), context = react.useMemo(
30
- () => ({ ...experimentFieldPluginConfig, experiments }),
31
- [experimentFieldPluginConfig, experiments]
33
+ () => ({ ...experimentFieldPluginConfig, experiments, secret, setSecret }),
34
+ [experimentFieldPluginConfig, experiments, secret, setSecret]
32
35
  );
33
36
  return /* @__PURE__ */ jsxRuntime.jsx(ExperimentContext.Provider, { value: context, children: props.renderDefault(props) });
34
37
  }
@@ -6405,9 +6408,9 @@ const icons = {
6405
6408
  });
6406
6409
  Icon.displayName = "ForwardRef(Icon)";
6407
6410
  const useAddExperimentAction = (props) => {
6408
- const { onChange, experimentNameOverride } = props, handleAddAction = () => {
6409
- onChange([sanity.set(!0, ["active"])]);
6410
- };
6411
+ const { onChange, active, experimentNameOverride } = props, handleAddAction = react.useCallback(() => {
6412
+ onChange([sanity.set(!active, ["active"])]);
6413
+ }, [onChange, active]);
6411
6414
  return {
6412
6415
  title: `Add ${experimentNameOverride}`,
6413
6416
  type: "action",
@@ -6416,13 +6419,10 @@ const useAddExperimentAction = (props) => {
6416
6419
  renderAsButton: !0
6417
6420
  };
6418
6421
  }, useRemoveExperimentAction = (props) => {
6419
- const { onChange, experimentId, experimentNameOverride } = props, patchActiveFalseEvent = () => sanity.set(!1, ["active"]), patchClearEvent = () => {
6420
- const experiment = [experimentId], variants = [experimentNameOverride];
6421
- return [sanity.unset(experiment), sanity.unset(variants)];
6422
- }, handleClearAction = () => {
6423
- const clearEvents = patchClearEvent(), activeEvent = patchActiveFalseEvent();
6424
- onChange([activeEvent, ...clearEvents]);
6425
- };
6422
+ const { onChange, active, experimentId, experimentNameOverride, variantNameOverride } = props, handleClearAction = react.useCallback(() => {
6423
+ const activeId = ["active"], experiment = [experimentId], variants = [`${variantNameOverride}s`];
6424
+ onChange([sanity.set(!active, activeId), sanity.unset(experiment), sanity.unset(variants)]);
6425
+ }, [onChange, active, experimentId, variantNameOverride]);
6426
6426
  return {
6427
6427
  title: `Remove ${experimentNameOverride}`,
6428
6428
  type: "action",
@@ -6430,36 +6430,53 @@ const useAddExperimentAction = (props) => {
6430
6430
  onAction: handleClearAction,
6431
6431
  renderAsButton: !0
6432
6432
  };
6433
- }, newActions = ({
6433
+ }, createActions = ({
6434
6434
  onChange,
6435
6435
  inputId,
6436
6436
  active,
6437
6437
  experimentNameOverride,
6438
- experimentId
6438
+ experimentId,
6439
+ variantNameOverride
6439
6440
  }) => {
6440
6441
  const removeAction = sanity.defineDocumentFieldAction({
6441
6442
  name: `Remove ${experimentNameOverride}`,
6442
6443
  useAction: (props) => useRemoveExperimentAction({
6444
+ active: !0,
6443
6445
  onChange,
6444
6446
  experimentNameOverride,
6445
- experimentId
6447
+ experimentId,
6448
+ variantNameOverride
6446
6449
  })
6447
6450
  }), addAction = sanity.defineDocumentFieldAction({
6448
6451
  name: `Add ${experimentNameOverride}`,
6449
6452
  useAction: (props) => useAddExperimentAction({
6453
+ active: !1,
6450
6454
  onChange,
6451
6455
  experimentNameOverride
6452
6456
  })
6453
6457
  });
6454
6458
  return active ? removeAction : addAction;
6455
6459
  }, ExperimentField = (props) => {
6456
- const { onChange } = props.inputProps, { inputId, experimentNameOverride, experimentId } = props, active = props.value?.active, oldActions = props.actions || [], withActionProps = {
6457
- ...props,
6458
- actions: [
6459
- newActions({ onChange, inputId, active, experimentNameOverride, experimentId }),
6460
- ...oldActions
6461
- ]
6462
- };
6460
+ const { onChange } = props.inputProps, { inputId, experimentNameOverride, experimentId, variantNameOverride } = props, active = props.value?.active, actionProps = react.useMemo(
6461
+ () => ({
6462
+ onChange,
6463
+ inputId,
6464
+ active,
6465
+ experimentNameOverride,
6466
+ experimentId,
6467
+ variantNameOverride
6468
+ }),
6469
+ [onChange, inputId, active, experimentNameOverride, experimentId, variantNameOverride]
6470
+ ), memoizedActions = react.useMemo(() => {
6471
+ const oldActions = props.actions || [];
6472
+ return [createActions(actionProps), ...oldActions];
6473
+ }, [actionProps, props.actions]), withActionProps = react.useMemo(
6474
+ () => ({
6475
+ ...props,
6476
+ actions: memoizedActions
6477
+ }),
6478
+ [props, memoizedActions]
6479
+ );
6463
6480
  return props.renderDefault(withActionProps);
6464
6481
  }, Select = (props) => {
6465
6482
  const {
@@ -6491,7 +6508,7 @@ const useAddExperimentAction = (props) => {
6491
6508
  value: experiment.id
6492
6509
  })), ExperimentInput = (props) => {
6493
6510
  const { experiments } = useExperimentContext(), id = sanity.useFormValue(["_id"]), aditionalChangePath = react.useMemo(
6494
- () => [...props.path.slice(0, -1), props.variantNameOverride],
6511
+ () => [...props.path.slice(0, -1), `${props.variantNameOverride}s`],
6495
6512
  [props.variantNameOverride, props.path]
6496
6513
  ), subValues = sanity.useFormValue(aditionalChangePath), { patch } = sanity.useDocumentOperation(id.replace("drafts.", ""), props.schemaType.name), handleChange = react.useCallback(
6497
6514
  (event, onChange) => {
@@ -6579,7 +6596,8 @@ const createExperimentType = ({
6579
6596
  {
6580
6597
  ...props,
6581
6598
  experimentId,
6582
- experimentNameOverride
6599
+ experimentNameOverride,
6600
+ variantNameOverride
6583
6601
  }
6584
6602
  )
6585
6603
  },
@@ -6742,7 +6760,91 @@ const createExperimentType = ({
6742
6760
  }
6743
6761
  }
6744
6762
  };
6763
+ }), namespace = "growthbook", pluginConfigKeys = [
6764
+ {
6765
+ key: "apiKey",
6766
+ title: "Your secret API key"
6767
+ }
6768
+ ], Secrets = (props) => {
6769
+ const { secrets, loading } = studioSecrets.useSecrets(namespace), { setSecret } = useExperimentContext(), [showSettings, setShowSettings] = react.useState(!1);
6770
+ return react.useEffect(() => {
6771
+ if (!loading)
6772
+ return !secrets && !loading ? (setSecret(void 0), setShowSettings(!0)) : (setSecret(secrets.apiKey), setShowSettings(!1));
6773
+ }, [secrets, loading, setSecret]), showSettings ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6774
+ /* @__PURE__ */ jsxRuntime.jsx(
6775
+ studioSecrets.SettingsView,
6776
+ {
6777
+ title: "Growthbook secret",
6778
+ namespace,
6779
+ keys: pluginConfigKeys,
6780
+ onClose: () => {
6781
+ setShowSettings(!1);
6782
+ }
6783
+ }
6784
+ ),
6785
+ props.renderDefault(props)
6786
+ ] }) : props.renderDefault(props);
6787
+ }, getBooleanConversion = (value) => value === "true" ? "variant" : value === "false" ? "control" : value, getExperiments = async ({
6788
+ client,
6789
+ environment,
6790
+ baseUrl,
6791
+ project,
6792
+ convertBooleans
6793
+ }) => {
6794
+ const secret = await client.fetch("*[_id == 'secrets.growthbook'][0].secrets.apiKey");
6795
+ if (!secret) return [];
6796
+ const featureExperiments = [];
6797
+ let hasMore = !0, offset = 0;
6798
+ const url = new URL(baseUrl ?? "https://api.growthbook.io/api/v1/features");
6799
+ for (project && url.searchParams.set("projectId", project); hasMore; ) {
6800
+ url.searchParams.set("offset", offset.toString());
6801
+ const response = await fetch(url, {
6802
+ headers: {
6803
+ Authorization: `Bearer ${secret}`
6804
+ }
6805
+ }), { features, hasMore: responseHasMore, nextOffset } = await response.json();
6806
+ hasMore = responseHasMore, offset = nextOffset, features && features.forEach((feature) => {
6807
+ if (feature.archived)
6808
+ return;
6809
+ const experiments = feature.environments[environment]?.rules.filter(
6810
+ (experiment) => experiment.type === "experiment-ref" || experiment.type === "experiment"
6811
+ );
6812
+ if (!experiments)
6813
+ return;
6814
+ const variations = /* @__PURE__ */ new Set();
6815
+ experiments.forEach((experiment) => {
6816
+ experiment?.variations.forEach((variant) => {
6817
+ variations.add({
6818
+ id: convertBooleans ? getBooleanConversion(variant.value) : variant.value,
6819
+ label: convertBooleans ? getBooleanConversion(variant.value) : variant.value
6820
+ });
6821
+ });
6822
+ });
6823
+ const value = { id: feature.id, label: feature.id, variants: [...variations] };
6824
+ featureExperiments.push(value);
6825
+ });
6826
+ }
6827
+ return featureExperiments;
6828
+ }, growthbookFieldLevel = sanity.definePlugin((config) => {
6829
+ const { fields, environment, project, convertBooleans, baseUrl } = config;
6830
+ return {
6831
+ name: "sanity-growthbook-personalistaion-plugin-field-level-experiments",
6832
+ plugins: [
6833
+ fieldLevelExperiments({
6834
+ fields,
6835
+ experiments: (client) => getExperiments({ client, environment, baseUrl, project, convertBooleans })
6836
+ })
6837
+ ],
6838
+ form: {
6839
+ components: {
6840
+ input: (props) => !(props.id === "root" && sanity.isObjectInputProps(props)) || !flattenSchemaType(props.schemaType).map(
6841
+ (field) => field.type.name
6842
+ ).some((name) => name.startsWith("experiment")) ? props.renderDefault(props) : Secrets(props)
6843
+ }
6844
+ }
6845
+ };
6745
6846
  });
6746
6847
  exports.fieldLevelExperiments = fieldLevelExperiments;
6747
6848
  exports.flattenSchemaType = flattenSchemaType;
6849
+ exports.growthbookFieldLevel = growthbookFieldLevel;
6748
6850
  //# sourceMappingURL=index.js.map