@naman_deep_singh/js-extensions 1.3.3 → 1.4.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 (38) hide show
  1. package/README.md +174 -425
  2. package/dist/cjs/array/array-extensions.js +84 -50
  3. package/dist/cjs/core/performance.d.ts +1 -0
  4. package/dist/cjs/core/performance.js +6 -0
  5. package/dist/cjs/core/version.d.ts +1 -0
  6. package/dist/cjs/core/version.js +9 -0
  7. package/dist/cjs/index.d.ts +1 -0
  8. package/dist/cjs/index.js +1 -0
  9. package/dist/cjs/number/number-extensions.js +85 -97
  10. package/dist/cjs/object/object-extensions.js +102 -103
  11. package/dist/cjs/string/string-extensions.js +66 -43
  12. package/dist/cjs/types/global-augmentations.d.ts +1 -0
  13. package/dist/cjs/utils/defineExtension.d.ts +1 -0
  14. package/dist/cjs/utils/defineExtension.js +13 -0
  15. package/dist/cjs/utils/index.d.ts +1 -0
  16. package/dist/cjs/utils/index.js +1 -0
  17. package/dist/esm/array/array-extensions.js +84 -50
  18. package/dist/esm/core/performance.d.ts +1 -0
  19. package/dist/esm/core/performance.js +5 -0
  20. package/dist/esm/core/version.d.ts +1 -0
  21. package/dist/esm/core/version.js +5 -0
  22. package/dist/esm/index.d.ts +1 -0
  23. package/dist/esm/index.js +1 -0
  24. package/dist/esm/number/number-extensions.js +86 -98
  25. package/dist/esm/object/object-extensions.js +102 -103
  26. package/dist/esm/string/string-extensions.js +66 -43
  27. package/dist/esm/types/global-augmentations.d.ts +1 -0
  28. package/dist/esm/utils/defineExtension.d.ts +1 -0
  29. package/dist/esm/utils/defineExtension.js +10 -0
  30. package/dist/esm/utils/index.d.ts +1 -0
  31. package/dist/esm/utils/index.js +1 -0
  32. package/dist/types/core/performance.d.ts +1 -0
  33. package/dist/types/core/version.d.ts +1 -0
  34. package/dist/types/index.d.ts +1 -0
  35. package/dist/types/types/global-augmentations.d.ts +1 -0
  36. package/dist/types/utils/defineExtension.d.ts +1 -0
  37. package/dist/types/utils/index.d.ts +1 -0
  38. package/package.json +8 -4
@@ -1,20 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extendArray = extendArray;
4
- // Array prototype extensions
4
+ const utils_1 = require("src/utils");
5
+ let arrayExtended = false;
5
6
  function extendArray() {
6
- Array.prototype.unique = function () {
7
+ if (arrayExtended)
8
+ return;
9
+ arrayExtended = true;
10
+ (0, utils_1.defineExtension)(Array.prototype, 'unique', function () {
7
11
  return [...new Set(this)];
8
- };
9
- Array.prototype.shuffle = function () {
12
+ });
13
+ (0, utils_1.defineExtension)(Array.prototype, 'shuffle', function () {
10
14
  const arr = [...this];
11
15
  for (let i = arr.length - 1; i > 0; i--) {
12
16
  const j = Math.floor(Math.random() * (i + 1));
13
17
  [arr[i], arr[j]] = [arr[j], arr[i]];
14
18
  }
15
19
  return arr;
16
- };
17
- Array.prototype.chunk = function (size) {
20
+ });
21
+ (0, utils_1.defineExtension)(Array.prototype, 'chunk', function (size) {
18
22
  if (!Number.isInteger(size) || size <= 0) {
19
23
  throw new TypeError(`chunk: size must be a positive integer, got ${size}`);
20
24
  }
@@ -23,8 +27,8 @@ function extendArray() {
23
27
  chunks.push(this.slice(i, i + size));
24
28
  }
25
29
  return chunks;
26
- };
27
- Array.prototype.groupBy = function (keyFn) {
30
+ });
31
+ (0, utils_1.defineExtension)(Array.prototype, 'groupBy', function (keyFn) {
28
32
  if (typeof keyFn !== 'function') {
29
33
  throw new TypeError(`groupBy: keyFn must be a function, got ${typeof keyFn}`);
30
34
  }
@@ -35,33 +39,31 @@ function extendArray() {
35
39
  groups[key].push(item);
36
40
  return groups;
37
41
  }, {});
38
- };
39
- Array.prototype.sum = function () {
40
- const numbers = this.filter((item) => typeof item === 'number');
41
- if (numbers.length === 0) {
42
+ });
43
+ (0, utils_1.defineExtension)(Array.prototype, 'sum', function () {
44
+ if (this.length === 0) {
42
45
  throw new TypeError('sum: array must contain at least one number');
43
46
  }
44
- return numbers.reduce((sum, num) => sum + num, 0);
45
- };
46
- Array.prototype.average = function () {
47
- const numbers = this.filter((item) => typeof item === 'number');
48
- if (numbers.length === 0) {
47
+ return this.reduce((sum, num) => sum + num, 0);
48
+ });
49
+ (0, utils_1.defineExtension)(Array.prototype, 'average', function () {
50
+ if (this.length === 0) {
49
51
  throw new TypeError('average: array must contain at least one number');
50
52
  }
51
- return numbers.reduce((sum, num) => sum + num, 0) / numbers.length;
52
- };
53
- Array.prototype.compact = function () {
54
- return this.filter((item) => item != null && item !== '' && item !== false);
55
- };
56
- Array.prototype.pluck = function (key) {
57
- if (typeof key !== 'string' &&
58
- typeof key !== 'number' &&
59
- typeof key !== 'symbol') {
60
- throw new TypeError(`pluck: key must be a string, number, or symbol, got ${typeof key}`);
61
- }
62
- return this.map((item) => item && typeof item === 'object' ? item[key] : undefined).filter((val) => val !== undefined);
63
- };
64
- Array.prototype.findLast = function (predicate) {
53
+ return this.reduce((sum, num) => sum + num, 0) / this.length;
54
+ });
55
+ (0, utils_1.defineExtension)(Array.prototype, 'compact', function () {
56
+ return this.filter((item) => item !== null && item !== undefined && item !== '');
57
+ });
58
+ (0, utils_1.defineExtension)(Array.prototype, 'compactTruthy', function () {
59
+ return this.filter(Boolean);
60
+ });
61
+ (0, utils_1.defineExtension)(Array.prototype, 'pluck', function (key) {
62
+ return this
63
+ .map((item) => item[key])
64
+ .filter((val) => val !== undefined);
65
+ });
66
+ (0, utils_1.defineExtension)(Array.prototype, 'findLast', function (predicate) {
65
67
  if (typeof predicate !== 'function') {
66
68
  throw new TypeError(`findLast: predicate must be a function, got ${typeof predicate}`);
67
69
  }
@@ -70,8 +72,8 @@ function extendArray() {
70
72
  return this[i];
71
73
  }
72
74
  return undefined;
73
- };
74
- Array.prototype.partition = function (predicate) {
75
+ });
76
+ (0, utils_1.defineExtension)(Array.prototype, 'partition', function (predicate) {
75
77
  if (typeof predicate !== 'function') {
76
78
  throw new TypeError(`partition: predicate must be a function, got ${typeof predicate}`);
77
79
  }
@@ -79,42 +81,74 @@ function extendArray() {
79
81
  const falsy = [];
80
82
  this.forEach((item) => predicate(item) ? truthy.push(item) : falsy.push(item));
81
83
  return [truthy, falsy];
82
- };
83
- Array.prototype.flatten = function (depth = 1) {
84
+ });
85
+ (0, utils_1.defineExtension)(Array.prototype, 'flatten', function (depth = 1) {
84
86
  return depth > 0
85
87
  ? this.reduce((acc, val) => acc.concat(Array.isArray(val) ? val.flatten(depth - 1) : val), [])
86
88
  : this.slice();
87
- };
88
- Array.prototype.deepFlatten = function () {
89
+ });
90
+ (0, utils_1.defineExtension)(Array.prototype, 'deepFlatten', function () {
89
91
  return this.reduce((acc, val) => acc.concat(Array.isArray(val) ? val.deepFlatten() : val), []);
90
- };
91
- Array.prototype.difference = function (other) {
92
+ });
93
+ (0, utils_1.defineExtension)(Array.prototype, 'difference', function (other) {
92
94
  if (!Array.isArray(other)) {
93
95
  throw new TypeError(`difference: other must be an array, got ${typeof other}`);
94
96
  }
95
97
  return this.filter((item) => !other.includes(item));
96
- };
97
- Array.prototype.intersection = function (other) {
98
+ });
99
+ (0, utils_1.defineExtension)(Array.prototype, 'intersection', function (other) {
98
100
  if (!Array.isArray(other)) {
99
101
  throw new TypeError(`intersection: other must be an array, got ${typeof other}`);
100
102
  }
101
103
  return this.filter((item) => other.includes(item));
102
- };
103
- Array.prototype.union = function (other) {
104
+ });
105
+ (0, utils_1.defineExtension)(Array.prototype, 'union', function (other) {
104
106
  if (!Array.isArray(other)) {
105
107
  throw new TypeError(`union: other must be an array, got ${typeof other}`);
106
108
  }
107
109
  return [...new Set([...this, ...other])];
108
- };
109
- Array.prototype.sample = function () {
110
+ });
111
+ (0, utils_1.defineExtension)(Array.prototype, 'sample', function () {
110
112
  return this.length > 0
111
113
  ? this[Math.floor(Math.random() * this.length)]
112
114
  : undefined;
113
- };
114
- Array.prototype.take = function (count) {
115
+ });
116
+ (0, utils_1.defineExtension)(Array.prototype, 'take', function (count) {
115
117
  return this.slice(0, Math.max(0, count));
116
- };
117
- Array.prototype.drop = function (count) {
118
+ });
119
+ (0, utils_1.defineExtension)(Array.prototype, 'drop', function (count) {
118
120
  return this.slice(Math.max(0, count));
119
- };
121
+ });
122
+ (0, utils_1.defineExtension)(Array.prototype, 'uniqueBy', function (keyFn) {
123
+ if (typeof keyFn !== 'function') {
124
+ throw new TypeError(`uniqueBy: keyFn must be a function, got ${typeof keyFn}`);
125
+ }
126
+ const seen = new Set();
127
+ const result = [];
128
+ for (const item of this) {
129
+ const key = keyFn(item);
130
+ if (!seen.has(key)) {
131
+ seen.add(key);
132
+ result.push(item);
133
+ }
134
+ }
135
+ return result;
136
+ });
137
+ (0, utils_1.defineExtension)(Array.prototype, 'sortBy', function (keyFn) {
138
+ if (typeof keyFn !== 'function') {
139
+ throw new TypeError(`sortBy: keyFn must be a function, got ${typeof keyFn}`);
140
+ }
141
+ return [...this].sort((a, b) => {
142
+ const aVal = keyFn(a);
143
+ const bVal = keyFn(b);
144
+ if (aVal < bVal)
145
+ return -1;
146
+ if (aVal > bVal)
147
+ return 1;
148
+ return 0;
149
+ });
150
+ });
151
+ (0, utils_1.defineExtension)(Array.prototype, 'last', function () {
152
+ return this.length > 0 ? this[this.length - 1] : undefined;
153
+ });
120
154
  }
@@ -13,4 +13,5 @@ export declare class LRUCache<K, V> {
13
13
  set(key: K, value: V): void;
14
14
  clear(): void;
15
15
  }
16
+ export declare function makeInternalCacheKey(domain: string, key: string | number): string;
16
17
  export declare function withCache<T>(key: string, fn: () => T): T;
@@ -3,7 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LRUCache = void 0;
4
4
  exports.setPerformanceConfig = setPerformanceConfig;
5
5
  exports.getPerformanceConfig = getPerformanceConfig;
6
+ exports.makeInternalCacheKey = makeInternalCacheKey;
6
7
  exports.withCache = withCache;
8
+ const version_1 = require("./version");
7
9
  const defaultConfig = {
8
10
  enableCaching: false,
9
11
  maxCacheSize: 100,
@@ -61,6 +63,10 @@ function getOrCreateCache() {
61
63
  }
62
64
  return cache;
63
65
  }
66
+ function makeInternalCacheKey(domain, key) {
67
+ const INTERNAL_CACHE_PREFIX = '@js-ext' + (0, version_1.getPackageVersion)();
68
+ return `${INTERNAL_CACHE_PREFIX}:${domain}:${key}`;
69
+ }
64
70
  function withCache(key, fn) {
65
71
  if (!config.enableCaching) {
66
72
  return fn();
@@ -0,0 +1 @@
1
+ export declare const getPackageVersion: () => string;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPackageVersion = void 0;
4
+ const node_module_1 = require("node:module");
5
+ const requireFn = (0, node_module_1.createRequire)("../../package.json");
6
+ const getPackageVersion = () => {
7
+ return requireFn('../package.json').version;
8
+ };
9
+ exports.getPackageVersion = getPackageVersion;
@@ -21,6 +21,7 @@ export declare function initializeExtensions(options?: ExtensionOptions): void;
21
21
  */
22
22
  export { extendAll };
23
23
  /**
24
+ * Selective prototype extension helpers
24
25
  * Initialize only specific extensions
25
26
  */
26
27
  export declare const extend: {
package/dist/cjs/index.js CHANGED
@@ -43,6 +43,7 @@ function initializeExtensions(options = {}) {
43
43
  (0, initializer_1.initExtensions)(options);
44
44
  }
45
45
  /**
46
+ * Selective prototype extension helpers
46
47
  * Initialize only specific extensions
47
48
  */
48
49
  exports.extend = {
@@ -1,90 +1,71 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extendNumber = extendNumber;
4
- // Number prototype extensions
4
+ const utils_1 = require("src/utils");
5
5
  const performance_1 = require("../core/performance");
6
+ let numberExtended = false;
6
7
  function extendNumber() {
7
- Number.prototype.toPercent = function (decimals = 2) {
8
- return `${(this.valueOf() * 100).toFixed(decimals)}%`;
9
- };
10
- Number.prototype.toCurrency = function (currency = 'USD', locale = 'en-US') {
11
- return new Intl.NumberFormat(locale, {
12
- style: 'currency',
13
- currency,
14
- }).format(this.valueOf());
15
- };
16
- Number.prototype.clamp = function (min, max) {
17
- if (min > max) {
8
+ if (numberExtended)
9
+ return;
10
+ numberExtended = true;
11
+ (0, utils_1.defineExtension)(Number.prototype, 'toPercent', function (decimals = 2) {
12
+ return `${(this * 100).toFixed(decimals)}%`;
13
+ });
14
+ (0, utils_1.defineExtension)(Number.prototype, 'toCurrency', function (currency = 'USD', locale = 'en-US') {
15
+ return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(this);
16
+ });
17
+ (0, utils_1.defineExtension)(Number.prototype, 'clamp', function (min, max) {
18
+ if (min > max)
18
19
  throw new RangeError(`clamp: min (${min}) cannot be greater than max (${max})`);
19
- }
20
- return Math.min(Math.max(this.valueOf(), min), max);
21
- };
22
- Number.prototype.isEven = function () {
23
- return this.valueOf() % 2 === 0;
24
- };
25
- Number.prototype.isOdd = function () {
26
- return this.valueOf() % 2 !== 0;
27
- };
28
- Number.prototype.isPrime = function () {
29
- const num = this.valueOf();
30
- return (0, performance_1.withCache)(`prime_${num}`, () => {
20
+ return Math.min(Math.max(this, min), max);
21
+ });
22
+ (0, utils_1.defineExtension)(Number.prototype, 'isEven', function () {
23
+ return this % 2 === 0;
24
+ });
25
+ (0, utils_1.defineExtension)(Number.prototype, 'isOdd', function () {
26
+ return this % 2 !== 0;
27
+ });
28
+ (0, utils_1.defineExtension)(Number.prototype, 'isPrime', function () {
29
+ const num = this;
30
+ return (0, performance_1.withCache)((0, performance_1.makeInternalCacheKey)('prime', num), () => {
31
31
  if (num < 2)
32
32
  return false;
33
- for (let i = 2; i <= Math.sqrt(num); i++) {
33
+ for (let i = 2; i <= Math.sqrt(num); i++)
34
34
  if (num % i === 0)
35
35
  return false;
36
- }
37
36
  return true;
38
37
  });
39
- };
40
- Number.prototype.factorial = function () {
41
- const num = Math.floor(this.valueOf());
42
- return (0, performance_1.withCache)(`factorial_${num}`, () => {
38
+ });
39
+ (0, utils_1.defineExtension)(Number.prototype, 'factorial', function () {
40
+ const num = Math.floor(this);
41
+ return (0, performance_1.withCache)((0, performance_1.makeInternalCacheKey)('factorial', num), () => {
43
42
  if (num < 0)
44
- return Number.NaN;
45
- if (num === 0 || num === 1)
43
+ return NaN;
44
+ if (num <= 1)
46
45
  return 1;
47
46
  let result = 1;
48
- for (let i = 2; i <= num; i++) {
47
+ for (let i = 2; i <= num; i++)
49
48
  result *= i;
50
- }
51
49
  return result;
52
50
  });
53
- };
54
- Number.prototype.toOrdinal = function () {
55
- const num = Math.floor(this.valueOf());
51
+ });
52
+ (0, utils_1.defineExtension)(Number.prototype, 'toOrdinal', function () {
53
+ const num = Math.floor(this);
56
54
  const suffix = ['th', 'st', 'nd', 'rd'];
57
55
  const v = num % 100;
58
56
  return num + (suffix[(v - 20) % 10] || suffix[v] || suffix[0]);
59
- };
60
- Number.prototype.toRoman = function () {
61
- const num = Math.floor(this.valueOf());
62
- // Better validation for roman numerals
63
- if (num <= 0) {
57
+ });
58
+ (0, utils_1.defineExtension)(Number.prototype, 'toRoman', function () {
59
+ const num = Math.floor(this);
60
+ if (num <= 0)
64
61
  throw new RangeError('toRoman: number must be positive');
65
- }
66
- if (num >= 4000) {
62
+ if (num >= 4000)
67
63
  throw new RangeError('toRoman: number must be less than 4000');
68
- }
69
- return (0, performance_1.withCache)(`roman_${num}`, () => {
64
+ return (0, performance_1.withCache)((0, performance_1.makeInternalCacheKey)('roman', num), () => {
70
65
  const values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
71
- const symbols = [
72
- 'M',
73
- 'CM',
74
- 'D',
75
- 'CD',
76
- 'C',
77
- 'XC',
78
- 'L',
79
- 'XL',
80
- 'X',
81
- 'IX',
82
- 'V',
83
- 'IV',
84
- 'I',
85
- ];
86
- let result = '';
66
+ const symbols = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
87
67
  let n = num;
68
+ let result = '';
88
69
  for (let i = 0; i < values.length; i++) {
89
70
  while (n >= values[i]) {
90
71
  result += symbols[i];
@@ -93,45 +74,52 @@ function extendNumber() {
93
74
  }
94
75
  return result;
95
76
  });
96
- };
97
- Number.prototype.inRange = function (min, max) {
98
- const num = this.valueOf();
99
- return num >= min && num <= max;
100
- };
101
- Number.prototype.round = function (decimals = 0) {
102
- if (!Number.isInteger(decimals) || decimals < 0) {
103
- throw new TypeError(`round: decimals must be a non-negative integer, got ${decimals}`);
104
- }
77
+ });
78
+ (0, utils_1.defineExtension)(Number.prototype, 'inRange', function (min, max) {
79
+ return this >= min && this <= max;
80
+ });
81
+ (0, utils_1.defineExtension)(Number.prototype, 'round', function (decimals = 0) {
82
+ if (!Number.isInteger(decimals) || decimals < 0)
83
+ throw new TypeError('round: decimals must be non-negative integer');
105
84
  const factor = Math.pow(10, decimals);
106
- return Math.round(this.valueOf() * factor) / factor;
107
- };
108
- Number.prototype.ceil = function (decimals = 0) {
109
- if (!Number.isInteger(decimals) || decimals < 0) {
110
- throw new TypeError(`ceil: decimals must be a non-negative integer, got ${decimals}`);
111
- }
85
+ return Math.round(this * factor) / factor;
86
+ });
87
+ (0, utils_1.defineExtension)(Number.prototype, 'ceil', function (decimals = 0) {
88
+ if (!Number.isInteger(decimals) || decimals < 0)
89
+ throw new TypeError('ceil: decimals must be non-negative integer');
90
+ const factor = Math.pow(10, decimals);
91
+ return Math.ceil(this * factor) / factor;
92
+ });
93
+ (0, utils_1.defineExtension)(Number.prototype, 'floor', function (decimals = 0) {
94
+ if (!Number.isInteger(decimals) || decimals < 0)
95
+ throw new TypeError('floor: decimals must be non-negative integer');
112
96
  const factor = Math.pow(10, decimals);
113
- return Math.ceil(this.valueOf() * factor) / factor;
114
- };
115
- Number.prototype.floor = function (decimals = 0) {
97
+ return Math.floor(this * factor) / factor;
98
+ });
99
+ (0, utils_1.defineExtension)(Number.prototype, 'abs', function () {
100
+ return Math.abs(this);
101
+ });
102
+ (0, utils_1.defineExtension)(Number.prototype, 'sign', function () {
103
+ return Math.sign(this);
104
+ });
105
+ (0, utils_1.defineExtension)(Number.prototype, 'times', function (callback) {
106
+ if (typeof callback !== 'function')
107
+ throw new TypeError('times: callback must be a function');
108
+ for (let i = 0; i < Math.floor(this); i++)
109
+ callback(i);
110
+ });
111
+ (0, utils_1.defineExtension)(Number.prototype, 'toFixedNumber', function (decimals = 0) {
116
112
  if (!Number.isInteger(decimals) || decimals < 0) {
117
- throw new TypeError(`floor: decimals must be a non-negative integer, got ${decimals}`);
113
+ throw new TypeError(`toFixedNumber: decimals must be a non-negative integer, got ${decimals}`);
118
114
  }
119
115
  const factor = Math.pow(10, decimals);
120
- return Math.floor(this.valueOf() * factor) / factor;
121
- };
122
- Number.prototype.abs = function () {
123
- return Math.abs(this.valueOf());
124
- };
125
- Number.prototype.sign = function () {
126
- return Math.sign(this.valueOf());
127
- };
128
- Number.prototype.times = function (callback) {
129
- if (typeof callback !== 'function') {
130
- throw new TypeError(`times: callback must be a function, got ${typeof callback}`);
131
- }
132
- const num = Math.floor(this.valueOf());
133
- for (let i = 0; i < num; i++) {
134
- callback(i);
116
+ return Math.round(this.valueOf() * factor) / factor;
117
+ });
118
+ (0, utils_1.defineExtension)(Number.prototype, 'randomUpTo', function () {
119
+ const max = this.valueOf();
120
+ if (!Number.isFinite(max)) {
121
+ throw new TypeError(`randomUpTo: number must be finite, got ${max}`);
135
122
  }
136
- };
123
+ return Math.random() * max;
124
+ });
137
125
  }