@sanity/personalization-plugin 2.2.0-launch-darkly.1 → 2.3.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/src/types.ts CHANGED
@@ -1,4 +1,3 @@
1
- import {Dispatch, SetStateAction} from 'react'
2
1
  import {
3
2
  ArrayOfObjectsInputProps,
4
3
  FieldDefinition,
@@ -21,7 +20,9 @@ export type ExperimentType = {
21
20
 
22
21
  export type FieldPluginConfig = {
23
22
  fields: (string | FieldDefinition)[]
24
- experiments: ExperimentType[] | ((client: SanityClient) => Promise<ExperimentType[]>)
23
+ experiments:
24
+ | ExperimentType[]
25
+ | ((client: SanityClient, secret?: string) => Promise<ExperimentType[]>)
25
26
  apiVersion?: string
26
27
  experimentNameOverride?: string
27
28
  variantNameOverride?: string
@@ -38,8 +39,6 @@ export type VariantPreviewProps = Omit<PreviewProps, 'SchemaType'> & {
38
39
 
39
40
  export type ExperimentContextProps = Required<FieldPluginConfig> & {
40
41
  experiments: ExperimentType[]
41
- setSecret: Dispatch<SetStateAction<string | undefined>>
42
- secret: string | undefined
43
42
  }
44
43
 
45
44
  export type ArrayInputProps = ArrayOfObjectsInputProps & {
@@ -71,184 +70,178 @@ export type ExperimentGeneric<T> = {
71
70
  | undefined
72
71
  }
73
72
 
74
- export type LaunchDarklyFlagItem = {
73
+ export type GrowthbookExperiment = {
74
+ id: string
75
+ dateCreated: string
76
+ dateUpdated: string
75
77
  name: string
76
- kind: string
77
- key: string
78
- _version: number
79
- creationDate: number
80
- variations: Array<{
81
- value: boolean
82
- _id: string
83
- name: string
84
- }>
85
- temporary: boolean
86
- tags: string[]
87
- _links: {
88
- parent: {
89
- href: string
90
- type: string
91
- }
92
- self: {
93
- href: string
94
- type: string
95
- }
96
- }
97
- experiments: {
98
- baselineIdx: number
99
- items: Array<{
100
- metricKey: string
101
- _metric: {
102
- _id: string
103
- _versionId: string
104
- key: string
105
- name: string
106
- kind: string
107
- _links: {
108
- parent: {
109
- href: string
110
- type: string
111
- }
112
- self: {
113
- href: string
114
- type: string
115
- }
78
+ project: string
79
+ hypothesis: string
80
+ description: string
81
+ tags: [string]
82
+ owner: string
83
+ archived: boolean
84
+ status: string
85
+ autoRefresh: boolean
86
+ hashAttribute: string
87
+ fallbackAttribute: string
88
+ hashVersion: number
89
+ disableStickyBucketing: boolean
90
+ bucketVersion: number
91
+ minBucketVersion: number
92
+ variations: [
93
+ {
94
+ variationId: string
95
+ key: string
96
+ name: string
97
+ description: string
98
+ screenshots: [string]
99
+ },
100
+ ]
101
+ phases: [
102
+ {
103
+ name: string
104
+ dateStarted: string
105
+ dateEnded: string
106
+ reasonForStopping: string
107
+ seed: string
108
+ coverage: 0
109
+ trafficSplit: [
110
+ {
111
+ variationId: string
112
+ weight: 0
113
+ },
114
+ ]
115
+ namespace: {
116
+ namespaceId: string
117
+ range: []
118
+ }
119
+ targetingCondition: string
120
+ savedGroupTargeting: [
121
+ {
122
+ matchType: string
123
+ savedGroups: [string]
124
+ },
125
+ ]
126
+ },
127
+ ]
128
+ settings: {
129
+ datasourceId: string
130
+ assignmentQueryId: string
131
+ experimentId: string
132
+ segmentId: string
133
+ queryFilter: string
134
+ inProgressConversions: string
135
+ attributionModel: string
136
+ statsEngine: string
137
+ regressionAdjustmentEnabled: boolean
138
+ goals: [
139
+ {
140
+ metricId: string
141
+ overrides: {
142
+ delayHours: 0
143
+ windowHours: 0
144
+ window: string
145
+ winRiskThreshold: 0
146
+ loseRiskThreshold: 0
147
+ }
148
+ },
149
+ ]
150
+ secondaryMetrics: [
151
+ {
152
+ metricId: string
153
+ overrides: {
154
+ delayHours: 0
155
+ windowHours: 0
156
+ window: string
157
+ winRiskThreshold: 0
158
+ loseRiskThreshold: 0
116
159
  }
117
- tags: string[]
118
- _creationDate: number
119
- experimentCount: number
120
- metricGroupCount: number
121
- _attachedFlagCount: number
122
- maintainerId: string
123
- _maintainer: {
124
- _links: {
125
- self: {
126
- href: string
127
- type: string
128
- }
129
- }
130
- _id: string
131
- role: string
132
- email: string
133
- firstName: string
134
- lastName: string
160
+ },
161
+ ]
162
+ guardrails: [
163
+ {
164
+ metricId: string
165
+ overrides: {
166
+ delayHours: 0
167
+ windowHours: 0
168
+ window: string
169
+ winRiskThreshold: 0
170
+ loseRiskThreshold: 0
135
171
  }
136
- category: string
137
- isNumeric: boolean
138
- percentileValue: number
172
+ },
173
+ ]
174
+ activationMetric: {
175
+ metricId: string
176
+ overrides: {
177
+ delayHours: 0
178
+ windowHours: 0
179
+ window: string
180
+ winRiskThreshold: 0
181
+ loseRiskThreshold: 0
139
182
  }
140
- }>
141
- }
142
- customProperties: {
143
- key: {
144
- name: string
145
- value: string[]
146
183
  }
147
184
  }
185
+ resultSummary: {
186
+ status: string
187
+ winner: string
188
+ conclusions: string
189
+ releasedVariationId: string
190
+ excludeFromPayload: boolean
191
+ }
192
+ }
193
+
194
+ export type GrowthbookFeature = {
195
+ id: string
196
+ dateCreated: string
197
+ dateUpdated: string
148
198
  archived: boolean
149
199
  description: string
150
- maintainerId: string
151
- _maintainer: {
152
- _links: {
153
- self: {
154
- href: string
155
- type: string
156
- }
157
- }
158
- _id: string
159
- role: string
160
- email: string
161
- firstName: string
162
- lastName: string
163
- }
164
- maintainerTeamKey: string
165
- _maintainerTeam: {
166
- key: string
167
- name: string
168
- _links: {
169
- parent: {
170
- href: string
171
- type: string
172
- }
173
- roles: {
174
- href: string
175
- type: string
176
- }
177
- self: {
178
- href: string
179
- type: string
180
- }
181
- }
182
- }
183
- archivedDate: number
184
- deprecated: boolean
185
- deprecatedDate: number
186
- defaults: {
187
- onVariation: number
188
- offVariation: number
189
- }
190
- _purpose: string
191
- migrationSettings: {
192
- contextKind: string
193
- stageCount: number
194
- }
200
+ owner: string
201
+ project: string
202
+ valueType: string
203
+ defaultValue: string
204
+ tags: string[]
195
205
  environments: {
196
206
  [key: string]: {
197
- on: boolean
198
- archived: boolean
199
- salt: string
200
- sel: string
201
- lastModified: number
202
- version: number
203
- _site: {
204
- href: string
207
+ enabled: boolean
208
+ defaultValue: string
209
+ rules: {
210
+ description: string
211
+ condition: string
212
+ savedGroupTargeting: {matchType: string; savedGroups: string[]}[]
213
+ id: string
214
+ enabled: boolean
205
215
  type: string
206
- }
207
- _environmentName: string
208
- trackEvents: boolean
209
- trackEventsFallthrough: boolean
210
- targets: Array<{
211
- values: string[]
212
- variation: number
213
- contextKind: string
214
- }>
215
- contextTargets: Array<{
216
- values: string[]
217
- variation: number
218
- contextKind: string
219
- }>
220
- rules: Array<{
221
- clauses: Array<{
222
- attribute: string
223
- op: string
224
- values: unknown[]
225
- negate: boolean
226
- }>
227
- trackEvents: boolean
228
- }>
229
- fallthrough: {
230
- variation: number
231
- }
232
- offVariation: number
233
- prerequisites: Array<{
234
- key: string
235
- variation: number
236
- }>
237
- _summary: {
238
- variations: {
239
- [key: string]: {
240
- rules: number
241
- nullRules: number
242
- targets: number
243
- contextTargets: number
244
- isFallthrough?: boolean
245
- isOff?: boolean
246
- }
247
- }
248
- prerequisites: number
216
+ value: string
217
+ variations: {value: string; variationId: string}[]
218
+ }[]
219
+ definition: string
220
+ draft: {
221
+ enabled: boolean
222
+ defaultValue: string
223
+ rules: {
224
+ description: string
225
+ condition: string
226
+ savedGroupTargeting: {matchType: string; savedGroups: string[]}[]
227
+ id: string
228
+ enabled: boolean
229
+ type: string
230
+ value: string
231
+ variations: {value: string; variationId: string}[]
232
+ }[]
233
+ definition: string
249
234
  }
250
235
  }
251
236
  }
252
- includeInSnippet: boolean
253
- goalIds: string[]
237
+ prerequisites: {
238
+ parentId: string
239
+ parentCondition: string
240
+ }[]
241
+ revision: {
242
+ version: number
243
+ comment: string
244
+ date: string
245
+ publishedBy: string
246
+ }
254
247
  }
@@ -1,48 +0,0 @@
1
- import {definePlugin, FieldDefinition, isObjectInputProps} from 'sanity'
2
-
3
- import {Secrets} from './components/Secrets'
4
- import {fieldLevelExperiments} from './fieldExperiments'
5
- import {flattenSchemaType} from './utils/flattenSchemaType'
6
- import {getExperiments} from './utils/launchDarkly'
7
-
8
- export type LaunchDarklyFieldLevelConfig = {
9
- fields: (string | FieldDefinition)[]
10
- projectKey: string
11
- tags?: string[]
12
- }
13
-
14
- export const launchDarklyFieldLevel = definePlugin<LaunchDarklyFieldLevelConfig>((config) => {
15
- const {fields, projectKey, tags} = config
16
- return {
17
- name: 'sanity-growthbook-personalistaion-plugin-field-level-experiments',
18
- plugins: [
19
- fieldLevelExperiments({
20
- fields,
21
- experiments: (client) => getExperiments({client, projectKey, tags}),
22
- }),
23
- ],
24
-
25
- form: {
26
- components: {
27
- input: (props) => {
28
- const isRootInput = props.id === 'root' && isObjectInputProps(props)
29
-
30
- if (!isRootInput) {
31
- return props.renderDefault(props)
32
- }
33
-
34
- const flatFieldTypeNames = flattenSchemaType(props.schemaType).map(
35
- (field) => field.type.name,
36
- )
37
-
38
- const hasExperiment = flatFieldTypeNames.some((name) => name.startsWith('experiment'))
39
-
40
- if (!hasExperiment) {
41
- return props.renderDefault(props)
42
- }
43
- return Secrets(props, 'launchdarkly')
44
- },
45
- },
46
- },
47
- }
48
- })
@@ -1,54 +0,0 @@
1
- import {SanityClient} from 'sanity'
2
-
3
- import {LaunchDarklyFieldLevelConfig} from '../launchDarklyExperiments'
4
- import {ExperimentType, LaunchDarklyFlagItem} from '../types'
5
-
6
- export const getExperiments = async ({
7
- client,
8
- projectKey,
9
- tags,
10
- }: Omit<LaunchDarklyFieldLevelConfig, 'fields'> & {client: SanityClient}): Promise<
11
- ExperimentType[]
12
- > => {
13
- const query = `*[_id == 'secrets.launchdarkly'][0].secrets.apiKey`
14
-
15
- const secret = await client.fetch(query) // secret is stored in the content lake using @sanity/studio-secrets
16
- if (!secret) return []
17
-
18
- const url = new URL(`https://app.launchdarkly.com/api/v2/flags/${projectKey}`)
19
-
20
- if (tags) {
21
- url.searchParams.set('filter', `tags:${tags.join('+')}`)
22
- }
23
-
24
- const featureExperiments: ExperimentType[] = []
25
- let hasMore = true
26
- const offset = 0
27
- const limit = 10
28
-
29
- while (hasMore) {
30
- url.searchParams.set('offset', offset.toString())
31
- url.searchParams.set('limit', limit.toString())
32
- const responseFlags = await fetch(url, {
33
- headers: {
34
- Authorization: secret,
35
- },
36
- })
37
-
38
- const {items} = await responseFlags.json()
39
- const experiments = items.map((flag: LaunchDarklyFlagItem) => ({
40
- id: flag.key,
41
- label: flag.name,
42
- variants: flag.variations.map((variation) => ({
43
- id: variation.value,
44
- label: variation.name,
45
- })),
46
- }))
47
- featureExperiments.push(...experiments)
48
- if (items.length !== limit) {
49
- hasMore = false
50
- }
51
- }
52
-
53
- return featureExperiments
54
- }