@naturalcycles/abba 2.10.0 → 2.11.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.
package/dist/abba.d.ts CHANGED
@@ -65,6 +65,13 @@ export declare class Abba {
65
65
  * Hot method.
66
66
  */
67
67
  generateUserAssignments(userId: string, segmentationData: SegmentationData, existingOnly?: boolean): Promise<DecoratedUserAssignment[]>;
68
+ /**
69
+ * Returns all user IDs that are assigned to any of the given buckets in the given experiment.
70
+ *
71
+ * @param experimentKey - The `key` field of the experiment (not the DB id).
72
+ * @param bucketKeys - The `key` fields of the buckets to include.
73
+ */
74
+ getUserIdsInBuckets(experimentKey: string, bucketKeys: readonly string[]): Promise<Set<string>>;
68
75
  /**
69
76
  * Get assignment statistics for an experiment.
70
77
  * Cold method.
package/dist/abba.js CHANGED
@@ -291,6 +291,26 @@ export class Abba {
291
291
  await this.userAssignmentDao.saveBatch(newAssignments);
292
292
  return assignments;
293
293
  }
294
+ /**
295
+ * Returns all user IDs that are assigned to any of the given buckets in the given experiment.
296
+ *
297
+ * @param experimentKey - The `key` field of the experiment (not the DB id).
298
+ * @param bucketKeys - The `key` fields of the buckets to include.
299
+ */
300
+ async getUserIdsInBuckets(experimentKey, bucketKeys) {
301
+ if (!bucketKeys.length)
302
+ return new Set();
303
+ const experiment = await this.experimentDao.getByKey(experimentKey);
304
+ if (!experiment)
305
+ return new Set();
306
+ const bucketKeySet = new Set(bucketKeys);
307
+ const experimentBuckets = await this.bucketDao.getByExperimentId(experiment.id);
308
+ const matchedBucketIds = experimentBuckets.filter(b => bucketKeySet.has(b.key)).map(b => b.id);
309
+ if (!matchedBucketIds.length)
310
+ return new Set();
311
+ const userIds = await this.userAssignmentDao.getUserIdsByBucketIds(matchedBucketIds);
312
+ return new Set(userIds);
313
+ }
294
314
  /**
295
315
  * Get assignment statistics for an experiment.
296
316
  * Cold method.
@@ -7,5 +7,6 @@ export declare class UserAssignmentDao extends CommonDao<UserAssignment> {
7
7
  deleteByExperimentId(experimentId: string): Promise<void>;
8
8
  getCountByExperimentId(experimentId: string): Promise<number>;
9
9
  getCountByBucketId(bucketId: string): Promise<number>;
10
+ getUserIdsByBucketIds(bucketIds: string[]): Promise<string[]>;
10
11
  }
11
12
  export declare function userAssignmentDao(db: CommonDB): UserAssignmentDao;
@@ -1,4 +1,5 @@
1
1
  import { CommonDao } from '@naturalcycles/db-lib/dao';
2
+ import { _uniq } from '@naturalcycles/js-lib/array';
2
3
  export class UserAssignmentDao extends CommonDao {
3
4
  async getUserAssignmentByExperimentId(userId, experimentId) {
4
5
  const query = this.query().filterEq('userId', userId).filterEq('experimentId', experimentId);
@@ -18,6 +19,16 @@ export class UserAssignmentDao extends CommonDao {
18
19
  async getCountByBucketId(bucketId) {
19
20
  return await this.query().filterEq('bucketId', bucketId).runQueryCount();
20
21
  }
22
+ async getUserIdsByBucketIds(bucketIds) {
23
+ if (!bucketIds.length)
24
+ return [];
25
+ const userIds = await this.query()
26
+ .filterIn('bucketId', bucketIds)
27
+ .select(['userId'])
28
+ .distinct()
29
+ .runQuerySingleColumn();
30
+ return _uniq(userIds);
31
+ }
21
32
  }
22
33
  export function userAssignmentDao(db) {
23
34
  return new UserAssignmentDao({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/abba",
3
3
  "type": "module",
4
- "version": "2.10.0",
4
+ "version": "2.11.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/db-lib": "^10",
7
7
  "@naturalcycles/js-lib": "^15",
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "devDependencies": {
13
13
  "@types/semver": "^7",
14
- "@typescript/native-preview": "7.0.0-dev.20260415.1",
14
+ "@typescript/native-preview": "beta",
15
15
  "@naturalcycles/dev-lib": "18.4.2"
16
16
  },
17
17
  "exports": {
package/src/abba.ts CHANGED
@@ -411,6 +411,31 @@ export class Abba {
411
411
  return assignments
412
412
  }
413
413
 
414
+ /**
415
+ * Returns all user IDs that are assigned to any of the given buckets in the given experiment.
416
+ *
417
+ * @param experimentKey - The `key` field of the experiment (not the DB id).
418
+ * @param bucketKeys - The `key` fields of the buckets to include.
419
+ */
420
+ async getUserIdsInBuckets(
421
+ experimentKey: string,
422
+ bucketKeys: readonly string[],
423
+ ): Promise<Set<string>> {
424
+ if (!bucketKeys.length) return new Set()
425
+
426
+ const experiment = await this.experimentDao.getByKey(experimentKey)
427
+ if (!experiment) return new Set()
428
+
429
+ const bucketKeySet = new Set(bucketKeys)
430
+ const experimentBuckets = await this.bucketDao.getByExperimentId(experiment.id)
431
+ const matchedBucketIds = experimentBuckets.filter(b => bucketKeySet.has(b.key)).map(b => b.id)
432
+
433
+ if (!matchedBucketIds.length) return new Set()
434
+
435
+ const userIds = await this.userAssignmentDao.getUserIdsByBucketIds(matchedBucketIds)
436
+ return new Set(userIds)
437
+ }
438
+
414
439
  /**
415
440
  * Get assignment statistics for an experiment.
416
441
  * Cold method.
@@ -1,5 +1,6 @@
1
1
  import type { CommonDB } from '@naturalcycles/db-lib'
2
2
  import { CommonDao } from '@naturalcycles/db-lib/dao'
3
+ import { _uniq } from '@naturalcycles/js-lib/array'
3
4
  import type { UserAssignment } from '../types.js'
4
5
 
5
6
  export class UserAssignmentDao extends CommonDao<UserAssignment> {
@@ -31,6 +32,18 @@ export class UserAssignmentDao extends CommonDao<UserAssignment> {
31
32
  async getCountByBucketId(bucketId: string): Promise<number> {
32
33
  return await this.query().filterEq('bucketId', bucketId).runQueryCount()
33
34
  }
35
+
36
+ async getUserIdsByBucketIds(bucketIds: string[]): Promise<string[]> {
37
+ if (!bucketIds.length) return []
38
+
39
+ const userIds = await this.query()
40
+ .filterIn('bucketId', bucketIds)
41
+ .select(['userId'])
42
+ .distinct()
43
+ .runQuerySingleColumn<string>()
44
+
45
+ return _uniq(userIds)
46
+ }
34
47
  }
35
48
 
36
49
  export function userAssignmentDao(db: CommonDB): UserAssignmentDao {