@plyaz/core 1.0.3 → 1.1.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/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { CACHE_MAX_SIZE_DEFAULT, CACHE_CLEANUP_INTERVAL_DEFAULT, FILE_CHECK_INTERVAL_DEFAULT, FEATURE_FLAG_FILE_PATHS, FEATURE_FLAG_CACHE_TTL_DEFAULT, FEATURES } from '@plyaz/config';
1
+ import { CACHE_MAX_SIZE_DEFAULT, CACHE_CLEANUP_INTERVAL_DEFAULT, TIME_CONSTANTS, FORMAT_CONSTANTS, FILE_CHECK_INTERVAL_DEFAULT, FEATURE_FLAG_FILE_PATHS, FEATURE_FLAG_CACHE_TTL_DEFAULT, MATH_CONSTANTS, ISO_STANDARDS, FEATURES, FNV_CONSTANTS, HASH_SEED_CONSTANTS } from '@plyaz/config';
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
4
  import { promisify } from 'util';
@@ -23,24 +23,21 @@ var __decorateClass = (decorators, target, key, kind) => {
23
23
  };
24
24
  var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
25
25
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
26
-
27
- // src/utils/common/hash.ts
28
26
  function hashString(str) {
29
- const HASH_SHIFT = 5;
30
- let hash = 0;
27
+ if (str.length === 0) return 0;
28
+ let hash = FNV_CONSTANTS.FNV_32_OFFSET;
31
29
  for (let i = 0; i < str.length; i++) {
32
- const char = str.charCodeAt(i);
33
- hash = (hash << HASH_SHIFT) - hash + char;
34
- hash = hash & hash;
30
+ hash ^= str.charCodeAt(i);
31
+ hash = Math.imul(hash, FNV_CONSTANTS.FNV_32_PRIME) >>> 0;
35
32
  }
36
- return Math.abs(hash);
33
+ return hash >>> 0;
37
34
  }
38
35
  __name(hashString, "hashString");
39
36
  function isInRollout(identifier, percentage) {
40
- if (percentage >= 100) return true;
37
+ if (percentage >= MATH_CONSTANTS.PERCENTAGE_MAX) return true;
41
38
  if (percentage <= 0) return false;
42
39
  const hash = hashString(identifier);
43
- return hash % 100 < percentage;
40
+ return hash % MATH_CONSTANTS.PERCENTAGE_MAX < percentage;
44
41
  }
45
42
  __name(isInRollout, "isInRollout");
46
43
  function createRolloutIdentifier(featureKey, userId) {
@@ -69,23 +66,22 @@ var HashUtils = {
69
66
  * @param totalBuckets - Total number of buckets (default: 100)
70
67
  * @returns true if identifier is in the bucket range
71
68
  */
72
- isInBucketRange: /* @__PURE__ */ __name((identifier, startBucket, endBucket, totalBuckets = 100) => {
69
+ isInBucketRange: /* @__PURE__ */ __name((identifier, startBucket, endBucket, totalBuckets = MATH_CONSTANTS.PERCENTAGE_MAX) => {
73
70
  const bucket = hashString(identifier) % totalBuckets;
74
71
  return bucket >= startBucket && bucket <= endBucket;
75
72
  }, "isInBucketRange"),
76
73
  /**
77
74
  * Creates a deterministic random seed from a string.
75
+ * Uses the improved hash function and ensures the seed is within
76
+ * the safe range for JavaScript's Math.random seeding.
78
77
  *
79
78
  * @param str - String to convert to seed
80
- * @returns Deterministic seed value
79
+ * @returns Deterministic seed value (0 to 2^31-1)
81
80
  */
82
81
  createSeed: /* @__PURE__ */ __name((str) => {
83
- const SAFE_INT = 2147483647;
84
- return hashString(str) % SAFE_INT;
82
+ return hashString(str) % HASH_SEED_CONSTANTS.MAX_SAFE_SEED;
85
83
  }, "createSeed")
86
84
  };
87
-
88
- // src/utils/common/values.ts
89
85
  function isStringFalsy(value) {
90
86
  if (value === "") return true;
91
87
  const lower = value.toLowerCase().trim();
@@ -151,7 +147,7 @@ var ValueUtils = {
151
147
  */
152
148
  isValidPercentage: /* @__PURE__ */ __name((value) => {
153
149
  if (typeof value !== "number") return false;
154
- return !isNaN(value) && isFinite(value) && value >= 0 && value <= 100;
150
+ return !isNaN(value) && isFinite(value) && value >= 0 && value <= MATH_CONSTANTS.PERCENTAGE_MAX;
155
151
  }, "isValidPercentage"),
156
152
  /**
157
153
  * Clamps a number to a specific range.
@@ -197,8 +193,6 @@ var ValueUtils = {
197
193
  return current;
198
194
  }, "getNestedProperty")
199
195
  };
200
-
201
- // src/utils/featureFlags/context.ts
202
196
  var FeatureFlagContextBuilder = class _FeatureFlagContextBuilder {
203
197
  static {
204
198
  __name(this, "FeatureFlagContextBuilder");
@@ -394,7 +388,7 @@ var ContextUtils = {
394
388
  if (context.platform && !["web", "mobile", "desktop"].includes(context.platform)) {
395
389
  errors.push("Platform must be web, mobile, or desktop");
396
390
  }
397
- if (context.country && context.country.length !== 2) {
391
+ if (context.country && context.country.length !== ISO_STANDARDS.ISO_COUNTRY_CODE_LENGTH) {
398
392
  errors.push("Country must be a 2-letter ISO country code");
399
393
  }
400
394
  return {
@@ -1113,6 +1107,9 @@ var MemoryCacheStrategy = class {
1113
1107
  this.cleanupTimer = setInterval(() => {
1114
1108
  this.cleanupExpiredEntries();
1115
1109
  }, this.cleanupInterval);
1110
+ if (this.cleanupTimer && typeof this.cleanupTimer.unref === "function") {
1111
+ this.cleanupTimer.unref();
1112
+ }
1116
1113
  }
1117
1114
  /**
1118
1115
  * Removes expired entries from the cache.
@@ -1161,8 +1158,6 @@ var MemoryCacheStrategy = class {
1161
1158
  }
1162
1159
  }
1163
1160
  };
1164
-
1165
- // src/base/cache/strategies/redis.ts
1166
1161
  var RedisCacheStrategy = class {
1167
1162
  /**
1168
1163
  * Creates a new Redis cache strategy.
@@ -1200,7 +1195,7 @@ var RedisCacheStrategy = class {
1200
1195
  const redisKey = this.buildRedisKey(key);
1201
1196
  const serializedEntry = JSON.stringify(entry);
1202
1197
  const ttlMs = entry.expiresAt - Date.now();
1203
- const ttlSeconds = Math.max(1, Math.ceil(ttlMs / 1e3));
1198
+ const ttlSeconds = Math.max(1, Math.ceil(ttlMs / TIME_CONSTANTS.MILLISECONDS_PER_SECOND));
1204
1199
  await this.client.set(redisKey, serializedEntry, "EX", ttlSeconds);
1205
1200
  this.stats.setCount++;
1206
1201
  }
@@ -1371,7 +1366,7 @@ var CacheManager = class {
1371
1366
  const finalTtl = ttl ?? this.config.ttl;
1372
1367
  const entry = {
1373
1368
  data: value,
1374
- expiresAt: Date.now() + finalTtl * 1e3,
1369
+ expiresAt: Date.now() + finalTtl * TIME_CONSTANTS.MILLISECONDS_PER_SECOND,
1375
1370
  createdAt: Date.now()
1376
1371
  };
1377
1372
  await this.strategy.set(key, entry);
@@ -1464,8 +1459,6 @@ var CacheManager = class {
1464
1459
  await this.strategy.dispose?.();
1465
1460
  }
1466
1461
  };
1467
-
1468
- // src/domain/featureFlags/provider.ts
1469
1462
  var FeatureFlagProvider = class {
1470
1463
  /**
1471
1464
  * Creates a new feature flag provider.
@@ -1700,7 +1693,7 @@ var FeatureFlagProvider = class {
1700
1693
  void this.refresh().catch((error) => {
1701
1694
  this.log("Auto-refresh failed:", error);
1702
1695
  });
1703
- }, this.config.refreshInterval * 1e3);
1696
+ }, this.config.refreshInterval * TIME_CONSTANTS.MILLISECONDS_PER_SECOND);
1704
1697
  }
1705
1698
  }
1706
1699
  /**
@@ -2344,7 +2337,7 @@ var FileFeatureFlagProvider = class extends FeatureFlagProvider {
2344
2337
  };
2345
2338
  let content;
2346
2339
  if (format === "json") {
2347
- content = JSON.stringify(defaultData, null, 2);
2340
+ content = JSON.stringify(defaultData, null, FORMAT_CONSTANTS.JSON_INDENT_SPACES);
2348
2341
  } else {
2349
2342
  content = yaml.stringify(defaultData);
2350
2343
  }
@@ -2452,7 +2445,7 @@ var FileFeatureFlagProvider = class extends FeatureFlagProvider {
2452
2445
  try {
2453
2446
  let content;
2454
2447
  if (format === "json") {
2455
- content = JSON.stringify(fileData, null, 2);
2448
+ content = JSON.stringify(fileData, null, FORMAT_CONSTANTS.JSON_INDENT_SPACES);
2456
2449
  } else {
2457
2450
  content = yaml.stringify(fileData);
2458
2451
  }
@@ -3990,7 +3983,7 @@ function useFeatureFlagProviderStatus() {
3990
3983
  isInitialized: context.isInitialized,
3991
3984
  isLoading: context.isLoading,
3992
3985
  error: context.error,
3993
- lastUpdated: context.lastUpdated
3986
+ lastUpdated: context.lastUpdated ? new Date(context.lastUpdated) : void 0
3994
3987
  };
3995
3988
  }
3996
3989
  __name(useFeatureFlagProviderStatus, "useFeatureFlagProviderStatus");