@metamask-previews/remote-feature-flag-controller 1.2.0-preview-2ebcbae7 → 1.2.0-preview-ae144301
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/utils/user-segmentation-utils.cjs +50 -9
- package/dist/utils/user-segmentation-utils.cjs.map +1 -1
- package/dist/utils/user-segmentation-utils.d.cts +5 -3
- package/dist/utils/user-segmentation-utils.d.cts.map +1 -1
- package/dist/utils/user-segmentation-utils.d.mts +5 -3
- package/dist/utils/user-segmentation-utils.d.mts.map +1 -1
- package/dist/utils/user-segmentation-utils.mjs +50 -9
- package/dist/utils/user-segmentation-utils.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,21 +1,62 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isFeatureFlagWithScopeValue = exports.generateDeterministicRandomNumber = void 0;
|
|
4
|
-
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
/**
|
|
6
|
+
* Converts a UUID string to a BigInt by removing dashes and converting to hexadecimal.
|
|
7
|
+
* @param uuid - The UUID string to convert
|
|
8
|
+
* @returns The UUID as a BigInt value
|
|
9
|
+
*/
|
|
10
|
+
function uuidStringToBigInt(uuid) {
|
|
11
|
+
return BigInt(`0x${uuid.replace(/-/gu, '')}`);
|
|
12
|
+
}
|
|
13
|
+
const MIN_UUID_V4 = '00000000-0000-4000-8000-000000000000';
|
|
14
|
+
const MAX_UUID_V4 = 'ffffffff-ffff-4fff-bfff-ffffffffffff';
|
|
15
|
+
const MIN_UUID_V4_BIGINT = uuidStringToBigInt(MIN_UUID_V4);
|
|
16
|
+
const MAX_UUID_V4_BIGINT = uuidStringToBigInt(MAX_UUID_V4);
|
|
17
|
+
const UUID_V4_VALUE_RANGE_BIGINT = MAX_UUID_V4_BIGINT - MIN_UUID_V4_BIGINT;
|
|
5
18
|
/**
|
|
6
19
|
* Generates a deterministic random number between 0 and 1 based on a metaMetricsId.
|
|
7
20
|
* This is useful for A/B testing and feature flag rollouts where we want
|
|
8
21
|
* consistent group assignment for the same user.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
22
|
+
* @param metaMetricsId - The unique identifier used to generate the deterministic random number. Must be either:
|
|
23
|
+
* - A UUIDv4 string (e.g., '123e4567-e89b-12d3-a456-426614174000'
|
|
24
|
+
* - A hex string with '0x' prefix (e.g., '0x86bacb9b2bf9a7e8d2b147eadb95ac9aaa26842327cd24afc8bd4b3c1d136420')
|
|
25
|
+
* @returns A number between 0 and 1, deterministically generated from the input ID.
|
|
26
|
+
* The same input will always produce the same output.
|
|
12
27
|
*/
|
|
13
28
|
function generateDeterministicRandomNumber(metaMetricsId) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
29
|
+
if (!metaMetricsId) {
|
|
30
|
+
throw new Error('MetaMetrics ID cannot be empty');
|
|
31
|
+
}
|
|
32
|
+
let idValue;
|
|
33
|
+
let maxValue;
|
|
34
|
+
// uuidv4 format
|
|
35
|
+
if ((0, uuid_1.validate)(metaMetricsId)) {
|
|
36
|
+
if ((0, uuid_1.version)(metaMetricsId) !== 4) {
|
|
37
|
+
throw new Error(`Invalid UUID version. Expected v4, got v${(0, uuid_1.version)(metaMetricsId)}`);
|
|
38
|
+
}
|
|
39
|
+
idValue = uuidStringToBigInt(metaMetricsId) - MIN_UUID_V4_BIGINT;
|
|
40
|
+
maxValue = UUID_V4_VALUE_RANGE_BIGINT;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// hex format with 0x prefix
|
|
44
|
+
if (!metaMetricsId.startsWith('0x')) {
|
|
45
|
+
throw new Error('Hex ID must start with 0x prefix');
|
|
46
|
+
}
|
|
47
|
+
const cleanId = metaMetricsId.slice(2);
|
|
48
|
+
const EXPECTED_HEX_LENGTH = 64; // 32 bytes = 64 hex characters
|
|
49
|
+
if (cleanId.length !== EXPECTED_HEX_LENGTH) {
|
|
50
|
+
throw new Error(`Invalid hex ID length. Expected ${EXPECTED_HEX_LENGTH} characters, got ${cleanId.length}`);
|
|
51
|
+
}
|
|
52
|
+
if (!/^[0-9a-f]+$/iu.test(cleanId)) {
|
|
53
|
+
throw new Error('Hex ID contains invalid characters');
|
|
54
|
+
}
|
|
55
|
+
idValue = BigInt(`0x${cleanId}`);
|
|
56
|
+
maxValue = BigInt(`0x${'f'.repeat(cleanId.length)}`);
|
|
57
|
+
}
|
|
58
|
+
// Use BigInt division first, then convert to number to maintain precision
|
|
59
|
+
return Number((idValue * BigInt(1000000)) / maxValue) / 1000000;
|
|
19
60
|
}
|
|
20
61
|
exports.generateDeterministicRandomNumber = generateDeterministicRandomNumber;
|
|
21
62
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-segmentation-utils.cjs","sourceRoot":"","sources":["../../src/utils/user-segmentation-utils.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"user-segmentation-utils.cjs","sourceRoot":"","sources":["../../src/utils/user-segmentation-utils.ts"],"names":[],"mappings":";;;AACA,+BAAwE;AAIxE;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO,MAAM,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,WAAW,GAAG,sCAAsC,CAAC;AAC3D,MAAM,WAAW,GAAG,sCAAsC,CAAC;AAC3D,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;AAC3D,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;AAC3D,MAAM,0BAA0B,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAE3E;;;;;;;;;GASG;AACH,SAAgB,iCAAiC,CAC/C,aAAqB;IAErB,IAAI,CAAC,aAAa,EAAE;QAClB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;KACnD;IAED,IAAI,OAAe,CAAC;IACpB,IAAI,QAAgB,CAAC;IAErB,gBAAgB;IAChB,IAAI,IAAA,eAAY,EAAC,aAAa,CAAC,EAAE;QAC/B,IAAI,IAAA,cAAW,EAAC,aAAa,CAAC,KAAK,CAAC,EAAE;YACpC,MAAM,IAAI,KAAK,CACb,2CAA2C,IAAA,cAAW,EAAC,aAAa,CAAC,EAAE,CACxE,CAAC;SACH;QACD,OAAO,GAAG,kBAAkB,CAAC,aAAa,CAAC,GAAG,kBAAkB,CAAC;QACjE,QAAQ,GAAG,0BAA0B,CAAC;KACvC;SAAM;QACL,4BAA4B;QAC5B,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;YACnC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;SACrD;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,mBAAmB,GAAG,EAAE,CAAC,CAAC,+BAA+B;QAE/D,IAAI,OAAO,CAAC,MAAM,KAAK,mBAAmB,EAAE;YAC1C,MAAM,IAAI,KAAK,CACb,mCAAmC,mBAAmB,oBAAoB,OAAO,CAAC,MAAM,EAAE,CAC3F,CAAC;SACH;QAED,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YAClC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;SACvD;QAED,OAAO,GAAG,MAAM,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;QACjC,QAAQ,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;KACtD;IAED,0EAA0E;IAC1E,OAAO,MAAM,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,OAAS,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,OAAS,CAAC;AACtE,CAAC;AA5CD,8EA4CC;AAED;;;;;;GAMG;AACI,MAAM,2BAA2B,GAAG,CACzC,WAAiB,EACqB,EAAE;IACxC,OAAO,CACL,OAAO,WAAW,KAAK,QAAQ;QAC/B,WAAW,KAAK,IAAI;QACpB,OAAO,IAAI,WAAW,CACvB,CAAC;AACJ,CAAC,CAAC;AARW,QAAA,2BAA2B,+BAQtC","sourcesContent":["import type { Json } from '@metamask/utils';\nimport { validate as uuidValidate, version as uuidVersion } from 'uuid';\n\nimport type { FeatureFlagScopeValue } from '../remote-feature-flag-controller-types';\n\n/**\n * Converts a UUID string to a BigInt by removing dashes and converting to hexadecimal.\n * @param uuid - The UUID string to convert\n * @returns The UUID as a BigInt value\n */\nfunction uuidStringToBigInt(uuid: string): bigint {\n return BigInt(`0x${uuid.replace(/-/gu, '')}`);\n}\n\nconst MIN_UUID_V4 = '00000000-0000-4000-8000-000000000000';\nconst MAX_UUID_V4 = 'ffffffff-ffff-4fff-bfff-ffffffffffff';\nconst MIN_UUID_V4_BIGINT = uuidStringToBigInt(MIN_UUID_V4);\nconst MAX_UUID_V4_BIGINT = uuidStringToBigInt(MAX_UUID_V4);\nconst UUID_V4_VALUE_RANGE_BIGINT = MAX_UUID_V4_BIGINT - MIN_UUID_V4_BIGINT;\n\n/**\n * Generates a deterministic random number between 0 and 1 based on a metaMetricsId.\n * This is useful for A/B testing and feature flag rollouts where we want\n * consistent group assignment for the same user.\n * @param metaMetricsId - The unique identifier used to generate the deterministic random number. Must be either:\n * - A UUIDv4 string (e.g., '123e4567-e89b-12d3-a456-426614174000'\n * - A hex string with '0x' prefix (e.g., '0x86bacb9b2bf9a7e8d2b147eadb95ac9aaa26842327cd24afc8bd4b3c1d136420')\n * @returns A number between 0 and 1, deterministically generated from the input ID.\n * The same input will always produce the same output.\n */\nexport function generateDeterministicRandomNumber(\n metaMetricsId: string,\n): number {\n if (!metaMetricsId) {\n throw new Error('MetaMetrics ID cannot be empty');\n }\n\n let idValue: bigint;\n let maxValue: bigint;\n\n // uuidv4 format\n if (uuidValidate(metaMetricsId)) {\n if (uuidVersion(metaMetricsId) !== 4) {\n throw new Error(\n `Invalid UUID version. Expected v4, got v${uuidVersion(metaMetricsId)}`,\n );\n }\n idValue = uuidStringToBigInt(metaMetricsId) - MIN_UUID_V4_BIGINT;\n maxValue = UUID_V4_VALUE_RANGE_BIGINT;\n } else {\n // hex format with 0x prefix\n if (!metaMetricsId.startsWith('0x')) {\n throw new Error('Hex ID must start with 0x prefix');\n }\n\n const cleanId = metaMetricsId.slice(2);\n const EXPECTED_HEX_LENGTH = 64; // 32 bytes = 64 hex characters\n\n if (cleanId.length !== EXPECTED_HEX_LENGTH) {\n throw new Error(\n `Invalid hex ID length. Expected ${EXPECTED_HEX_LENGTH} characters, got ${cleanId.length}`,\n );\n }\n\n if (!/^[0-9a-f]+$/iu.test(cleanId)) {\n throw new Error('Hex ID contains invalid characters');\n }\n\n idValue = BigInt(`0x${cleanId}`);\n maxValue = BigInt(`0x${'f'.repeat(cleanId.length)}`);\n }\n\n // Use BigInt division first, then convert to number to maintain precision\n return Number((idValue * BigInt(1_000_000)) / maxValue) / 1_000_000;\n}\n\n/**\n * Type guard to check if a value is a feature flag with scope.\n * Used to validate feature flag objects that contain scope-based configurations.\n *\n * @param featureFlag - The value to check if it's a feature flag with scope\n * @returns True if the value is a feature flag with scope, false otherwise\n */\nexport const isFeatureFlagWithScopeValue = (\n featureFlag: Json,\n): featureFlag is FeatureFlagScopeValue => {\n return (\n typeof featureFlag === 'object' &&\n featureFlag !== null &&\n 'scope' in featureFlag\n );\n};\n"]}
|
|
@@ -4,9 +4,11 @@ import type { FeatureFlagScopeValue } from "../remote-feature-flag-controller-ty
|
|
|
4
4
|
* Generates a deterministic random number between 0 and 1 based on a metaMetricsId.
|
|
5
5
|
* This is useful for A/B testing and feature flag rollouts where we want
|
|
6
6
|
* consistent group assignment for the same user.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* @param metaMetricsId - The unique identifier used to generate the deterministic random number. Must be either:
|
|
8
|
+
* - A UUIDv4 string (e.g., '123e4567-e89b-12d3-a456-426614174000'
|
|
9
|
+
* - A hex string with '0x' prefix (e.g., '0x86bacb9b2bf9a7e8d2b147eadb95ac9aaa26842327cd24afc8bd4b3c1d136420')
|
|
10
|
+
* @returns A number between 0 and 1, deterministically generated from the input ID.
|
|
11
|
+
* The same input will always produce the same output.
|
|
10
12
|
*/
|
|
11
13
|
export declare function generateDeterministicRandomNumber(metaMetricsId: string): number;
|
|
12
14
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-segmentation-utils.d.cts","sourceRoot":"","sources":["../../src/utils/user-segmentation-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;
|
|
1
|
+
{"version":3,"file":"user-segmentation-utils.d.cts","sourceRoot":"","sources":["../../src/utils/user-segmentation-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAG5C,OAAO,KAAK,EAAE,qBAAqB,EAAE,oDAAgD;AAiBrF;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,MAAM,GACpB,MAAM,CA0CR;AAED;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,gBACzB,IAAI,yCAOlB,CAAC"}
|
|
@@ -4,9 +4,11 @@ import type { FeatureFlagScopeValue } from "../remote-feature-flag-controller-ty
|
|
|
4
4
|
* Generates a deterministic random number between 0 and 1 based on a metaMetricsId.
|
|
5
5
|
* This is useful for A/B testing and feature flag rollouts where we want
|
|
6
6
|
* consistent group assignment for the same user.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* @param metaMetricsId - The unique identifier used to generate the deterministic random number. Must be either:
|
|
8
|
+
* - A UUIDv4 string (e.g., '123e4567-e89b-12d3-a456-426614174000'
|
|
9
|
+
* - A hex string with '0x' prefix (e.g., '0x86bacb9b2bf9a7e8d2b147eadb95ac9aaa26842327cd24afc8bd4b3c1d136420')
|
|
10
|
+
* @returns A number between 0 and 1, deterministically generated from the input ID.
|
|
11
|
+
* The same input will always produce the same output.
|
|
10
12
|
*/
|
|
11
13
|
export declare function generateDeterministicRandomNumber(metaMetricsId: string): number;
|
|
12
14
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-segmentation-utils.d.mts","sourceRoot":"","sources":["../../src/utils/user-segmentation-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;
|
|
1
|
+
{"version":3,"file":"user-segmentation-utils.d.mts","sourceRoot":"","sources":["../../src/utils/user-segmentation-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAG5C,OAAO,KAAK,EAAE,qBAAqB,EAAE,oDAAgD;AAiBrF;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,MAAM,GACpB,MAAM,CA0CR;AAED;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,gBACzB,IAAI,yCAOlB,CAAC"}
|
|
@@ -1,18 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
import { validate as uuidValidate, version as uuidVersion } from "uuid";
|
|
2
|
+
/**
|
|
3
|
+
* Converts a UUID string to a BigInt by removing dashes and converting to hexadecimal.
|
|
4
|
+
* @param uuid - The UUID string to convert
|
|
5
|
+
* @returns The UUID as a BigInt value
|
|
6
|
+
*/
|
|
7
|
+
function uuidStringToBigInt(uuid) {
|
|
8
|
+
return BigInt(`0x${uuid.replace(/-/gu, '')}`);
|
|
9
|
+
}
|
|
10
|
+
const MIN_UUID_V4 = '00000000-0000-4000-8000-000000000000';
|
|
11
|
+
const MAX_UUID_V4 = 'ffffffff-ffff-4fff-bfff-ffffffffffff';
|
|
12
|
+
const MIN_UUID_V4_BIGINT = uuidStringToBigInt(MIN_UUID_V4);
|
|
13
|
+
const MAX_UUID_V4_BIGINT = uuidStringToBigInt(MAX_UUID_V4);
|
|
14
|
+
const UUID_V4_VALUE_RANGE_BIGINT = MAX_UUID_V4_BIGINT - MIN_UUID_V4_BIGINT;
|
|
2
15
|
/**
|
|
3
16
|
* Generates a deterministic random number between 0 and 1 based on a metaMetricsId.
|
|
4
17
|
* This is useful for A/B testing and feature flag rollouts where we want
|
|
5
18
|
* consistent group assignment for the same user.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
19
|
+
* @param metaMetricsId - The unique identifier used to generate the deterministic random number. Must be either:
|
|
20
|
+
* - A UUIDv4 string (e.g., '123e4567-e89b-12d3-a456-426614174000'
|
|
21
|
+
* - A hex string with '0x' prefix (e.g., '0x86bacb9b2bf9a7e8d2b147eadb95ac9aaa26842327cd24afc8bd4b3c1d136420')
|
|
22
|
+
* @returns A number between 0 and 1, deterministically generated from the input ID.
|
|
23
|
+
* The same input will always produce the same output.
|
|
9
24
|
*/
|
|
10
25
|
export function generateDeterministicRandomNumber(metaMetricsId) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
26
|
+
if (!metaMetricsId) {
|
|
27
|
+
throw new Error('MetaMetrics ID cannot be empty');
|
|
28
|
+
}
|
|
29
|
+
let idValue;
|
|
30
|
+
let maxValue;
|
|
31
|
+
// uuidv4 format
|
|
32
|
+
if (uuidValidate(metaMetricsId)) {
|
|
33
|
+
if (uuidVersion(metaMetricsId) !== 4) {
|
|
34
|
+
throw new Error(`Invalid UUID version. Expected v4, got v${uuidVersion(metaMetricsId)}`);
|
|
35
|
+
}
|
|
36
|
+
idValue = uuidStringToBigInt(metaMetricsId) - MIN_UUID_V4_BIGINT;
|
|
37
|
+
maxValue = UUID_V4_VALUE_RANGE_BIGINT;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// hex format with 0x prefix
|
|
41
|
+
if (!metaMetricsId.startsWith('0x')) {
|
|
42
|
+
throw new Error('Hex ID must start with 0x prefix');
|
|
43
|
+
}
|
|
44
|
+
const cleanId = metaMetricsId.slice(2);
|
|
45
|
+
const EXPECTED_HEX_LENGTH = 64; // 32 bytes = 64 hex characters
|
|
46
|
+
if (cleanId.length !== EXPECTED_HEX_LENGTH) {
|
|
47
|
+
throw new Error(`Invalid hex ID length. Expected ${EXPECTED_HEX_LENGTH} characters, got ${cleanId.length}`);
|
|
48
|
+
}
|
|
49
|
+
if (!/^[0-9a-f]+$/iu.test(cleanId)) {
|
|
50
|
+
throw new Error('Hex ID contains invalid characters');
|
|
51
|
+
}
|
|
52
|
+
idValue = BigInt(`0x${cleanId}`);
|
|
53
|
+
maxValue = BigInt(`0x${'f'.repeat(cleanId.length)}`);
|
|
54
|
+
}
|
|
55
|
+
// Use BigInt division first, then convert to number to maintain precision
|
|
56
|
+
return Number((idValue * BigInt(1000000)) / maxValue) / 1000000;
|
|
16
57
|
}
|
|
17
58
|
/**
|
|
18
59
|
* Type guard to check if a value is a feature flag with scope.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-segmentation-utils.mjs","sourceRoot":"","sources":["../../src/utils/user-segmentation-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"user-segmentation-utils.mjs","sourceRoot":"","sources":["../../src/utils/user-segmentation-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,aAAa;AAIxE;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO,MAAM,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,WAAW,GAAG,sCAAsC,CAAC;AAC3D,MAAM,WAAW,GAAG,sCAAsC,CAAC;AAC3D,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;AAC3D,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;AAC3D,MAAM,0BAA0B,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAE3E;;;;;;;;;GASG;AACH,MAAM,UAAU,iCAAiC,CAC/C,aAAqB;IAErB,IAAI,CAAC,aAAa,EAAE;QAClB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;KACnD;IAED,IAAI,OAAe,CAAC;IACpB,IAAI,QAAgB,CAAC;IAErB,gBAAgB;IAChB,IAAI,YAAY,CAAC,aAAa,CAAC,EAAE;QAC/B,IAAI,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE;YACpC,MAAM,IAAI,KAAK,CACb,2CAA2C,WAAW,CAAC,aAAa,CAAC,EAAE,CACxE,CAAC;SACH;QACD,OAAO,GAAG,kBAAkB,CAAC,aAAa,CAAC,GAAG,kBAAkB,CAAC;QACjE,QAAQ,GAAG,0BAA0B,CAAC;KACvC;SAAM;QACL,4BAA4B;QAC5B,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;YACnC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;SACrD;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,mBAAmB,GAAG,EAAE,CAAC,CAAC,+BAA+B;QAE/D,IAAI,OAAO,CAAC,MAAM,KAAK,mBAAmB,EAAE;YAC1C,MAAM,IAAI,KAAK,CACb,mCAAmC,mBAAmB,oBAAoB,OAAO,CAAC,MAAM,EAAE,CAC3F,CAAC;SACH;QAED,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YAClC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;SACvD;QAED,OAAO,GAAG,MAAM,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;QACjC,QAAQ,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;KACtD;IAED,0EAA0E;IAC1E,OAAO,MAAM,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,OAAS,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,OAAS,CAAC;AACtE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACzC,WAAiB,EACqB,EAAE;IACxC,OAAO,CACL,OAAO,WAAW,KAAK,QAAQ;QAC/B,WAAW,KAAK,IAAI;QACpB,OAAO,IAAI,WAAW,CACvB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import type { Json } from '@metamask/utils';\nimport { validate as uuidValidate, version as uuidVersion } from 'uuid';\n\nimport type { FeatureFlagScopeValue } from '../remote-feature-flag-controller-types';\n\n/**\n * Converts a UUID string to a BigInt by removing dashes and converting to hexadecimal.\n * @param uuid - The UUID string to convert\n * @returns The UUID as a BigInt value\n */\nfunction uuidStringToBigInt(uuid: string): bigint {\n return BigInt(`0x${uuid.replace(/-/gu, '')}`);\n}\n\nconst MIN_UUID_V4 = '00000000-0000-4000-8000-000000000000';\nconst MAX_UUID_V4 = 'ffffffff-ffff-4fff-bfff-ffffffffffff';\nconst MIN_UUID_V4_BIGINT = uuidStringToBigInt(MIN_UUID_V4);\nconst MAX_UUID_V4_BIGINT = uuidStringToBigInt(MAX_UUID_V4);\nconst UUID_V4_VALUE_RANGE_BIGINT = MAX_UUID_V4_BIGINT - MIN_UUID_V4_BIGINT;\n\n/**\n * Generates a deterministic random number between 0 and 1 based on a metaMetricsId.\n * This is useful for A/B testing and feature flag rollouts where we want\n * consistent group assignment for the same user.\n * @param metaMetricsId - The unique identifier used to generate the deterministic random number. Must be either:\n * - A UUIDv4 string (e.g., '123e4567-e89b-12d3-a456-426614174000'\n * - A hex string with '0x' prefix (e.g., '0x86bacb9b2bf9a7e8d2b147eadb95ac9aaa26842327cd24afc8bd4b3c1d136420')\n * @returns A number between 0 and 1, deterministically generated from the input ID.\n * The same input will always produce the same output.\n */\nexport function generateDeterministicRandomNumber(\n metaMetricsId: string,\n): number {\n if (!metaMetricsId) {\n throw new Error('MetaMetrics ID cannot be empty');\n }\n\n let idValue: bigint;\n let maxValue: bigint;\n\n // uuidv4 format\n if (uuidValidate(metaMetricsId)) {\n if (uuidVersion(metaMetricsId) !== 4) {\n throw new Error(\n `Invalid UUID version. Expected v4, got v${uuidVersion(metaMetricsId)}`,\n );\n }\n idValue = uuidStringToBigInt(metaMetricsId) - MIN_UUID_V4_BIGINT;\n maxValue = UUID_V4_VALUE_RANGE_BIGINT;\n } else {\n // hex format with 0x prefix\n if (!metaMetricsId.startsWith('0x')) {\n throw new Error('Hex ID must start with 0x prefix');\n }\n\n const cleanId = metaMetricsId.slice(2);\n const EXPECTED_HEX_LENGTH = 64; // 32 bytes = 64 hex characters\n\n if (cleanId.length !== EXPECTED_HEX_LENGTH) {\n throw new Error(\n `Invalid hex ID length. Expected ${EXPECTED_HEX_LENGTH} characters, got ${cleanId.length}`,\n );\n }\n\n if (!/^[0-9a-f]+$/iu.test(cleanId)) {\n throw new Error('Hex ID contains invalid characters');\n }\n\n idValue = BigInt(`0x${cleanId}`);\n maxValue = BigInt(`0x${'f'.repeat(cleanId.length)}`);\n }\n\n // Use BigInt division first, then convert to number to maintain precision\n return Number((idValue * BigInt(1_000_000)) / maxValue) / 1_000_000;\n}\n\n/**\n * Type guard to check if a value is a feature flag with scope.\n * Used to validate feature flag objects that contain scope-based configurations.\n *\n * @param featureFlag - The value to check if it's a feature flag with scope\n * @returns True if the value is a feature flag with scope, false otherwise\n */\nexport const isFeatureFlagWithScopeValue = (\n featureFlag: Json,\n): featureFlag is FeatureFlagScopeValue => {\n return (\n typeof featureFlag === 'object' &&\n featureFlag !== null &&\n 'scope' in featureFlag\n );\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/remote-feature-flag-controller",
|
|
3
|
-
"version": "1.2.0-preview-
|
|
3
|
+
"version": "1.2.0-preview-ae144301",
|
|
4
4
|
"description": "The RemoteFeatureFlagController manages the retrieval and caching of remote feature flags",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|