@naturalcycles/abba 1.7.0 → 1.8.0

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.
Files changed (57) hide show
  1. package/dist/abba.d.ts +15 -29
  2. package/dist/abba.js +56 -107
  3. package/dist/dao/bucket.dao.d.ts +5 -0
  4. package/dist/dao/bucket.dao.js +15 -0
  5. package/dist/dao/experiment.dao.d.ts +10 -0
  6. package/dist/dao/experiment.dao.js +19 -0
  7. package/dist/dao/userAssignment.dao.d.ts +5 -0
  8. package/dist/dao/userAssignment.dao.js +15 -0
  9. package/dist/index.d.ts +0 -1
  10. package/dist/index.js +1 -1
  11. package/dist/migrations/init.sql +47 -0
  12. package/dist/types.d.ts +30 -7
  13. package/dist/util.d.ts +5 -5
  14. package/package.json +7 -8
  15. package/readme.md +8 -9
  16. package/src/abba.ts +90 -134
  17. package/src/dao/bucket.dao.ts +13 -0
  18. package/src/dao/experiment.dao.ts +22 -0
  19. package/src/dao/userAssignment.dao.ts +13 -0
  20. package/src/index.ts +0 -3
  21. package/src/migrations/init.sql +47 -0
  22. package/src/types.ts +33 -7
  23. package/src/util.ts +5 -5
  24. package/dist/prisma-output/index-browser.js +0 -141
  25. package/dist/prisma-output/index.d.ts +0 -5526
  26. package/dist/prisma-output/index.js +0 -217
  27. package/dist/prisma-output/libquery_engine-darwin-arm64.dylib.node +0 -0
  28. package/dist/prisma-output/libquery_engine-darwin.dylib.node +0 -0
  29. package/dist/prisma-output/libquery_engine-debian-openssl-1.1.x.so.node +0 -0
  30. package/dist/prisma-output/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  31. package/dist/prisma-output/runtime/esm/index-browser.mjs +0 -2370
  32. package/dist/prisma-output/runtime/esm/index.mjs +0 -40587
  33. package/dist/prisma-output/runtime/esm/proxy.mjs +0 -113
  34. package/dist/prisma-output/runtime/index-browser.d.ts +0 -269
  35. package/dist/prisma-output/runtime/index-browser.js +0 -2621
  36. package/dist/prisma-output/runtime/index.d.ts +0 -1384
  37. package/dist/prisma-output/runtime/index.js +0 -59183
  38. package/dist/prisma-output/runtime/proxy.d.ts +0 -1384
  39. package/dist/prisma-output/runtime/proxy.js +0 -13576
  40. package/dist/prisma-output/schema.prisma +0 -47
  41. package/src/prisma-output/index-browser.js +0 -141
  42. package/src/prisma-output/index.d.ts +0 -5526
  43. package/src/prisma-output/index.js +0 -217
  44. package/src/prisma-output/libquery_engine-darwin-arm64.dylib.node +0 -0
  45. package/src/prisma-output/libquery_engine-darwin.dylib.node +0 -0
  46. package/src/prisma-output/libquery_engine-debian-openssl-1.1.x.so.node +0 -0
  47. package/src/prisma-output/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  48. package/src/prisma-output/runtime/esm/index-browser.mjs +0 -2370
  49. package/src/prisma-output/runtime/esm/index.mjs +0 -40587
  50. package/src/prisma-output/runtime/esm/proxy.mjs +0 -113
  51. package/src/prisma-output/runtime/index-browser.d.ts +0 -269
  52. package/src/prisma-output/runtime/index-browser.js +0 -2621
  53. package/src/prisma-output/runtime/index.d.ts +0 -1384
  54. package/src/prisma-output/runtime/index.js +0 -59183
  55. package/src/prisma-output/runtime/proxy.d.ts +0 -1384
  56. package/src/prisma-output/runtime/proxy.js +0 -13576
  57. package/src/prisma-output/schema.prisma +0 -47
package/src/abba.ts CHANGED
@@ -1,41 +1,55 @@
1
- import { Bucket, Experiment, Prisma, PrismaClient, UserAssignment } from './prisma-output'
2
- import { AssignmentStatus } from './types'
3
- import { determineAssignment, validateSegmentationRules, validateTotalBucketRatio } from './util'
1
+ import { pMap, Saved } from '@naturalcycles/js-lib'
4
2
  import {
5
- BucketInput,
3
+ AbbaConfig,
4
+ AssignmentStatus,
5
+ Bucket,
6
+ Experiment,
6
7
  ExperimentWithBuckets,
7
- ExperimentInput,
8
- SegmentationData,
9
- SegmentationRule,
10
- AssignmentStatistics,
11
- } from '.'
12
-
13
- // Note: Schema currently contains an output dir which generates all the files to the prisma dir
14
- // it would be tidier not to include it here when possible later on:
15
- // Explanation is here: https://github.com/prisma/prisma/issues/9435#issuecomment-960290681
8
+ UserAssignment,
9
+ } from './types'
10
+ import { determineAssignment, validateSegmentationRules, validateTotalBucketRatio } from './util'
11
+ import { ExperimentDao, experimentDao } from './dao/experiment.dao'
12
+ import { UserAssignmentDao, userAssignmentDao } from './dao/userAssignment.dao'
13
+ import { BucketDao, bucketDao } from './dao/bucket.dao'
14
+ import { SegmentationData, SegmentationRule, AssignmentStatistics } from '.'
16
15
 
17
16
  export class Abba {
18
- private client: PrismaClient
17
+ private experimentDao: ExperimentDao
18
+ private bucketDao: BucketDao
19
+ private userAssignmentDao: UserAssignmentDao
19
20
 
20
- constructor(dbUrl?: string) {
21
- this.client = new PrismaClient({
22
- datasources: {
23
- db: {
24
- url: dbUrl,
25
- },
26
- },
27
- })
21
+ constructor({ db }: AbbaConfig) {
22
+ this.experimentDao = experimentDao(db)
23
+ this.bucketDao = bucketDao(db)
24
+ this.userAssignmentDao = userAssignmentDao(db)
28
25
  }
26
+
27
+ // TODO: Cache me
29
28
  /**
30
29
  * Returns all experiments
31
30
  *
32
31
  * @returns
33
32
  */
34
33
  async getAllExperiments(excludeInactive: boolean = false): Promise<ExperimentWithBuckets[]> {
35
- return await this.client.experiment.findMany({
36
- where: excludeInactive ? { NOT: { status: AssignmentStatus.Inactive } } : undefined,
37
- include: { buckets: true },
38
- })
34
+ const query = this.experimentDao.query()
35
+ if (excludeInactive) {
36
+ query.filter('status', '!=', AssignmentStatus.Inactive)
37
+ }
38
+
39
+ const experiments = await this.experimentDao.runQuery(query)
40
+ const buckets = await this.bucketDao
41
+ .query()
42
+ .filter(
43
+ 'experimentId',
44
+ 'in',
45
+ experiments.map(e => e.id),
46
+ )
47
+ .runQuery()
48
+
49
+ return experiments.map(experiment => ({
50
+ ...experiment,
51
+ buckets: buckets.filter(bucket => bucket.experimentId === experiment.id),
52
+ }))
39
53
  }
40
54
 
41
55
  /**
@@ -46,28 +60,21 @@ export class Abba {
46
60
  * @returns
47
61
  */
48
62
  async createExperiment(
49
- experiment: ExperimentInput,
50
- buckets: BucketInput[],
63
+ experiment: Experiment,
64
+ buckets: Bucket[],
51
65
  ): Promise<ExperimentWithBuckets> {
52
66
  if (experiment.status === AssignmentStatus.Active) {
53
67
  validateTotalBucketRatio(buckets)
54
68
  }
55
69
 
56
- const created = await this.client.experiment.create({
57
- data: {
58
- ...experiment,
59
- rules: experiment.rules as Prisma.InputJsonArray,
60
- buckets: {
61
- createMany: {
62
- data: buckets,
63
- },
64
- },
65
- },
66
- include: {
67
- buckets: true,
68
- },
69
- })
70
- return created
70
+ const created = await this.experimentDao.save(experiment)
71
+
72
+ return {
73
+ ...created,
74
+ buckets: await this.bucketDao.saveBatch(
75
+ buckets.map(b => ({ ...b, experimentId: created.id })),
76
+ ),
77
+ }
71
78
  }
72
79
 
73
80
  /**
@@ -81,19 +88,21 @@ export class Abba {
81
88
  */
82
89
  async saveExperiment(
83
90
  id: number,
84
- experiment: ExperimentInput,
85
- buckets: BucketInput[],
91
+ experiment: Experiment,
92
+ buckets: Bucket[],
86
93
  ): Promise<ExperimentWithBuckets> {
87
94
  if (experiment.status === AssignmentStatus.Active) {
88
95
  validateTotalBucketRatio(buckets)
89
96
  }
90
97
 
91
- const updatedExperiment = await this.updateExperiment(id, experiment)
92
- const updatedBuckets = await this.saveBuckets(buckets)
98
+ const updated = await this.experimentDao.save({
99
+ ...experiment,
100
+ id,
101
+ })
93
102
 
94
103
  return {
95
- ...updatedExperiment,
96
- buckets: updatedBuckets,
104
+ ...updated,
105
+ buckets: await this.bucketDao.saveBatch(buckets.map(b => ({ ...b, experimentId: id }))),
97
106
  }
98
107
  }
99
108
 
@@ -103,7 +112,7 @@ export class Abba {
103
112
  * @param id
104
113
  */
105
114
  async deleteExperiment(id: number): Promise<void> {
106
- await this.client.experiment.delete({ where: { id } })
115
+ await this.experimentDao.deleteById(id)
107
116
  }
108
117
 
109
118
  /**
@@ -111,8 +120,8 @@ export class Abba {
111
120
  *
112
121
  * @param experimentId
113
122
  * @param userId
114
- * @param createNew
115
- * @param segmentationData
123
+ * @param existingOnly Do not generate any new assignments for this experiment
124
+ * @param segmentationData Required if existingOnly is false
116
125
  * @returns
117
126
  */
118
127
  async getUserAssignment(
@@ -120,13 +129,12 @@ export class Abba {
120
129
  userId: string,
121
130
  existingOnly: boolean,
122
131
  segmentationData?: SegmentationData,
123
- ): Promise<UserAssignment | null> {
124
- const experiment = await this.client.experiment.findUnique({
125
- where: { id: experimentId },
126
- include: { buckets: true },
127
- })
132
+ ): Promise<Saved<UserAssignment> | null> {
133
+ const experiment = await this.experimentDao.requireById(experimentId)
128
134
  if (!experiment) throw new Error('Experiment not found')
129
135
 
136
+ const buckets = await this.bucketDao.getBy('experimentId', experimentId)
137
+
130
138
  const existing = await this.getExistingUserAssignment(experimentId, userId)
131
139
  if (existing) return existing
132
140
 
@@ -135,17 +143,17 @@ export class Abba {
135
143
  if (!segmentationData)
136
144
  throw new Error('Segmentation data required when creating a new assignment')
137
145
 
138
- return await this.generateUserAssignment(experiment, userId, segmentationData)
146
+ return await this.generateUserAssignment({ ...experiment, buckets }, userId, segmentationData)
139
147
  }
140
148
 
141
149
  /**
142
150
  * Get all existing user assignments
143
151
  *
144
- * @param userId G
152
+ * @param userId
145
153
  * @returns
146
154
  */
147
- async getAllExistingUserAssignments(userId: string): Promise<UserAssignment[]> {
148
- return await this.client.userAssignment.findMany({ where: { userId } })
155
+ async getAllExistingUserAssignments(userId: string): Promise<Saved<UserAssignment>[]> {
156
+ return await this.userAssignmentDao.getBy('userId', userId)
149
157
  }
150
158
 
151
159
  /**
@@ -158,12 +166,12 @@ export class Abba {
158
166
  async generateUserAssignments(
159
167
  userId: string,
160
168
  segmentationData: SegmentationData,
161
- ): Promise<UserAssignment[]> {
169
+ ): Promise<Saved<UserAssignment>[]> {
162
170
  const experiments = await this.getAllExperiments(true)
163
171
  const existingAssignments = await this.getAllExistingUserAssignments(userId)
164
172
 
165
- const assignments: UserAssignment[] = []
166
- const generatedAssignments: Promise<UserAssignment | null>[] = []
173
+ const assignments: Saved<UserAssignment>[] = []
174
+ const generatedAssignments: Promise<Saved<UserAssignment> | null>[] = []
167
175
 
168
176
  for (const experiment of experiments) {
169
177
  const existing = existingAssignments.find(ua => ua.experimentId === experiment.id)
@@ -176,7 +184,7 @@ export class Abba {
176
184
  }
177
185
 
178
186
  const generated = await Promise.all(generatedAssignments)
179
- const filtered = generated.filter((ua): ua is UserAssignment => ua !== null)
187
+ const filtered = generated.filter((ua): ua is Saved<UserAssignment> => ua !== null)
180
188
  return [...assignments, ...filtered]
181
189
  }
182
190
 
@@ -188,21 +196,17 @@ export class Abba {
188
196
  */
189
197
  async getExperimentAssignmentStatistics(experimentId: number): Promise<AssignmentStatistics> {
190
198
  const statistics = {
191
- sampled: await this.client.userAssignment.count({ where: { experimentId } }),
199
+ sampled: await this.userAssignmentDao
200
+ .query()
201
+ .filterEq('experimentId', experimentId)
202
+ .runQueryCount(),
192
203
  buckets: {},
193
204
  }
194
205
 
195
- const buckets = await this.client.bucket.findMany({ where: { experimentId } })
196
- const assignmentCounts = await this.client.userAssignment.groupBy({
197
- where: { experimentId },
198
- by: ['bucketId'],
199
- _count: {
200
- _all: true,
201
- },
202
- })
203
-
204
- buckets.forEach(({ id }) => {
205
- statistics.buckets[`${id}`] = assignmentCounts.find(i => i.bucketId === id)?._count?._all || 0
206
+ const buckets = await this.bucketDao.getBy('experimentId', experimentId)
207
+ await pMap(buckets, async bucket => {
208
+ const count = this.userAssignmentDao.query().filterEq('bucketId', bucket.id)
209
+ statistics[bucket.id] = await this.userAssignmentDao.runQueryCount(count)
206
210
  })
207
211
 
208
212
  return statistics
@@ -220,16 +224,17 @@ export class Abba {
220
224
  experiment: ExperimentWithBuckets,
221
225
  userId: string,
222
226
  segmentationData: SegmentationData,
223
- ): Promise<UserAssignment | null> {
227
+ ): Promise<Saved<UserAssignment> | null> {
224
228
  const segmentationMatch = validateSegmentationRules(
225
229
  experiment.rules as unknown as SegmentationRule[],
226
230
  segmentationData,
227
231
  )
228
232
  if (!segmentationMatch) return null
229
233
 
230
- const bucketId = determineAssignment(experiment.sampling, experiment.buckets)
231
- return await this.client.userAssignment.create({
232
- data: { userId, experimentId: experiment.id, bucketId },
234
+ return await this.userAssignmentDao.save({
235
+ userId,
236
+ experimentId: experiment.id,
237
+ bucketId: determineAssignment(experiment.sampling, experiment.buckets),
233
238
  })
234
239
  }
235
240
 
@@ -243,58 +248,9 @@ export class Abba {
243
248
  private async getExistingUserAssignment(
244
249
  experimentId: number,
245
250
  userId: string,
246
- ): Promise<UserAssignment | null> {
247
- return await this.client.userAssignment.findFirst({ where: { userId, experimentId } })
248
- }
249
-
250
- /**
251
- * Update experiment information
252
- *
253
- * @param id
254
- * @param experiment
255
- * @param rules
256
- * @returns
257
- */
258
- private async updateExperiment(id: number, experiment: Partial<Experiment>): Promise<Experiment> {
259
- return await this.client.experiment.update({
260
- where: { id },
261
- data: {
262
- ...experiment,
263
- rules: experiment.rules as Prisma.InputJsonArray,
264
- },
265
- })
266
- }
267
-
268
- /**
269
- * Upserts bucket info
270
- *
271
- * @param id
272
- * @param experiment
273
- * @returns
274
- */
275
- private async saveBuckets(buckets: BucketInput[]): Promise<Bucket[]> {
276
- const savedBuckets: Promise<Bucket>[] = []
277
- for (const bucket of buckets) {
278
- const { id, ...data } = bucket
279
- if (id) {
280
- savedBuckets.push(this.client.bucket.update({ where: { id }, data }))
281
- } else {
282
- savedBuckets.push(
283
- this.client.bucket.create({
284
- data: {
285
- key: data.key,
286
- ratio: data.ratio,
287
- experiment: {
288
- connect: {
289
- id: data.experimentId,
290
- },
291
- },
292
- },
293
- }),
294
- )
295
- }
296
- }
297
-
298
- return await Promise.all(savedBuckets)
251
+ ): Promise<Saved<UserAssignment> | null> {
252
+ const assignments = await this.userAssignmentDao.getBy('userId', userId)
253
+ const assignment = assignments.find(assignment => assignment.experimentId === experimentId)
254
+ return assignment || null
299
255
  }
300
256
  }
@@ -0,0 +1,13 @@
1
+ import { CommonDao, CommonDB } from '@naturalcycles/db-lib'
2
+ import { Bucket } from '../types'
3
+
4
+ export class BucketDao extends CommonDao<Bucket> {}
5
+
6
+ export const bucketDao = (db: CommonDB): BucketDao =>
7
+ new BucketDao({
8
+ db,
9
+ table: 'Bucket',
10
+ createId: false, // mysql auto_increment is used instead
11
+ idType: 'number',
12
+ assignGeneratedIds: true,
13
+ })
@@ -0,0 +1,22 @@
1
+ import { CommonDao, CommonDB } from '@naturalcycles/db-lib'
2
+ import { Saved } from '@naturalcycles/js-lib'
3
+ import { BaseExperiment, Experiment } from '../types'
4
+
5
+ type ExperimentDBM = Saved<BaseExperiment> & {
6
+ rules: string | null
7
+ }
8
+
9
+ export class ExperimentDao extends CommonDao<Experiment, ExperimentDBM> {}
10
+
11
+ export const experimentDao = (db: CommonDB): ExperimentDao =>
12
+ new ExperimentDao({
13
+ db,
14
+ table: 'Experiment',
15
+ createId: false, // mysql auto_increment is used instead
16
+ idType: 'number',
17
+ assignGeneratedIds: true,
18
+ hooks: {
19
+ beforeBMToDBM: bm => ({ ...bm, rules: bm.rules.length ? JSON.stringify(bm.rules) : null }),
20
+ beforeDBMToBM: dbm => ({ ...dbm, rules: dbm.rules && JSON.parse(dbm.rules) }),
21
+ },
22
+ })
@@ -0,0 +1,13 @@
1
+ import { CommonDao, CommonDB } from '@naturalcycles/db-lib'
2
+ import { UserAssignment } from '../types'
3
+
4
+ export class UserAssignmentDao extends CommonDao<UserAssignment> {}
5
+
6
+ export const userAssignmentDao = (db: CommonDB): UserAssignmentDao =>
7
+ new UserAssignmentDao({
8
+ db,
9
+ table: 'UserAssignment',
10
+ createId: false, // mysql auto_increment is used instead
11
+ idType: 'number',
12
+ assignGeneratedIds: true,
13
+ })
package/src/index.ts CHANGED
@@ -1,5 +1,2 @@
1
- export type { Bucket, Experiment, UserAssignment } from './prisma-output'
2
-
3
1
  export * from './types'
4
-
5
2
  export { Abba } from './abba'
@@ -0,0 +1,47 @@
1
+ -- CreateTable
2
+ CREATE TABLE IF NOT EXISTS `Bucket` (
3
+ `id` INTEGER NOT NULL AUTO_INCREMENT,
4
+ `experimentId` INTEGER NOT NULL,
5
+ `key` VARCHAR(10) NOT NULL,
6
+ `ratio` INTEGER NOT NULL,
7
+ `created` INTEGER(11) NOT NULL,
8
+ `updated` INTEGER(11) NOT NULL,
9
+
10
+ PRIMARY KEY (`id`)
11
+ ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
12
+
13
+ -- CreateTable
14
+ CREATE TABLE IF NOT EXISTS `Experiment` (
15
+ `id` INTEGER NOT NULL AUTO_INCREMENT,
16
+ `name` VARCHAR(191) NOT NULL,
17
+ `status` INTEGER NOT NULL,
18
+ `sampling` INTEGER NOT NULL,
19
+ `description` VARCHAR(240) NULL,
20
+ `created` INTEGER(11) NOT NULL,
21
+ `updated` INTEGER(11) NOT NULL,
22
+ `rules` JSON NULL,
23
+
24
+ PRIMARY KEY (`id`)
25
+ ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
26
+
27
+ -- CreateTable
28
+ CREATE TABLE IF NOT EXISTS `UserAssignment` (
29
+ `id` INTEGER NOT NULL AUTO_INCREMENT,
30
+ `userId` VARCHAR(191) NOT NULL,
31
+ `experimentId` INTEGER NOT NULL,
32
+ `bucketId` INTEGER NULL,
33
+ `created` INTEGER(11) NOT NULL,
34
+ `updated` INTEGER(11) NOT NULL,
35
+
36
+ UNIQUE INDEX `UserAssignment_userId_experimentId_key`(`userId`, `experimentId`),
37
+ PRIMARY KEY (`id`)
38
+ ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
39
+
40
+ -- AddForeignKey
41
+ ALTER TABLE `Bucket` ADD CONSTRAINT `Bucket_experimentId_fkey` FOREIGN KEY (`experimentId`) REFERENCES `Experiment`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
42
+
43
+ -- AddForeignKey
44
+ ALTER TABLE `UserAssignment` ADD CONSTRAINT `UserAssignment_bucketId_fkey` FOREIGN KEY (`bucketId`) REFERENCES `Bucket`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
45
+
46
+ -- AddForeignKey
47
+ ALTER TABLE `UserAssignment` ADD CONSTRAINT `UserAssignment_experimentId_fkey` FOREIGN KEY (`experimentId`) REFERENCES `Experiment`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
package/src/types.ts CHANGED
@@ -1,16 +1,42 @@
1
- import { Bucket, Experiment } from './prisma-output'
1
+ import { CommonDB } from '@naturalcycles/db-lib'
2
+ import { BaseDBEntity, Saved } from '@naturalcycles/js-lib'
2
3
 
3
- export type Unsaved<T> = Omit<T, 'createdAt' | 'updatedAt'> & {
4
- id?: number
4
+ export interface AbbaConfig {
5
+ db: CommonDB
5
6
  }
6
7
 
7
- export type ExperimentWithBuckets = Experiment & {
8
- buckets: Bucket[]
8
+ export type BaseExperiment = BaseDBEntity<number> & {
9
+ name: string
10
+ status: number
11
+ sampling: number
12
+ description: string | null
9
13
  }
10
14
 
11
- export type ExperimentInput = Unsaved<Experiment>
15
+ export type Experiment = BaseExperiment & {
16
+ rules: SegmentationRule[]
17
+ }
18
+
19
+ export type ExperimentWithBuckets = Saved<Experiment> & {
20
+ buckets: Saved<Bucket>[]
21
+ }
22
+
23
+ export interface BucketInput {
24
+ experimentId: number
25
+ key: string
26
+ ratio: number
27
+ }
12
28
 
13
- export type BucketInput = Unsaved<Bucket>
29
+ export type Bucket = BaseDBEntity<number> & {
30
+ experimentId: number
31
+ key: string
32
+ ratio: number
33
+ }
34
+
35
+ export type UserAssignment = BaseDBEntity<number> & {
36
+ userId: string
37
+ experimentId: number
38
+ bucketId: number | null
39
+ }
14
40
 
15
41
  export type SegmentationData = Record<string, string | boolean | number>
16
42
 
package/src/util.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { Saved } from '@naturalcycles/js-lib'
1
2
  import { satisfies } from 'semver'
2
- import { Bucket } from './prisma-output'
3
- import { BucketInput, SegmentationData, SegmentationRule } from '.'
3
+ import { Bucket, SegmentationData, SegmentationRule } from './types'
4
4
 
5
5
  /**
6
6
  * Generate a random number between 0 and 100
@@ -18,7 +18,7 @@ export const rollDie = (): number => {
18
18
  * @param buckets
19
19
  * @returns
20
20
  */
21
- export const determineAssignment = (sampling: number, buckets: Bucket[]): number | null => {
21
+ export const determineAssignment = (sampling: number, buckets: Saved<Bucket>[]): number | null => {
22
22
  // Should this person be considered for the experiment?
23
23
  if (rollDie() > sampling) {
24
24
  return null
@@ -34,7 +34,7 @@ export const determineAssignment = (sampling: number, buckets: Bucket[]): number
34
34
  * @param buckets
35
35
  * @returns
36
36
  */
37
- export const determineBucket = (buckets: Bucket[]): number => {
37
+ export const determineBucket = (buckets: Saved<Bucket>[]): number => {
38
38
  const bucketRoll = rollDie()
39
39
  let range: [number, number] | undefined
40
40
  const bucket = buckets.find(b => {
@@ -62,7 +62,7 @@ export const determineBucket = (buckets: Bucket[]): number => {
62
62
  * @param buckets
63
63
  * @returns
64
64
  */
65
- export const validateTotalBucketRatio = (buckets: BucketInput[]): void => {
65
+ export const validateTotalBucketRatio = (buckets: Bucket[]): void => {
66
66
  const bucketSum = buckets.reduce((sum, current) => sum + current.ratio, 0)
67
67
  if (bucketSum !== 100) {
68
68
  throw new Error('Total bucket ratio must be 100 before you can activate an experiment')
@@ -1,141 +0,0 @@
1
- Object.defineProperty(exports, '__esModule', { value: true })
2
-
3
- const { Decimal } = require('./runtime/index-browser')
4
-
5
- const Prisma = {}
6
-
7
- exports.Prisma = Prisma
8
-
9
- /**
10
- * Prisma Client JS version: 3.13.0
11
- * Query Engine version: efdf9b1183dddfd4258cd181a72125755215ab7b
12
- */
13
- Prisma.prismaVersion = {
14
- client: '3.13.0',
15
- engine: 'efdf9b1183dddfd4258cd181a72125755215ab7b',
16
- }
17
-
18
- Prisma.PrismaClientKnownRequestError = () => {
19
- throw new Error(`PrismaClientKnownRequestError is unable to be run in the browser.
20
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`)
21
- }
22
- Prisma.PrismaClientUnknownRequestError = () => {
23
- throw new Error(`PrismaClientUnknownRequestError is unable to be run in the browser.
24
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`)
25
- }
26
- Prisma.PrismaClientRustPanicError = () => {
27
- throw new Error(`PrismaClientRustPanicError is unable to be run in the browser.
28
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`)
29
- }
30
- Prisma.PrismaClientInitializationError = () => {
31
- throw new Error(`PrismaClientInitializationError is unable to be run in the browser.
32
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`)
33
- }
34
- Prisma.PrismaClientValidationError = () => {
35
- throw new Error(`PrismaClientValidationError is unable to be run in the browser.
36
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`)
37
- }
38
- Prisma.Decimal = Decimal
39
-
40
- /**
41
- * Re-export of sql-template-tag
42
- */
43
- Prisma.sql = () => {
44
- throw new Error(`sqltag is unable to be run in the browser.
45
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`)
46
- }
47
- Prisma.empty = () => {
48
- throw new Error(`empty is unable to be run in the browser.
49
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`)
50
- }
51
- Prisma.join = () => {
52
- throw new Error(`join is unable to be run in the browser.
53
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`)
54
- }
55
- Prisma.raw = () => {
56
- throw new Error(`raw is unable to be run in the browser.
57
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`)
58
- }
59
- Prisma.validator = () => val => val
60
-
61
- /**
62
- * Shorthand utilities for JSON filtering
63
- */
64
- Prisma.DbNull = 'DbNull'
65
- Prisma.JsonNull = 'JsonNull'
66
- Prisma.AnyNull = 'AnyNull'
67
-
68
- /**
69
- * Enums
70
- */
71
- // Based on
72
- // https://github.com/microsoft/TypeScript/issues/3192#issuecomment-261720275
73
- function makeEnum(x) {
74
- return x
75
- }
76
-
77
- exports.Prisma.BucketScalarFieldEnum = makeEnum({
78
- id: 'id',
79
- experimentId: 'experimentId',
80
- key: 'key',
81
- ratio: 'ratio',
82
- createdAt: 'createdAt',
83
- updatedAt: 'updatedAt',
84
- })
85
-
86
- exports.Prisma.ExperimentScalarFieldEnum = makeEnum({
87
- id: 'id',
88
- name: 'name',
89
- status: 'status',
90
- sampling: 'sampling',
91
- createdAt: 'createdAt',
92
- updatedAt: 'updatedAt',
93
- description: 'description',
94
- rules: 'rules',
95
- })
96
-
97
- exports.Prisma.UserAssignmentScalarFieldEnum = makeEnum({
98
- id: 'id',
99
- userId: 'userId',
100
- experimentId: 'experimentId',
101
- bucketId: 'bucketId',
102
- createdAt: 'createdAt',
103
- updatedAt: 'updatedAt',
104
- })
105
-
106
- exports.Prisma.SortOrder = makeEnum({
107
- asc: 'asc',
108
- desc: 'desc',
109
- })
110
-
111
- exports.Prisma.NullableJsonNullValueInput = makeEnum({
112
- DbNull: 'DbNull',
113
- JsonNull: 'JsonNull',
114
- })
115
-
116
- exports.Prisma.JsonNullValueFilter = makeEnum({
117
- DbNull: 'DbNull',
118
- JsonNull: 'JsonNull',
119
- AnyNull: 'AnyNull',
120
- })
121
-
122
- exports.Prisma.ModelName = makeEnum({
123
- Bucket: 'Bucket',
124
- Experiment: 'Experiment',
125
- UserAssignment: 'UserAssignment',
126
- })
127
-
128
- /**
129
- * Create the Client
130
- */
131
- class PrismaClient {
132
- constructor() {
133
- throw new Error(
134
- `PrismaClient is unable to be run in the browser.
135
- In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues`,
136
- )
137
- }
138
- }
139
- exports.PrismaClient = PrismaClient
140
-
141
- Object.assign(exports, Prisma)