@edgeandnode/eds-utils 1.0.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 (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/dist/bigIntToNumber.d.ts +17 -0
  4. package/dist/bigIntToNumber.d.ts.map +1 -0
  5. package/dist/bigIntToNumber.js +25 -0
  6. package/dist/bigIntToNumber.js.map +1 -0
  7. package/dist/camelToKebab.d.ts +3 -0
  8. package/dist/camelToKebab.d.ts.map +1 -0
  9. package/dist/camelToKebab.js +15 -0
  10. package/dist/camelToKebab.js.map +1 -0
  11. package/dist/constants.d.ts +3 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/constants.js +3 -0
  14. package/dist/constants.js.map +1 -0
  15. package/dist/createIdenticon.d.ts +2 -0
  16. package/dist/createIdenticon.d.ts.map +1 -0
  17. package/dist/createIdenticon.js +75 -0
  18. package/dist/createIdenticon.js.map +1 -0
  19. package/dist/formatAddress.d.ts +14 -0
  20. package/dist/formatAddress.d.ts.map +1 -0
  21. package/dist/formatAddress.js +28 -0
  22. package/dist/formatAddress.js.map +1 -0
  23. package/dist/formatBigInt.d.ts +23 -0
  24. package/dist/formatBigInt.d.ts.map +1 -0
  25. package/dist/formatBigInt.js +38 -0
  26. package/dist/formatBigInt.js.map +1 -0
  27. package/dist/getKey.d.ts +14 -0
  28. package/dist/getKey.d.ts.map +1 -0
  29. package/dist/getKey.js +36 -0
  30. package/dist/getKey.js.map +1 -0
  31. package/dist/index.d.ts +14 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +14 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/loremIpsum.d.ts +11 -0
  36. package/dist/loremIpsum.d.ts.map +1 -0
  37. package/dist/loremIpsum.js +136 -0
  38. package/dist/loremIpsum.js.map +1 -0
  39. package/dist/numberToBigInt.d.ts +18 -0
  40. package/dist/numberToBigInt.d.ts.map +1 -0
  41. package/dist/numberToBigInt.js +27 -0
  42. package/dist/numberToBigInt.js.map +1 -0
  43. package/dist/parseBigInt.d.ts +25 -0
  44. package/dist/parseBigInt.d.ts.map +1 -0
  45. package/dist/parseBigInt.js +35 -0
  46. package/dist/parseBigInt.js.map +1 -0
  47. package/dist/parseNumber.d.ts +17 -0
  48. package/dist/parseNumber.d.ts.map +1 -0
  49. package/dist/parseNumber.js +18 -0
  50. package/dist/parseNumber.js.map +1 -0
  51. package/dist/sliceWrap.d.ts +3 -0
  52. package/dist/sliceWrap.d.ts.map +1 -0
  53. package/dist/sliceWrap.js +11 -0
  54. package/dist/sliceWrap.js.map +1 -0
  55. package/dist/types.d.ts +6 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +2 -0
  58. package/dist/types.js.map +1 -0
  59. package/package.json +37 -0
  60. package/src/bigIntToNumber.ts +34 -0
  61. package/src/camelToKebab.ts +16 -0
  62. package/src/constants.ts +2 -0
  63. package/src/createIdenticon.ts +84 -0
  64. package/src/formatAddress.ts +33 -0
  65. package/src/formatBigInt.ts +60 -0
  66. package/src/getKey.ts +37 -0
  67. package/src/index.ts +13 -0
  68. package/src/loremIpsum.ts +143 -0
  69. package/src/numberToBigInt.ts +38 -0
  70. package/src/parseBigInt.ts +51 -0
  71. package/src/parseNumber.ts +24 -0
  72. package/src/sliceWrap.ts +9 -0
  73. package/src/types.ts +4 -0
@@ -0,0 +1,136 @@
1
+ import { sliceWrap } from './sliceWrap.js';
2
+ /**
3
+ * Generates lorem ipsum text.
4
+ *
5
+ * @param {number} [count=4] - The number of words, sentences, or paragraphs to generate. Default is
6
+ * `4`
7
+ * @param {'words' | 'sentences' | 'paragraphs'} [units='sentences'] - The units to generate.
8
+ * Default is `'sentences'`
9
+ * @returns {string} The generated text.
10
+ */
11
+ export function loremIpsum(count = 4, units = 'sentences') {
12
+ switch (units) {
13
+ case 'words':
14
+ return wordsToSentence(sliceWrap(WORDS, 0, count));
15
+ case 'sentences':
16
+ return sliceWrap(SENTENCES, 0, count)
17
+ .map((sentence) => wordsToSentence(sentence.words))
18
+ .join(' ');
19
+ case 'paragraphs':
20
+ return sliceWrap(PARAGRAPHS, 0, count)
21
+ .map((paragraph) => paragraph.sentences.map((sentence) => wordsToSentence(sentence.words)).join(' '))
22
+ .join('\n');
23
+ }
24
+ }
25
+ function wordsToSentence(words) {
26
+ let sentence = '';
27
+ for (const word of words) {
28
+ if (sentence.length > 0)
29
+ sentence += ' ';
30
+ sentence += word;
31
+ }
32
+ if (sentence.endsWith(',')) {
33
+ sentence = sentence.slice(0, -1);
34
+ }
35
+ if (sentence.length > 0 && !sentence.endsWith('.')) {
36
+ sentence += '.';
37
+ }
38
+ return sentence;
39
+ }
40
+ const LOREM_IPSUM = {
41
+ paragraphs: [
42
+ {
43
+ sentences: [
44
+ {
45
+ words: [
46
+ 'Lorem',
47
+ 'ipsum',
48
+ 'dolor',
49
+ 'sit',
50
+ 'amet,',
51
+ 'consectetur',
52
+ 'adipiscing',
53
+ 'elit,',
54
+ 'sed',
55
+ 'do',
56
+ 'eiusmod',
57
+ 'tempor',
58
+ 'incididunt',
59
+ 'ut',
60
+ 'labore',
61
+ 'et',
62
+ 'dolore',
63
+ 'magna',
64
+ 'aliqua.',
65
+ ],
66
+ },
67
+ {
68
+ words: [
69
+ 'Ut',
70
+ 'enim',
71
+ 'ad',
72
+ 'minim',
73
+ 'veniam,',
74
+ 'quis',
75
+ 'nostrud',
76
+ 'exercitation',
77
+ 'ullamco',
78
+ 'laboris',
79
+ 'nisi',
80
+ 'ut',
81
+ 'aliquip',
82
+ 'ex',
83
+ 'ea',
84
+ 'commodo',
85
+ 'consequat.',
86
+ ],
87
+ },
88
+ {
89
+ words: [
90
+ 'Duis',
91
+ 'aute',
92
+ 'irure',
93
+ 'dolor',
94
+ 'in',
95
+ 'reprehenderit',
96
+ 'in',
97
+ 'voluptate',
98
+ 'velit',
99
+ 'esse',
100
+ 'cillum',
101
+ 'dolore',
102
+ 'eu',
103
+ 'fugiat',
104
+ 'nulla',
105
+ 'pariatur.',
106
+ ],
107
+ },
108
+ {
109
+ words: [
110
+ 'Excepteur',
111
+ 'sint',
112
+ 'occaecat',
113
+ 'cupidatat',
114
+ 'non',
115
+ 'proident,',
116
+ 'sunt',
117
+ 'in',
118
+ 'culpa',
119
+ 'qui',
120
+ 'officia',
121
+ 'deserunt',
122
+ 'mollit',
123
+ 'anim',
124
+ 'id',
125
+ 'est',
126
+ 'laborum.',
127
+ ],
128
+ },
129
+ ],
130
+ },
131
+ ],
132
+ };
133
+ const PARAGRAPHS = LOREM_IPSUM.paragraphs;
134
+ const SENTENCES = PARAGRAPHS.flatMap((paragraph) => paragraph.sentences);
135
+ const WORDS = SENTENCES.flatMap((sentence) => sentence.words);
136
+ //# sourceMappingURL=loremIpsum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loremIpsum.js","sourceRoot":"","sources":["../src/loremIpsum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CACxB,KAAK,GAAW,CAAC,EACjB,KAAK,GAAyC,WAAW;IAEzD,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,eAAe,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;QACpD,KAAK,WAAW;YACd,OAAO,SAAS,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC;iBAClC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;iBAClD,IAAI,CAAC,GAAG,CAAC,CAAA;QACd,KAAK,YAAY;YACf,OAAO,SAAS,CAAC,UAAU,EAAE,CAAC,EAAE,KAAK,CAAC;iBACnC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CACjB,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CACjF;iBACA,IAAI,CAAC,IAAI,CAAC,CAAA;IACjB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAe;IACtC,IAAI,QAAQ,GAAG,EAAE,CAAA;IACjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,QAAQ,IAAI,GAAG,CAAA;QACxC,QAAQ,IAAI,IAAI,CAAA;IAClB,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAClC,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,QAAQ,IAAI,GAAG,CAAA;IACjB,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,WAAW,GAAG;IAClB,UAAU,EAAE;QACV;YACE,SAAS,EAAE;gBACT;oBACE,KAAK,EAAE;wBACL,OAAO;wBACP,OAAO;wBACP,OAAO;wBACP,KAAK;wBACL,OAAO;wBACP,aAAa;wBACb,YAAY;wBACZ,OAAO;wBACP,KAAK;wBACL,IAAI;wBACJ,SAAS;wBACT,QAAQ;wBACR,YAAY;wBACZ,IAAI;wBACJ,QAAQ;wBACR,IAAI;wBACJ,QAAQ;wBACR,OAAO;wBACP,SAAS;qBACV;iBACF;gBACD;oBACE,KAAK,EAAE;wBACL,IAAI;wBACJ,MAAM;wBACN,IAAI;wBACJ,OAAO;wBACP,SAAS;wBACT,MAAM;wBACN,SAAS;wBACT,cAAc;wBACd,SAAS;wBACT,SAAS;wBACT,MAAM;wBACN,IAAI;wBACJ,SAAS;wBACT,IAAI;wBACJ,IAAI;wBACJ,SAAS;wBACT,YAAY;qBACb;iBACF;gBACD;oBACE,KAAK,EAAE;wBACL,MAAM;wBACN,MAAM;wBACN,OAAO;wBACP,OAAO;wBACP,IAAI;wBACJ,eAAe;wBACf,IAAI;wBACJ,WAAW;wBACX,OAAO;wBACP,MAAM;wBACN,QAAQ;wBACR,QAAQ;wBACR,IAAI;wBACJ,QAAQ;wBACR,OAAO;wBACP,WAAW;qBACZ;iBACF;gBACD;oBACE,KAAK,EAAE;wBACL,WAAW;wBACX,MAAM;wBACN,UAAU;wBACV,WAAW;wBACX,KAAK;wBACL,WAAW;wBACX,MAAM;wBACN,IAAI;wBACJ,OAAO;wBACP,KAAK;wBACL,SAAS;wBACT,UAAU;wBACV,QAAQ;wBACR,MAAM;wBACN,IAAI;wBACJ,KAAK;wBACL,UAAU;qBACX;iBACF;aACF;SACF;KACF;CACF,CAAA;AAED,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAA;AACzC,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;AACxE,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA"}
@@ -0,0 +1,18 @@
1
+ export interface NumberToBigIntOptions {
2
+ /**
3
+ * The number of digits starting from the right of the returned bigint to consider as decimal
4
+ * places.
5
+ *
6
+ * @default 18n
7
+ */
8
+ precision?: bigint | undefined;
9
+ }
10
+ /**
11
+ * Converts a number to a bigint. Decimals to the right of `precision` are truncated.
12
+ *
13
+ * @param value - The number to convert to a bigint.
14
+ * @param options - Conversion options.
15
+ * @returns The bigint representation of `value`
16
+ */
17
+ export declare function numberToBigInt(value: number, options?: NumberToBigIntOptions): bigint;
18
+ //# sourceMappingURL=numberToBigInt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numberToBigInt.d.ts","sourceRoot":"","sources":["../src/numberToBigInt.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAkBrF"}
@@ -0,0 +1,27 @@
1
+ import { parseBigInt } from './parseBigInt.js';
2
+ /**
3
+ * Converts a number to a bigint. Decimals to the right of `precision` are truncated.
4
+ *
5
+ * @param value - The number to convert to a bigint.
6
+ * @param options - Conversion options.
7
+ * @returns The bigint representation of `value`
8
+ */
9
+ export function numberToBigInt(value, options) {
10
+ const { precision = 18n } = options ?? {};
11
+ if (precision < 0n) {
12
+ throw new Error(`[numberToBigInt] \`precision\` must be positive, got ${precision}`);
13
+ }
14
+ // If `value` has decimals and `precision` is at least 1, parse it as a string
15
+ if (value % 1 !== 0 && precision >= 1n) {
16
+ const parsedValue = parseBigInt(String(value), { precision });
17
+ if (parsedValue === null) {
18
+ throw new Error(`[numberToBigInt] Failed to parse ${value} as a bigint with precision ${precision}`);
19
+ }
20
+ return parsedValue;
21
+ }
22
+ else {
23
+ const precisionFactor = 10n ** precision;
24
+ return BigInt(Math.trunc(value)) * precisionFactor;
25
+ }
26
+ }
27
+ //# sourceMappingURL=numberToBigInt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numberToBigInt.js","sourceRoot":"","sources":["../src/numberToBigInt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAY9C;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,OAA+B;IAC3E,MAAM,EAAE,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;IACzC,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,wDAAwD,SAAS,EAAE,CAAC,CAAA;IACtF,CAAC;IACD,8EAA8E;IAC9E,IAAI,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAC7D,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,oCAAoC,KAAK,+BAA+B,SAAS,EAAE,CACpF,CAAA;QACH,CAAC;QACD,OAAO,WAAW,CAAA;IACpB,CAAC;SAAM,CAAC;QACN,MAAM,eAAe,GAAG,GAAG,IAAI,SAAS,CAAA;QACxC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,eAAe,CAAA;IACpD,CAAC;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface ParseBigIntOptions {
2
+ /**
3
+ * The number of digits starting from the right of the returned bigint to consider as decimal
4
+ * places.
5
+ *
6
+ * @default 18n
7
+ */
8
+ precision?: bigint | undefined;
9
+ /**
10
+ * If true, requires exact match (no commas, no extra whitespace)
11
+ *
12
+ * @default false
13
+ */
14
+ strict?: boolean | undefined;
15
+ }
16
+ /**
17
+ * Like `parseNumber()`, but returns a bigint instead of a number. Decimals to the right of
18
+ * `precision` are truncated.
19
+ *
20
+ * @param value - The string to parse as a bigint.
21
+ * @param options - Parsing options.
22
+ * @returns The bigint representation of `value`, or `null` if we failed to parse it.
23
+ */
24
+ export declare function parseBigInt(value: string, options?: ParseBigIntOptions): bigint | null;
25
+ //# sourceMappingURL=parseBigInt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseBigInt.d.ts","sourceRoot":"","sources":["../src/parseBigInt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,iBA0BtE"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Like `parseNumber()`, but returns a bigint instead of a number. Decimals to the right of
3
+ * `precision` are truncated.
4
+ *
5
+ * @param value - The string to parse as a bigint.
6
+ * @param options - Parsing options.
7
+ * @returns The bigint representation of `value`, or `null` if we failed to parse it.
8
+ */
9
+ export function parseBigInt(value, options) {
10
+ const { precision = 18n, strict = false } = options ?? {};
11
+ if (precision < 0n) {
12
+ throw new Error(`[parseBigInt] \`precision\` must be positive, got ${precision}`);
13
+ }
14
+ const originalValue = value;
15
+ const cleanedValue = value.replace(/,/g, '').trim();
16
+ if (strict && cleanedValue !== originalValue)
17
+ return null;
18
+ if (cleanedValue === '' || cleanedValue === '-' || cleanedValue === '.' || cleanedValue === '-.')
19
+ return null;
20
+ const [integerPart, decimalPart = '', somethingAfterDecimalPart] = cleanedValue.split('.');
21
+ if (integerPart.trim() !== integerPart)
22
+ return null;
23
+ if (decimalPart.trim() !== decimalPart)
24
+ return null;
25
+ if (somethingAfterDecimalPart !== undefined)
26
+ return null;
27
+ try {
28
+ const precisionNumber = Number(precision);
29
+ return BigInt(`${integerPart}${decimalPart.slice(0, precisionNumber).padEnd(precisionNumber, '0')}`);
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ //# sourceMappingURL=parseBigInt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseBigInt.js","sourceRoot":"","sources":["../src/parseBigInt.ts"],"names":[],"mappings":"AAgBA;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,OAA4B;IACrE,MAAM,EAAE,SAAS,GAAG,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;IACzD,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,qDAAqD,SAAS,EAAE,CAAC,CAAA;IACnF,CAAC;IAED,MAAM,aAAa,GAAG,KAAK,CAAA;IAC3B,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAEnD,IAAI,MAAM,IAAI,YAAY,KAAK,aAAa;QAAE,OAAO,IAAI,CAAA;IACzD,IAAI,YAAY,KAAK,EAAE,IAAI,YAAY,KAAK,GAAG,IAAI,YAAY,KAAK,GAAG,IAAI,YAAY,KAAK,IAAI;QAC9F,OAAO,IAAI,CAAA;IAEb,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,EAAE,EAAE,yBAAyB,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1F,IAAI,WAAY,CAAC,IAAI,EAAE,KAAK,WAAW;QAAE,OAAO,IAAI,CAAA;IACpD,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,WAAW;QAAE,OAAO,IAAI,CAAA;IACnD,IAAI,yBAAyB,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IAExD,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;QACzC,OAAO,MAAM,CACX,GAAG,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,GAAG,CAAC,EAAE,CACtF,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface ParseNumberOptions {
2
+ /**
3
+ * If true, requires exact match (no commas, no extra whitespace)
4
+ *
5
+ * @default false
6
+ */
7
+ strict?: boolean | undefined;
8
+ }
9
+ /**
10
+ * Parses a string value into a number, with optional strict mode.
11
+ *
12
+ * @param value - The string value to parse.
13
+ * @param options - Parsing options.
14
+ * @returns The parsed number, or null if parsing fails.
15
+ */
16
+ export declare function parseNumber(value: string, options?: ParseNumberOptions): number | null;
17
+ //# sourceMappingURL=parseNumber.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseNumber.d.ts","sourceRoot":"","sources":["../src/parseNumber.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,iBAOtE"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Parses a string value into a number, with optional strict mode.
3
+ *
4
+ * @param value - The string value to parse.
5
+ * @param options - Parsing options.
6
+ * @returns The parsed number, or null if parsing fails.
7
+ */
8
+ export function parseNumber(value, options) {
9
+ const { strict = false } = options ?? {};
10
+ const cleanedValue = value.replace(/,/g, '').trim();
11
+ if (cleanedValue === '' || (cleanedValue !== value && strict))
12
+ return null;
13
+ const number = Number(cleanedValue);
14
+ if (!Number.isFinite(number) || (String(number) !== cleanedValue && strict))
15
+ return null;
16
+ return number;
17
+ }
18
+ //# sourceMappingURL=parseNumber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseNumber.js","sourceRoot":"","sources":["../src/parseNumber.ts"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,OAA4B;IACrE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;IACxC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IACnD,IAAI,YAAY,KAAK,EAAE,IAAI,CAAC,YAAY,KAAK,KAAK,IAAI,MAAM,CAAC;QAAE,OAAO,IAAI,CAAA;IAC1E,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,CAAA;IACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,YAAY,IAAI,MAAM,CAAC;QAAE,OAAO,IAAI,CAAA;IACxF,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Same as `array.slice(start, end)`, but wraps around the end of the array. */
2
+ export declare function sliceWrap<T>(array: T[], start: number, end: number): T[];
3
+ //# sourceMappingURL=sliceWrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sliceWrap.d.ts","sourceRoot":"","sources":["../src/sliceWrap.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAOlE"}
@@ -0,0 +1,11 @@
1
+ /** Same as `array.slice(start, end)`, but wraps around the end of the array. */
2
+ export function sliceWrap(array, start, end) {
3
+ if (array.length === 0)
4
+ return [];
5
+ const result = [];
6
+ for (let i = start; i < end; i++) {
7
+ result.push(array[i % array.length]);
8
+ }
9
+ return result;
10
+ }
11
+ //# sourceMappingURL=sliceWrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sliceWrap.js","sourceRoot":"","sources":["../src/sliceWrap.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAI,KAAU,EAAE,KAAa,EAAE,GAAW;IACjE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACjC,MAAM,MAAM,GAAiB,EAAE,CAAA;IAC/B,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAE,CAAC,CAAA;IACvC,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { SetNonNullable, SetRequired } from 'type-fest';
2
+ export type DeepRecord<Value> = {
3
+ [key: string]: Value | DeepRecord<Value>;
4
+ };
5
+ export type SetRequiredNonNullable<T, K extends keyof T> = SetRequired<SetNonNullable<T, K>, K>;
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5D,MAAM,MAAM,UAAU,CAAC,KAAK,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;CAAE,CAAA;AAC5E,MAAM,MAAM,sBAAsB,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@edgeandnode/eds-utils",
3
+ "version": "1.0.0",
4
+ "description": "General utility functions for The Edge Design System",
5
+ "author": "Edge & Node and contributors",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/edgeandnode/eds.git",
10
+ "directory": "packages/utils"
11
+ },
12
+ "homepage": "https://github.com/edgeandnode/eds/tree/main/packages/utils",
13
+ "bugs": "https://github.com/edgeandnode/eds/issues",
14
+ "type": "module",
15
+ "sideEffects": false,
16
+ "exports": {
17
+ ".": "./dist/index.js"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "!dist/**/*.test.*",
22
+ "src",
23
+ "!src/**/*.test.*"
24
+ ],
25
+ "dependencies": {
26
+ "md5": "^2.3.0",
27
+ "viem": "^2.56.8"
28
+ },
29
+ "devDependencies": {
30
+ "@types/md5": "^2.3.6"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc --build tsconfig.build.json",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest"
36
+ }
37
+ }
@@ -0,0 +1,34 @@
1
+ export interface BigIntToNumberOptions {
2
+ /**
3
+ * The number of digits starting from the right of `value` to consider as decimal places.
4
+ *
5
+ * @default 18n
6
+ */
7
+ precision?: bigint | undefined
8
+ }
9
+
10
+ /**
11
+ * Converts a bigint to a number.
12
+ *
13
+ * @param value - The bigint to convert to a number.
14
+ * @param options - Conversion options.
15
+ * @returns The number representation of `value`
16
+ */
17
+ export function bigIntToNumber(value: bigint, options?: BigIntToNumberOptions): number {
18
+ const { precision = 18n } = options ?? {}
19
+ if (precision < 0n) {
20
+ throw new Error(`[bigIntToNumber] \`precision\` must be positive, got ${precision}`)
21
+ }
22
+ if (precision === 0n) {
23
+ return Number(value)
24
+ } else {
25
+ const valueString = String(value)
26
+ const decimalPointIndex = valueString.length - Number(precision)
27
+ if (decimalPointIndex <= 0) {
28
+ return Number(`0.${'0'.repeat(Math.abs(decimalPointIndex))}${valueString}`)
29
+ }
30
+ return Number(
31
+ `${valueString.slice(0, decimalPointIndex)}.${valueString.slice(decimalPointIndex)}`,
32
+ )
33
+ }
34
+ }
@@ -0,0 +1,16 @@
1
+ /** Converts a camelCase string to kebab-case. */
2
+ export function camelToKebab(string: string) {
3
+ return (
4
+ string
5
+ // Insert dash between a group of uppercase letters and an uppercase letter followed by lowercase (`HTTPSEncryptionMethod200Success` => `HTTPS-EncryptionMethod200Success`)
6
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
7
+ // Insert dash between a lowercase letter and an uppercase letter (`HTTPS-EncryptionMethod200Success` => `HTTPS-Encryption-Method200Success`)
8
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
9
+ // Insert dash between a letter and a digit (`HTTPS-Encryption-Method200Success` => `HTTPS-Encryption-Method-200Success`)
10
+ .replace(/([A-Za-z])(\d)/g, '$1-$2')
11
+ // Insert dash between a digit and a letter (`HTTPS-Encryption-Method-200Success` => `HTTPS-Encryption-Method-200-Success`)
12
+ .replace(/(\d)([A-Za-z])/g, '$1-$2')
13
+ // Convert to lowercase (`HTTPS-Encryption-Method-200-Success` => `https-encryption-method-200-success`)
14
+ .toLowerCase()
15
+ )
16
+ }
@@ -0,0 +1,2 @@
1
+ export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
2
+ export const PLACEHOLDER_ADDRESS = '0x646563656E7472616c697a656420646174612121' // "decentralized data!!" in HEX format
@@ -0,0 +1,84 @@
1
+ import md5 from 'md5'
2
+
3
+ import { sliceWrap } from './sliceWrap.ts'
4
+
5
+ const identiconCache = new Map<string, string>()
6
+
7
+ export function createIdenticon(address: string) {
8
+ const lowercasedAddress = address.toLowerCase()
9
+
10
+ // Check the cache first
11
+ const cachedIdenticon = identiconCache.get(lowercasedAddress)
12
+ if (cachedIdenticon) {
13
+ return cachedIdenticon
14
+ }
15
+
16
+ const hash = md5(lowercasedAddress)
17
+ const bytesPerPixel = 3
18
+ const pixels = 5
19
+ const rowPadding = (4 - ((pixels * bytesPerPixel) % 4)) % 4
20
+ const pixelArraySize = pixels * (pixels * bytesPerPixel + rowPadding)
21
+ const fileHeaderSize = 14
22
+ const dibHeaderSize = 40
23
+ const totalHeaderSize = fileHeaderSize + dibHeaderSize
24
+ const bufferSize = totalHeaderSize + pixelArraySize
25
+ const buffer = new Uint8Array(bufferSize)
26
+
27
+ // Set up the bitmap headers
28
+ buffer[0] = 0x42 // 'B'
29
+ buffer[1] = 0x4d // 'M'
30
+ buffer[2] = bufferSize & 0xff
31
+ buffer[3] = (bufferSize >> 8) & 0xff
32
+ buffer[4] = (bufferSize >> 16) & 0xff
33
+ buffer[5] = (bufferSize >> 24) & 0xff
34
+ buffer[10] = totalHeaderSize // Pixel data offset
35
+ buffer[14] = dibHeaderSize
36
+ buffer[18] = pixels & 0xff
37
+ buffer[19] = (pixels >> 8) & 0xff
38
+ buffer[22] = pixels & 0xff
39
+ buffer[23] = (pixels >> 8) & 0xff
40
+ buffer[26] = 1 // Planes
41
+ buffer[28] = 24 // Bits per pixel
42
+
43
+ // Determine the primary color based on the hash
44
+ const match = /#(..)(..)(..)/.exec(`#${hash.slice(0, 6)}`)
45
+ if (!match) throw new Error('[createIdenticon] Invalid color format')
46
+ const [r, g, b] = match.slice(1).map((hex) => parseInt(hex, 16)) as [number, number, number]
47
+ type BGR = [number, number, number]
48
+ const primaryColor: BGR = [b, g, r]
49
+ const backgroundColor: BGR = [255, 255, 255]
50
+
51
+ // Draw the image
52
+ const hashBinary = hash
53
+ .split('')
54
+ .map((el) => parseInt(el, 16))
55
+ .map((num) => (num < 8 ? 0 : 1))
56
+ const hashBinaryMap: (0 | 1)[][] = []
57
+ const columns = Math.ceil(pixels / 2)
58
+ for (let x = 0; x < columns; x++) {
59
+ hashBinaryMap[x] = sliceWrap(hashBinary, x * pixels, (x + 1) * pixels)
60
+ }
61
+ let position = totalHeaderSize
62
+ for (let y = pixels - 1; y >= 0; y--) {
63
+ for (let x = 0; x < pixels; x++) {
64
+ const color: BGR = hashBinaryMap[x > columns - 1 ? pixels - 1 - x : x]?.[y]
65
+ ? primaryColor
66
+ : backgroundColor
67
+ buffer[position++] = color[0]
68
+ buffer[position++] = color[1]
69
+ buffer[position++] = color[2]
70
+ }
71
+ position += rowPadding
72
+ }
73
+
74
+ // Convert the image to a base64 string
75
+ let binary = ''
76
+ for (let i = 0; i < buffer.length; i++) {
77
+ binary += String.fromCharCode(buffer[i]!)
78
+ }
79
+ const identicon = `data:image/bmp;base64,${btoa(binary)}`
80
+
81
+ // Store it in the cache, then return it
82
+ identiconCache.set(lowercasedAddress, identicon)
83
+ return identicon
84
+ }
@@ -0,0 +1,33 @@
1
+ import { getAddress } from 'viem'
2
+
3
+ import { ZERO_ADDRESS } from './constants.ts'
4
+
5
+ type FormatAddressOptions = {
6
+ /** @default 'short' */
7
+ style?: 'short' | 'full' | undefined
8
+ }
9
+
10
+ /**
11
+ * Formats an EVM wallet address as a string.
12
+ *
13
+ * @param address - The address to format.
14
+ * @param options - Formatting options.
15
+ * @returns The formatted address string.
16
+ */
17
+ export function formatAddress(address: string, options: FormatAddressOptions = {}): string {
18
+ const { style = 'short' } = options
19
+
20
+ if (!address) address = ZERO_ADDRESS
21
+ try {
22
+ address = address.startsWith('0x') ? getAddress(address) : address
23
+ } catch {}
24
+
25
+ switch (style) {
26
+ case 'short':
27
+ const lengthOnEachSide = 6
28
+ if (address.length <= lengthOnEachSide * 2 + 1) return address
29
+ return `${address.slice(0, lengthOnEachSide)}–${address.slice(-lengthOnEachSide)}`
30
+ case 'full':
31
+ return address
32
+ }
33
+ }
@@ -0,0 +1,60 @@
1
+ export interface BigIntFormatOptions {
2
+ /**
3
+ * The number of digits starting from the right of `value` to consider as decimal places.
4
+ *
5
+ * @default 18n
6
+ */
7
+ precision?: bigint | undefined
8
+ /** @default 0 */
9
+ minimumFractionDigits?: number | undefined
10
+ /** @default 20 */
11
+ maximumFractionDigits?: number | undefined
12
+ /** @default 'auto' */
13
+ trailingZeroDisplay?: 'auto' | 'stripIfInteger' | undefined
14
+ }
15
+
16
+ /**
17
+ * Formats a bigint as a string.
18
+ *
19
+ * @param value - The bigint to format.
20
+ * @param options - Formatting options.
21
+ * @returns The string representation of `value`
22
+ */
23
+ export function formatBigInt(value: bigint, options?: BigIntFormatOptions): string {
24
+ const {
25
+ precision = 18n,
26
+ minimumFractionDigits = 0,
27
+ maximumFractionDigits = 20,
28
+ trailingZeroDisplay = 'auto',
29
+ } = options ?? {}
30
+
31
+ if (precision < 0n) {
32
+ throw new Error(`[formatBigInt] \`precision\` must be positive, got ${precision}`)
33
+ }
34
+ if (minimumFractionDigits > maximumFractionDigits) {
35
+ throw new Error(
36
+ `[formatBigInt] \`minimumFractionDigits\` (${minimumFractionDigits}) cannot be greater than \`maximumFractionDigits\` (${maximumFractionDigits})`,
37
+ )
38
+ }
39
+ const isNegative = value < 0n
40
+ const absValue = isNegative ? value * -1n : value
41
+ const precisionFactor = 10n ** precision
42
+ const integerPart = absValue / precisionFactor
43
+ const integerPartString = `${isNegative ? '-' : ''}${integerPart.toLocaleString('en-US')}`
44
+ const decimalPart = absValue % precisionFactor
45
+ let decimalPartString = ''
46
+ if ((decimalPart > 0n || minimumFractionDigits > 0) && maximumFractionDigits > 0) {
47
+ decimalPartString = decimalPart
48
+ .toLocaleString('en-US', {
49
+ useGrouping: false,
50
+ })
51
+ .padStart(Number(precision), '0')
52
+ .replace(/0+$/, '')
53
+ .padEnd(minimumFractionDigits, '0')
54
+ .slice(0, maximumFractionDigits)
55
+ if (trailingZeroDisplay === 'stripIfInteger' && decimalPartString.replace(/0/g, '') === '') {
56
+ decimalPartString = ''
57
+ }
58
+ }
59
+ return `${integerPartString}${decimalPartString ? `.${decimalPartString}` : ''}`
60
+ }