@hkdigital/lib-sveltekit 0.1.58 → 0.1.60
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/constants/bases.d.ts +10 -0
- package/dist/constants/bases.js +13 -0
- package/dist/constants/time.d.ts +1 -2
- package/dist/constants/time.js +2 -2
- package/dist/util/bases/base58.d.ts +58 -0
- package/dist/util/bases/base58.js +262 -0
- package/dist/util/bases/index.d.ts +1 -0
- package/dist/util/bases/index.js +1 -0
- package/dist/util/time/index.d.ts +34 -46
- package/dist/util/time/index.js +59 -75
- package/dist/util/unique/index.d.ts +81 -0
- package/dist/util/unique/index.js +249 -0
- package/package.json +1 -1
@@ -0,0 +1,10 @@
|
|
1
|
+
/**
|
2
|
+
* Characters selected for their visually distinct shapes to improve
|
3
|
+
* human readability and reduce confusion.
|
4
|
+
*/
|
5
|
+
export const ALPHABET_BASE_HUMAN: "3456789abcdefghjkmnpqrstuvwxy";
|
6
|
+
/**
|
7
|
+
* Base58 character set: alphanumeric characters excluding similar-looking
|
8
|
+
* ones (0, O, I, l) to prevent visual ambiguity.
|
9
|
+
*/
|
10
|
+
export const ALPHABET_BASE_58: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
/**
|
3
|
+
* Characters selected for their visually distinct shapes to improve
|
4
|
+
* human readability and reduce confusion.
|
5
|
+
*/
|
6
|
+
export const ALPHABET_BASE_HUMAN = '3456789abcdefghjkmnpqrstuvwxy';
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Base58 character set: alphanumeric characters excluding similar-looking
|
10
|
+
* ones (0, O, I, l) to prevent visual ambiguity.
|
11
|
+
*/
|
12
|
+
export const ALPHABET_BASE_58 =
|
13
|
+
'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
package/dist/constants/time.d.ts
CHANGED
package/dist/constants/time.js
CHANGED
@@ -24,5 +24,5 @@ export const INTERVALS_MS = {
|
|
24
24
|
|
25
25
|
// > Offsets
|
26
26
|
|
27
|
-
export const
|
28
|
-
export const TIME_2100_01_01 = 4102444800000; // 2100-01-01T00:00:00.000Z
|
27
|
+
export const TIME_2025_01_01 = 1577836800000; // 2020-01-01T00:00:00.000Z
|
28
|
+
// export const TIME_2100_01_01 = 4102444800000; // 2100-01-01T00:00:00.000Z
|
@@ -0,0 +1,58 @@
|
|
1
|
+
/**
|
2
|
+
* Convert a number to a base 58 encoded string
|
3
|
+
*
|
4
|
+
* @param {number|BigInt} num - Number to encode
|
5
|
+
*
|
6
|
+
* @returns {string} string encoded using base 58
|
7
|
+
*/
|
8
|
+
export function base58fromNumber(num: number | bigint): string;
|
9
|
+
/**
|
10
|
+
* Returns true if the specified string only contains base 58 characters
|
11
|
+
*
|
12
|
+
* @param {string} str [description]
|
13
|
+
*
|
14
|
+
* @returns {boolean} true if the string only contains base 58 characters
|
15
|
+
*/
|
16
|
+
export function isBase58(str: string): boolean;
|
17
|
+
/**
|
18
|
+
* Convert a string encoded as base 58 to a number (BigInt)
|
19
|
+
*
|
20
|
+
* @param {string} str - String to decode
|
21
|
+
*
|
22
|
+
* @param {number} [exceptionValue]
|
23
|
+
* If specified, the exceptionValue will be returned instead of
|
24
|
+
* throwing an exception
|
25
|
+
*
|
26
|
+
* @returns {number} decoded decimal numerical representation
|
27
|
+
*/
|
28
|
+
export function base58toNumber(str: string, exceptionValue?: number, ...args: any[]): number;
|
29
|
+
/**
|
30
|
+
* Convert a base58 encoded string to an Uint8Array (bytes)
|
31
|
+
* - A base58 encoded string actually represents a (potentially very big)
|
32
|
+
* number. This method converts that number into a bytes representation
|
33
|
+
* - A byte can hold 256 values, a base58 character only 58, so there will be
|
34
|
+
* less bytes needed to encode the value of the base58 encoded string
|
35
|
+
*
|
36
|
+
* @param {string} str - String to convert
|
37
|
+
*
|
38
|
+
* @returns {Uint8Array} bytes that represent the base58 encoded string value
|
39
|
+
*/
|
40
|
+
export function base58toBytes(str: string): Uint8Array;
|
41
|
+
/**
|
42
|
+
* Convert a base58 encoded string to a (base256) byte string
|
43
|
+
*
|
44
|
+
* @param {string} str
|
45
|
+
*
|
46
|
+
* @returns {string} byte string
|
47
|
+
*/
|
48
|
+
export function base58toByteString(str: string): string;
|
49
|
+
/**
|
50
|
+
* Convert bytes to number
|
51
|
+
*
|
52
|
+
* @param {Uint8Array} bytes
|
53
|
+
*
|
54
|
+
* @returns {BigInt} numeric value
|
55
|
+
*/
|
56
|
+
export function bytesToNumber(bytes: Uint8Array): bigint;
|
57
|
+
export const ALPHABET_BASE_58: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
58
|
+
export const ALPHABET_BASE_58_MAP: Map<string, number>;
|
@@ -0,0 +1,262 @@
|
|
1
|
+
/**
|
2
|
+
* base-58.js
|
3
|
+
*
|
4
|
+
* @description
|
5
|
+
* This file contains code for working with base 58 encoding
|
6
|
+
*
|
7
|
+
* @example
|
8
|
+
*
|
9
|
+
* import { base58fromNumber } from "./base-58.js";
|
10
|
+
*
|
11
|
+
* console.log( base58fromNumber( 1234513245 ) ) // base 58 encoded string
|
12
|
+
*/
|
13
|
+
|
14
|
+
/* ------------------------------------------------------------------ Imports */
|
15
|
+
|
16
|
+
import * as expect from '../expect';
|
17
|
+
|
18
|
+
/* ------------------------------------------------------------------ Exports */
|
19
|
+
|
20
|
+
// Base 58 helper functions
|
21
|
+
//
|
22
|
+
// Inspired by
|
23
|
+
// https://github.com/jimeh/node-base58/blob/master/src/base58.js
|
24
|
+
//
|
25
|
+
// @note
|
26
|
+
// Two different commonly used alphabets exist
|
27
|
+
//
|
28
|
+
// Bitcoin, IPFS (respects default sort order):
|
29
|
+
// 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
|
30
|
+
//
|
31
|
+
// Short URLs for Flickr
|
32
|
+
// 123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ
|
33
|
+
//
|
34
|
+
// @see https://en.wikipedia.org/wiki/StdBase58Helper
|
35
|
+
//
|
36
|
+
|
37
|
+
export const ALPHABET_BASE_58 =
|
38
|
+
'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
39
|
+
|
40
|
+
//export
|
41
|
+
const BASE_SIZE = BigInt(ALPHABET_BASE_58.length);
|
42
|
+
|
43
|
+
// Create a lookup table to fetch character index
|
44
|
+
|
45
|
+
export const ALPHABET_BASE_58_MAP =
|
46
|
+
new Map( [...ALPHABET_BASE_58].map( ( char, index ) => [ char, index ] ) );
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Convert a number to a base 58 encoded string
|
50
|
+
*
|
51
|
+
* @param {number|BigInt} num - Number to encode
|
52
|
+
*
|
53
|
+
* @returns {string} string encoded using base 58
|
54
|
+
*/
|
55
|
+
export function base58fromNumber( num )
|
56
|
+
{
|
57
|
+
let str = '';
|
58
|
+
|
59
|
+
if( typeof num !== 'bigint' )
|
60
|
+
{
|
61
|
+
if( Number.isNaN( num ) ||
|
62
|
+
num < 0 ||
|
63
|
+
num > Number.MAX_SAFE_INTEGER ||
|
64
|
+
Math.floor( num ) !== num )
|
65
|
+
{
|
66
|
+
throw new Error(
|
67
|
+
'Invalid parameter [num], expected not negative safe integer');
|
68
|
+
}
|
69
|
+
|
70
|
+
num = BigInt(num);
|
71
|
+
}
|
72
|
+
|
73
|
+
while( num >= BASE_SIZE )
|
74
|
+
{
|
75
|
+
const mod = Number(num % BASE_SIZE);
|
76
|
+
|
77
|
+
str = ALPHABET_BASE_58[ mod ] + str;
|
78
|
+
|
79
|
+
// num = Math.floor( num / BASE_SIZE );
|
80
|
+
//
|
81
|
+
num = num / BASE_SIZE; // BigInts are integers, automatically rounded down
|
82
|
+
}
|
83
|
+
|
84
|
+
return ALPHABET_BASE_58[ Number(num) ] + str;
|
85
|
+
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Returns true if the specified string only contains base 58 characters
|
89
|
+
*
|
90
|
+
* @param {string} str [description]
|
91
|
+
*
|
92
|
+
* @returns {boolean} true if the string only contains base 58 characters
|
93
|
+
*/
|
94
|
+
export function isBase58( str )
|
95
|
+
{
|
96
|
+
expect.string( str );
|
97
|
+
|
98
|
+
for( let j = 0, n = str.length; j < n; j = j + 1 )
|
99
|
+
{
|
100
|
+
const char = str.charAt(j);
|
101
|
+
if( !ALPHABET_BASE_58_MAP.has( char ) )
|
102
|
+
{
|
103
|
+
return false;
|
104
|
+
}
|
105
|
+
} // end for
|
106
|
+
|
107
|
+
return true;
|
108
|
+
}
|
109
|
+
|
110
|
+
// -----------------------------------------------------------------------------
|
111
|
+
|
112
|
+
/**
|
113
|
+
* Convert a string encoded as base 58 to a number (BigInt)
|
114
|
+
*
|
115
|
+
* @param {string} str - String to decode
|
116
|
+
*
|
117
|
+
* @param {number} [exceptionValue]
|
118
|
+
* If specified, the exceptionValue will be returned instead of
|
119
|
+
* throwing an exception
|
120
|
+
*
|
121
|
+
* @returns {number} decoded decimal numerical representation
|
122
|
+
*/
|
123
|
+
export function base58toNumber( str, exceptionValue )
|
124
|
+
{
|
125
|
+
expect.string( str, 'Missing or invalid parameter [str]' );
|
126
|
+
|
127
|
+
let num = BigInt(0);
|
128
|
+
|
129
|
+
const n = str.length;
|
130
|
+
const n_1 = n - 1;
|
131
|
+
|
132
|
+
for( let j = 0; j < n; j = j + 1 )
|
133
|
+
{
|
134
|
+
const char = str.charAt(j);
|
135
|
+
const value = ALPHABET_BASE_58_MAP.get( char );
|
136
|
+
|
137
|
+
if( value === undefined )
|
138
|
+
{
|
139
|
+
if( 1 === arguments.length )
|
140
|
+
{
|
141
|
+
throw new Error(
|
142
|
+
`Invalid character [${char}] found in string (expected base58`);
|
143
|
+
}
|
144
|
+
else {
|
145
|
+
return exceptionValue;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
num = num + BigInt(value) * BigInt(58) ** BigInt( n_1 - j );
|
150
|
+
|
151
|
+
// console.log("num", num );
|
152
|
+
|
153
|
+
} // end for
|
154
|
+
|
155
|
+
return num;
|
156
|
+
}
|
157
|
+
|
158
|
+
// -----------------------------------------------------------------------------
|
159
|
+
|
160
|
+
/**
|
161
|
+
* Convert a base58 encoded string to an Uint8Array (bytes)
|
162
|
+
* - A base58 encoded string actually represents a (potentially very big)
|
163
|
+
* number. This method converts that number into a bytes representation
|
164
|
+
* - A byte can hold 256 values, a base58 character only 58, so there will be
|
165
|
+
* less bytes needed to encode the value of the base58 encoded string
|
166
|
+
*
|
167
|
+
* @param {string} str - String to convert
|
168
|
+
*
|
169
|
+
* @returns {Uint8Array} bytes that represent the base58 encoded string value
|
170
|
+
*/
|
171
|
+
export function base58toBytes( str )
|
172
|
+
{
|
173
|
+
const num = base58toNumber( str );
|
174
|
+
|
175
|
+
let numBase16 = num.toString(16);
|
176
|
+
|
177
|
+
if( 1 === numBase16.length % 2 )
|
178
|
+
{
|
179
|
+
//
|
180
|
+
// String contains inpair number of characters -> prefix a "0"
|
181
|
+
//
|
182
|
+
numBase16 = '0' + numBase16;
|
183
|
+
}
|
184
|
+
|
185
|
+
const n = numBase16.length;
|
186
|
+
|
187
|
+
const out = new Uint8Array( numBase16.length >> 1 );
|
188
|
+
|
189
|
+
for( let j = n - 1; j > 0; j = j - 2 )
|
190
|
+
{
|
191
|
+
const low16 = parseInt( numBase16[ j ], 16 );
|
192
|
+
const high16 = parseInt( numBase16[ j - 1 ], 16 );
|
193
|
+
|
194
|
+
// // const low16 = (j < n_1) ? parseInt(numBase16[ j + 1 ], 10) : 0;
|
195
|
+
|
196
|
+
// const low16 = (j < n_1) ? parseInt( numBase16[ j + 1 ], 16 ) : 0;
|
197
|
+
|
198
|
+
const value256 = (high16 << 4) + low16;
|
199
|
+
|
200
|
+
out[ j >> 1 ] = value256;
|
201
|
+
|
202
|
+
// console.log(
|
203
|
+
// {
|
204
|
+
// numBase16,
|
205
|
+
// n,
|
206
|
+
// j,
|
207
|
+
// high16,
|
208
|
+
// low16,
|
209
|
+
// value256,
|
210
|
+
// out
|
211
|
+
// } );
|
212
|
+
|
213
|
+
} // end for
|
214
|
+
|
215
|
+
return out;
|
216
|
+
}
|
217
|
+
|
218
|
+
// -----------------------------------------------------------------------------
|
219
|
+
|
220
|
+
/**
|
221
|
+
* Convert a base58 encoded string to a (base256) byte string
|
222
|
+
*
|
223
|
+
* @param {string} str
|
224
|
+
*
|
225
|
+
* @returns {string} byte string
|
226
|
+
*/
|
227
|
+
export function base58toByteString( str )
|
228
|
+
{
|
229
|
+
return new TextDecoder().decode( base58toBytes( str ) );
|
230
|
+
}
|
231
|
+
|
232
|
+
// -----------------------------------------------------------------------------
|
233
|
+
|
234
|
+
/**
|
235
|
+
* Convert bytes to number
|
236
|
+
*
|
237
|
+
* @param {Uint8Array} bytes
|
238
|
+
*
|
239
|
+
* @returns {BigInt} numeric value
|
240
|
+
*/
|
241
|
+
export function bytesToNumber( bytes )
|
242
|
+
{
|
243
|
+
let sum = BigInt(0);
|
244
|
+
|
245
|
+
// console.log( "check", bytes.length );
|
246
|
+
|
247
|
+
for( let j = 0, n = bytes.length; j < n; j = j + 1 )
|
248
|
+
{
|
249
|
+
const base = BigInt(256) ** BigInt( n - 1 - j );
|
250
|
+
const value = bytes[ j ];
|
251
|
+
|
252
|
+
// console.log(
|
253
|
+
// {
|
254
|
+
// base,
|
255
|
+
// value
|
256
|
+
// } );
|
257
|
+
|
258
|
+
sum = sum + base * BigInt( value );
|
259
|
+
}
|
260
|
+
|
261
|
+
return sum;
|
262
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from "./base58.js";
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './base58.js';
|
@@ -10,14 +10,14 @@
|
|
10
10
|
* resolves. If this parameter is set, the delay will be chosen randomly
|
11
11
|
* between the values [delayOrMinDelayMs, maxDelayMs]
|
12
12
|
*
|
13
|
-
* @returns {
|
13
|
+
* @returns {HkPromise} promise that resolves after a specified timeout
|
14
14
|
*/
|
15
|
-
export function delay(delayOrMinDelayMs: number, maxDelayMs?: number):
|
15
|
+
export function delay(delayOrMinDelayMs: number, maxDelayMs?: number): HkPromise;
|
16
16
|
/**
|
17
17
|
* Get the number of milliseconds since the specified time stamp of the default
|
18
|
-
* reference time stamp
|
18
|
+
* reference time stamp TIME_2025_01_01
|
19
19
|
*
|
20
|
-
* @param {number} [sinceMs=
|
20
|
+
* @param {number} [sinceMs=TIME_2025_01_01]
|
21
21
|
*
|
22
22
|
* @returns {number} number of milliseconds since the specified time
|
23
23
|
*/
|
@@ -53,68 +53,56 @@ export function toDate(dateOrTimestamp: Date | number): Date;
|
|
53
53
|
export function getWeekNumber(dateOrTimestamp: Date | number): number;
|
54
54
|
/**
|
55
55
|
* Get the name of the month
|
56
|
-
* - Returns the
|
56
|
+
* - Returns the month name using Intl.DateTimeFormat
|
57
|
+
* - By default uses English locale, but locale can be specified
|
57
58
|
*
|
58
|
-
*
|
59
|
-
*
|
59
|
+
* @param {Date|number} dateOrTimestamp - Date object or timestamp
|
60
|
+
* @param {string} [locale='nl-NL'] - The locale to use for the month name
|
60
61
|
*
|
61
|
-
*
|
62
|
+
* @param {Object} [options]
|
63
|
+
* @param {'numeric'|'2-digit'|'narrow'|'short'|'long'} [options.month='long']
|
64
|
+
* @param {string} [options.timeZone] - Optional timezone
|
62
65
|
*
|
63
|
-
*
|
64
|
-
* ...
|
65
|
-
*
|
66
|
-
* text( getMonthName( new Date() ) );
|
67
|
-
*
|
68
|
-
* --
|
69
|
-
*
|
70
|
-
* @param {Date|number} dateOrTimestamp
|
71
|
-
*
|
72
|
-
* @returns {string} name of the month (English)
|
66
|
+
* @returns {string} name of the month in the specified locale
|
73
67
|
*/
|
74
|
-
export function getMonthName(dateOrTimestamp: Date | number
|
68
|
+
export function getMonthName(dateOrTimestamp: Date | number, locale?: string, options?: {
|
69
|
+
month?: "numeric" | "2-digit" | "narrow" | "short" | "long";
|
70
|
+
timeZone?: string;
|
71
|
+
}): string;
|
75
72
|
/**
|
76
|
-
* Get the name of the day
|
77
|
-
* - Returns the
|
78
|
-
*
|
79
|
-
* - Use the output as label in combination with the functions
|
80
|
-
* text() and translate() for international day names
|
73
|
+
* Get the name of the day of the week
|
74
|
+
* - Returns the day name using Intl.DateTimeFormat
|
75
|
+
* - By default uses English locale, but locale can be specified
|
81
76
|
*
|
82
|
-
*
|
77
|
+
* @param {Date|number} dateOrTimestamp - Date object or timestamp
|
78
|
+
* @param {string} [locale='nl-NL'] - The locale to use for the day name
|
83
79
|
*
|
84
|
-
*
|
85
|
-
*
|
80
|
+
* @param {Object} [options]
|
81
|
+
* @param {'narrow'|'short'|'long'} [options.weekday='long']
|
82
|
+
* @param {string} [options.timeZone] - Optional timezone
|
86
83
|
*
|
87
|
-
*
|
88
|
-
*
|
89
|
-
* --
|
90
|
-
*
|
91
|
-
* @param {Date|number} dateOrTimestamp
|
92
|
-
*
|
93
|
-
* @returns {string} name of the day (English)
|
84
|
+
* @returns {string} name of the day in the specified locale
|
94
85
|
*/
|
95
|
-
export function getDayName(dateOrTimestamp: Date | number
|
86
|
+
export function getDayName(dateOrTimestamp: Date | number, locale?: string, options?: {
|
87
|
+
weekday?: "narrow" | "short" | "long";
|
88
|
+
timeZone?: string;
|
89
|
+
}): string;
|
96
90
|
/**
|
97
91
|
* Return the timestamp of the start of the day
|
98
92
|
* - Midnight
|
99
93
|
*
|
100
|
-
* @param {Date|number} dateOrTimestamp
|
94
|
+
* @param {Date|number} [dateOrTimestamp]
|
101
95
|
*
|
102
96
|
* @returns {number} timestamp of start of the day (00:00:00:0000)
|
103
97
|
*/
|
104
|
-
export function getTimeAtStartOfDay(dateOrTimestamp
|
98
|
+
export function getTimeAtStartOfDay(dateOrTimestamp?: Date | number): number;
|
105
99
|
/**
|
106
100
|
* Return the timestamp of the end of the day
|
107
101
|
* - Midnight - 1 millisecond
|
108
102
|
*
|
109
|
-
* @param {Date|number} dateOrTimestamp
|
103
|
+
* @param {Date|number} [dateOrTimestamp]
|
110
104
|
*
|
111
105
|
* @returns {number} timestamp of start of the day
|
112
106
|
*/
|
113
|
-
export function getTimeAtEndOfDay(dateOrTimestamp
|
114
|
-
|
115
|
-
export const MINUTE_MS: number;
|
116
|
-
export const HOUR_MS: number;
|
117
|
-
export const DAY_MS: number;
|
118
|
-
export const WEEK_MS: number;
|
119
|
-
export const TIME_2020_01_01: 1577836800000;
|
120
|
-
export const TIME_2100_01_01: 4102444800000;
|
107
|
+
export function getTimeAtEndOfDay(dateOrTimestamp?: Date | number): number;
|
108
|
+
import { HkPromise } from '../../classes/promise/index.js';
|
package/dist/util/time/index.js
CHANGED
@@ -28,24 +28,16 @@
|
|
28
28
|
* }).format(d);
|
29
29
|
*/
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
import {
|
32
|
+
SECOND_MS,
|
33
|
+
MINUTE_MS,
|
34
|
+
HOUR_MS,
|
35
|
+
DAY_MS,
|
36
|
+
TIME_2025_01_01 } from '../../constants/time.js';
|
37
|
+
|
38
|
+
import * as expect from '../expect';
|
34
39
|
import { HkPromise } from '../../classes/promise/index.js';
|
35
40
|
|
36
|
-
/* ---------------------------------------------------------------- Internals */
|
37
|
-
|
38
|
-
/* ------------------------------------------------------------------ Exports */
|
39
|
-
|
40
|
-
export const SECOND_MS = 1000;
|
41
|
-
export const MINUTE_MS = 60 * SECOND_MS;
|
42
|
-
export const HOUR_MS = 60 * MINUTE_MS;
|
43
|
-
export const DAY_MS = 24 * HOUR_MS;
|
44
|
-
export const WEEK_MS = 7 * DAY_MS;
|
45
|
-
|
46
|
-
export const TIME_2020_01_01 = 1577836800000; // 2020-01-01T00:00:00.000Z
|
47
|
-
export const TIME_2100_01_01 = 4102444800000; // 2100-01-01T00:00:00.000Z
|
48
|
-
|
49
41
|
/**
|
50
42
|
* Returns a promise that resolves after a specified timeout
|
51
43
|
* - If the returned promise is rejected, the timeout is cancelled
|
@@ -58,7 +50,7 @@ export const TIME_2100_01_01 = 4102444800000; // 2100-01-01T00:00:00.000Z
|
|
58
50
|
* resolves. If this parameter is set, the delay will be chosen randomly
|
59
51
|
* between the values [delayOrMinDelayMs, maxDelayMs]
|
60
52
|
*
|
61
|
-
* @returns {
|
53
|
+
* @returns {HkPromise} promise that resolves after a specified timeout
|
62
54
|
*/
|
63
55
|
export function delay(delayOrMinDelayMs, maxDelayMs) {
|
64
56
|
expect.number(delayOrMinDelayMs);
|
@@ -92,22 +84,18 @@ export function delay(delayOrMinDelayMs, maxDelayMs) {
|
|
92
84
|
return promise;
|
93
85
|
}
|
94
86
|
|
95
|
-
// -----------------------------------------------------------------------------
|
96
|
-
|
97
87
|
/**
|
98
88
|
* Get the number of milliseconds since the specified time stamp of the default
|
99
|
-
* reference time stamp
|
89
|
+
* reference time stamp TIME_2025_01_01
|
100
90
|
*
|
101
|
-
* @param {number} [sinceMs=
|
91
|
+
* @param {number} [sinceMs=TIME_2025_01_01]
|
102
92
|
*
|
103
93
|
* @returns {number} number of milliseconds since the specified time
|
104
94
|
*/
|
105
|
-
export function sinceMs(sinceMs =
|
95
|
+
export function sinceMs(sinceMs = TIME_2025_01_01) {
|
106
96
|
return Date.now() - sinceMs;
|
107
97
|
}
|
108
98
|
|
109
|
-
// -----------------------------------------------------------------------------
|
110
|
-
|
111
99
|
/**
|
112
100
|
* Get a string that represents the time in a readable
|
113
101
|
* string format: [DD:][HH:]MM:SS.mmm
|
@@ -144,13 +132,11 @@ export function timeToString(timeMs) {
|
|
144
132
|
|
145
133
|
str += `${minutes.toString().padStart(2, '0')}:`;
|
146
134
|
str += `${seconds.toString().padStart(2, '0')}.`;
|
147
|
-
str += `${restMs.toString().
|
135
|
+
str += `${restMs.toString().padStart(3, '0')}`;
|
148
136
|
|
149
137
|
return str;
|
150
138
|
}
|
151
139
|
|
152
|
-
// -----------------------------------------------------------------------------
|
153
|
-
|
154
140
|
/**
|
155
141
|
* Returns a Date object
|
156
142
|
* - The input can be a Date object or a numeric timestamp
|
@@ -171,8 +157,6 @@ export function toDate(dateOrTimestamp) {
|
|
171
157
|
throw new Error('Missing or invalid parameter [dateOrTimestamp]');
|
172
158
|
}
|
173
159
|
|
174
|
-
// -----------------------------------------------------------------------------
|
175
|
-
|
176
160
|
/**
|
177
161
|
* Get the ISO 8601 week number of the specified date
|
178
162
|
*
|
@@ -225,70 +209,72 @@ export function getWeekNumber(dateOrTimestamp) {
|
|
225
209
|
// of the year and the Thursday in the target week
|
226
210
|
// (604800000 = 7 * 24 * 3600 * 1000)
|
227
211
|
//
|
228
|
-
return 1 + Math.ceil((firstThursday - target) / 604800000);
|
212
|
+
return 1 + Math.ceil((firstThursday - target.getTime()) / 604800000);
|
229
213
|
}
|
230
214
|
|
231
|
-
// -----------------------------------------------------------------------------
|
232
|
-
|
233
215
|
/**
|
234
216
|
* Get the name of the month
|
235
|
-
* - Returns the
|
236
|
-
*
|
237
|
-
* - Use the output as label in combination with the functions
|
238
|
-
* text() and translate() for international month names
|
239
|
-
*
|
240
|
-
* e.g.
|
217
|
+
* - Returns the month name using Intl.DateTimeFormat
|
218
|
+
* - By default uses English locale, but locale can be specified
|
241
219
|
*
|
242
|
-
*
|
243
|
-
*
|
220
|
+
* @param {Date|number} dateOrTimestamp - Date object or timestamp
|
221
|
+
* @param {string} [locale='nl-NL'] - The locale to use for the month name
|
244
222
|
*
|
245
|
-
*
|
223
|
+
* @param {Object} [options]
|
224
|
+
* @param {'numeric'|'2-digit'|'narrow'|'short'|'long'} [options.month='long']
|
225
|
+
* @param {string} [options.timeZone] - Optional timezone
|
246
226
|
*
|
247
|
-
*
|
248
|
-
*
|
249
|
-
* @param {Date|number} dateOrTimestamp
|
250
|
-
*
|
251
|
-
* @returns {string} name of the month (English)
|
227
|
+
* @returns {string} name of the month in the specified locale
|
252
228
|
*/
|
253
|
-
export function getMonthName(dateOrTimestamp
|
254
|
-
|
255
|
-
// return MONTH_NAME_LABELS_EN[toDate(dateOrTimestamp).getMonth()];
|
256
|
-
}
|
229
|
+
export function getMonthName(dateOrTimestamp, locale = 'nl-NL',
|
230
|
+
options = { month: 'long' }) {
|
257
231
|
|
258
|
-
|
232
|
+
const date = toDate(dateOrTimestamp);
|
233
|
+
|
234
|
+
// Create formatter with provided locale and options
|
235
|
+
// @ts-ignore - TypeScript kan hier strikter zijn dan nodig met de options
|
236
|
+
const formatter = new Intl.DateTimeFormat(locale, {
|
237
|
+
month: options?.month || 'long',
|
238
|
+
...(options?.timeZone ? { timeZone: options.timeZone } : {})
|
239
|
+
});
|
240
|
+
|
241
|
+
return formatter.format(date);
|
242
|
+
}
|
259
243
|
|
260
244
|
/**
|
261
|
-
* Get the name of the day
|
262
|
-
* - Returns the
|
263
|
-
*
|
264
|
-
* - Use the output as label in combination with the functions
|
265
|
-
* text() and translate() for international day names
|
245
|
+
* Get the name of the day of the week
|
246
|
+
* - Returns the day name using Intl.DateTimeFormat
|
247
|
+
* - By default uses English locale, but locale can be specified
|
266
248
|
*
|
267
|
-
*
|
249
|
+
* @param {Date|number} dateOrTimestamp - Date object or timestamp
|
250
|
+
* @param {string} [locale='nl-NL'] - The locale to use for the day name
|
268
251
|
*
|
269
|
-
*
|
270
|
-
*
|
271
|
-
*
|
272
|
-
* text( getDayName( new Date() ) );
|
273
|
-
*
|
274
|
-
* --
|
275
|
-
*
|
276
|
-
* @param {Date|number} dateOrTimestamp
|
252
|
+
* @param {Object} [options]
|
253
|
+
* @param {'narrow'|'short'|'long'} [options.weekday='long']
|
254
|
+
* @param {string} [options.timeZone] - Optional timezone
|
277
255
|
*
|
278
|
-
* @returns {string} name of the day
|
256
|
+
* @returns {string} name of the day in the specified locale
|
279
257
|
*/
|
280
|
-
export function getDayName(dateOrTimestamp
|
281
|
-
|
282
|
-
|
283
|
-
|
258
|
+
export function getDayName(dateOrTimestamp, locale = 'nl-NL',
|
259
|
+
options = { weekday: 'long' }) {
|
260
|
+
|
261
|
+
const date = toDate(dateOrTimestamp);
|
284
262
|
|
285
|
-
//
|
263
|
+
// Create formatter with provided locale and options
|
264
|
+
// @ts-ignore - TypeScript kan hier strikter zijn dan nodig met de options
|
265
|
+
const formatter = new Intl.DateTimeFormat(locale, {
|
266
|
+
weekday: options?.weekday || 'long',
|
267
|
+
...(options?.timeZone ? { timeZone: options.timeZone } : {})
|
268
|
+
});
|
269
|
+
|
270
|
+
return formatter.format(date);
|
271
|
+
}
|
286
272
|
|
287
273
|
/**
|
288
274
|
* Return the timestamp of the start of the day
|
289
275
|
* - Midnight
|
290
276
|
*
|
291
|
-
* @param {Date|number} dateOrTimestamp
|
277
|
+
* @param {Date|number} [dateOrTimestamp]
|
292
278
|
*
|
293
279
|
* @returns {number} timestamp of start of the day (00:00:00:0000)
|
294
280
|
*/
|
@@ -310,13 +296,11 @@ export function getTimeAtStartOfDay(dateOrTimestamp) {
|
|
310
296
|
return d.getTime();
|
311
297
|
}
|
312
298
|
|
313
|
-
// -----------------------------------------------------------------------------
|
314
|
-
|
315
299
|
/**
|
316
300
|
* Return the timestamp of the end of the day
|
317
301
|
* - Midnight - 1 millisecond
|
318
302
|
*
|
319
|
-
* @param {Date|number} dateOrTimestamp
|
303
|
+
* @param {Date|number} [dateOrTimestamp]
|
320
304
|
*
|
321
305
|
* @returns {number} timestamp of start of the day
|
322
306
|
*/
|
@@ -0,0 +1,81 @@
|
|
1
|
+
/**
|
2
|
+
* Returns a three character prefix that is calculated at boot
|
3
|
+
*
|
4
|
+
* @returns {string} boot time prefix
|
5
|
+
*/
|
6
|
+
export function bootTimePrefix(): string;
|
7
|
+
/**
|
8
|
+
* Create a string that contains random characters from the base58 alphabet
|
9
|
+
*
|
10
|
+
* @param {number} [length=48]
|
11
|
+
*
|
12
|
+
* @returns {string} a base 58 encoded random string
|
13
|
+
*/
|
14
|
+
export function randomStringBase58(length?: number): string;
|
15
|
+
/**
|
16
|
+
* Create a string that contains random characters from a for human's not
|
17
|
+
* ambiguous alphabet
|
18
|
+
*
|
19
|
+
* @param {number} [length=48]
|
20
|
+
*
|
21
|
+
* @returns {string} a human friendly encoded random string
|
22
|
+
*/
|
23
|
+
export function randomStringBaseHuman(length?: number): string;
|
24
|
+
/**
|
25
|
+
* Create a string that contains random characters from the specified alphabet
|
26
|
+
*
|
27
|
+
* @param {number} [length=48]
|
28
|
+
* @param {string} [ALPHABET=ALPHABET_BASE_58]
|
29
|
+
*
|
30
|
+
* @returns {string} a base 58 encoded random string
|
31
|
+
*/
|
32
|
+
export function randomString(length?: number, ALPHABET?: string): string;
|
33
|
+
/**
|
34
|
+
* Create an access code: a string that contains 48 random characters from the
|
35
|
+
* base58 alphabet
|
36
|
+
*
|
37
|
+
* @returns {string} a base 58 encoded random string of length 48
|
38
|
+
*/
|
39
|
+
export function randomAccessCode(): string;
|
40
|
+
/**
|
41
|
+
* Generate client session id
|
42
|
+
*
|
43
|
+
* @returns {string} a base 58 encoded random string of length 48
|
44
|
+
*/
|
45
|
+
export function generateClientSessionId(): string;
|
46
|
+
/**
|
47
|
+
* Generates and returns a new unique local id
|
48
|
+
* - The generated id is garanteed to be unique on the currently running
|
49
|
+
* local system
|
50
|
+
*
|
51
|
+
* @param {number} [timeMs]
|
52
|
+
* Custom time value to be used instead of Date.now()
|
53
|
+
*
|
54
|
+
* @returns {string} local id
|
55
|
+
*/
|
56
|
+
export function generateLocalId(timeMs?: number): string;
|
57
|
+
/**
|
58
|
+
* Returns a time based number that changes every 30 seconds
|
59
|
+
*
|
60
|
+
* @param {number} [timeMs=sinceMs()]
|
61
|
+
* Custom time value to be used instead of sinceMs()
|
62
|
+
*
|
63
|
+
* @returns {number} time based numerical that changes every 30 seconds
|
64
|
+
*/
|
65
|
+
export function getTimeBasedNumber30s(timeMs?: number): number;
|
66
|
+
/**
|
67
|
+
* Returns two character base58 encoded string that changes every 10
|
68
|
+
* milliseconds
|
69
|
+
*
|
70
|
+
* - The function output changes every 9 milliseconds
|
71
|
+
* - Returns a two character string
|
72
|
+
* - The string is base58 encoded
|
73
|
+
* - After 58 * 58 * 10ms = 33,6 seconds, the function output repeats
|
74
|
+
*
|
75
|
+
* @param {number} [timeMs]
|
76
|
+
* Custom time value to be used instead of Date.now()
|
77
|
+
*
|
78
|
+
* @returns {string} time based value
|
79
|
+
*/
|
80
|
+
export function getTwoChar10ms(timeMs?: number): string;
|
81
|
+
export const BOOT_STAMP: string;
|
@@ -0,0 +1,249 @@
|
|
1
|
+
/**
|
2
|
+
* unique.js
|
3
|
+
*
|
4
|
+
* @description
|
5
|
+
* This file contains functionality to generate unique data
|
6
|
+
*
|
7
|
+
* @example
|
8
|
+
*
|
9
|
+
* import { generateLocalId } from './unqiue.js';
|
10
|
+
*
|
11
|
+
* async function test()
|
12
|
+
* {
|
13
|
+
* console.log( `Id 1 [${generateLocalId()}]` );
|
14
|
+
* console.log( `Id 2 [${generateLocalId()}]` );
|
15
|
+
* }
|
16
|
+
*/
|
17
|
+
|
18
|
+
/* ------------------------------------------------------------------ Imports */
|
19
|
+
|
20
|
+
import { ALPHABET_BASE_HUMAN, ALPHABET_BASE_58 } from '../../constants/bases.js';
|
21
|
+
|
22
|
+
import { base58fromNumber } from '../bases';
|
23
|
+
|
24
|
+
import { TIME_2025_01_01 } from '../../constants/time';
|
25
|
+
|
26
|
+
import { sinceMs } from '../time';
|
27
|
+
|
28
|
+
/**
|
29
|
+
* @type {{
|
30
|
+
* bootTimePrefix?:string,
|
31
|
+
* lastTimeBasedNumber?: number,
|
32
|
+
* lastTimeBasedValue58?: string,
|
33
|
+
* lastCountBasedNumber?: number
|
34
|
+
* }}
|
35
|
+
*/
|
36
|
+
var vars = {}; /* @note use 'var declaration' for hoisting */
|
37
|
+
|
38
|
+
export const BOOT_STAMP = ( Date.now() - TIME_2025_01_01 ).toString(36);
|
39
|
+
|
40
|
+
/* ------------------------------------------------------------------ Exports */
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Returns a three character prefix that is calculated at boot
|
44
|
+
*
|
45
|
+
* @returns {string} boot time prefix
|
46
|
+
*/
|
47
|
+
export function bootTimePrefix()
|
48
|
+
{
|
49
|
+
if( !vars.bootTimePrefix )
|
50
|
+
{
|
51
|
+
vars.bootTimePrefix = '3' + getTwoChar10ms();
|
52
|
+
}
|
53
|
+
|
54
|
+
return vars.bootTimePrefix;
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Create a string that contains random characters from the base58 alphabet
|
59
|
+
*
|
60
|
+
* @param {number} [length=48]
|
61
|
+
*
|
62
|
+
* @returns {string} a base 58 encoded random string
|
63
|
+
*/
|
64
|
+
export function randomStringBase58( length=48 )
|
65
|
+
{
|
66
|
+
return randomString( length, ALPHABET_BASE_58 );
|
67
|
+
}
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Create a string that contains random characters from a for human's not
|
71
|
+
* ambiguous alphabet
|
72
|
+
*
|
73
|
+
* @param {number} [length=48]
|
74
|
+
*
|
75
|
+
* @returns {string} a human friendly encoded random string
|
76
|
+
*/
|
77
|
+
export function randomStringBaseHuman( length=48 )
|
78
|
+
{
|
79
|
+
return randomString( length, ALPHABET_BASE_HUMAN );
|
80
|
+
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Create a string that contains random characters from the specified alphabet
|
84
|
+
*
|
85
|
+
* @param {number} [length=48]
|
86
|
+
* @param {string} [ALPHABET=ALPHABET_BASE_58]
|
87
|
+
*
|
88
|
+
* @returns {string} a base 58 encoded random string
|
89
|
+
*/
|
90
|
+
export function randomString( length=48, ALPHABET=ALPHABET_BASE_58 )
|
91
|
+
{
|
92
|
+
if( typeof length !== 'number' || length < 1 )
|
93
|
+
{
|
94
|
+
throw new Error('Invalid parameter [length]');
|
95
|
+
}
|
96
|
+
|
97
|
+
if( typeof ALPHABET !== 'string' || !ALPHABET.length )
|
98
|
+
{
|
99
|
+
throw new Error('Invalid parameter [ALPHABET]');
|
100
|
+
}
|
101
|
+
|
102
|
+
let str = '';
|
103
|
+
|
104
|
+
const n = ALPHABET.length;
|
105
|
+
|
106
|
+
for( let j = length; j > 0; j = j - 1 )
|
107
|
+
{
|
108
|
+
const num = n * Math.random() & -1; // number [0...n-1]
|
109
|
+
str += ALPHABET[ num ];
|
110
|
+
}
|
111
|
+
|
112
|
+
return str;
|
113
|
+
}
|
114
|
+
|
115
|
+
/**
|
116
|
+
* Create an access code: a string that contains 48 random characters from the
|
117
|
+
* base58 alphabet
|
118
|
+
*
|
119
|
+
* @returns {string} a base 58 encoded random string of length 48
|
120
|
+
*/
|
121
|
+
export function randomAccessCode()
|
122
|
+
{
|
123
|
+
return randomStringBase58( 48 );
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* Generate client session id
|
128
|
+
*
|
129
|
+
* @returns {string} a base 58 encoded random string of length 48
|
130
|
+
*/
|
131
|
+
export function generateClientSessionId()
|
132
|
+
{
|
133
|
+
return randomStringBase58( 48 );
|
134
|
+
}
|
135
|
+
|
136
|
+
/**
|
137
|
+
* Generates and returns a new unique local id
|
138
|
+
* - The generated id is garanteed to be unique on the currently running
|
139
|
+
* local system
|
140
|
+
*
|
141
|
+
* @param {number} [timeMs]
|
142
|
+
* Custom time value to be used instead of Date.now()
|
143
|
+
*
|
144
|
+
* @returns {string} local id
|
145
|
+
*/
|
146
|
+
export function generateLocalId( timeMs )
|
147
|
+
{
|
148
|
+
const timeBasedNumber = getTimeBasedNumber30s( timeMs );
|
149
|
+
|
150
|
+
let timeBasedValue58;
|
151
|
+
|
152
|
+
let countBasedNumber;
|
153
|
+
|
154
|
+
if( vars.lastTimeBasedNumber !== timeBasedNumber )
|
155
|
+
{
|
156
|
+
// -- Time stamp based number changed -> reset counter to zero
|
157
|
+
|
158
|
+
countBasedNumber =
|
159
|
+
vars.lastCountBasedNumber = 0;
|
160
|
+
|
161
|
+
// -- Calculate timeBasedValue58 and update cache
|
162
|
+
|
163
|
+
vars.lastTimeBasedNumber = timeBasedNumber;
|
164
|
+
|
165
|
+
// cache string representation
|
166
|
+
timeBasedValue58 =
|
167
|
+
vars.lastTimeBasedValue58 = base58fromNumber( timeBasedNumber );
|
168
|
+
}
|
169
|
+
else {
|
170
|
+
// -- Same time stamp based number -> increment counter
|
171
|
+
|
172
|
+
countBasedNumber =
|
173
|
+
vars.lastCountBasedNumber = vars.lastCountBasedNumber + 1;
|
174
|
+
|
175
|
+
// -- Use cached lastTimeBasedNumber
|
176
|
+
|
177
|
+
timeBasedValue58 = vars.lastTimeBasedValue58;
|
178
|
+
}
|
179
|
+
|
180
|
+
const countBasedValue58 = base58fromNumber( countBasedNumber );
|
181
|
+
|
182
|
+
// Combine parts into single identifier string
|
183
|
+
//
|
184
|
+
// @note ALPHABET_BASE_58 is used because it is faster than
|
185
|
+
// base58fromNumber for single character encoding
|
186
|
+
//
|
187
|
+
const id =
|
188
|
+
// idFormatPrefix
|
189
|
+
bootTimePrefix() +
|
190
|
+
ALPHABET_BASE_58[ timeBasedValue58.length ] +
|
191
|
+
timeBasedValue58 +
|
192
|
+
countBasedValue58;
|
193
|
+
|
194
|
+
// std.debug( id );
|
195
|
+
|
196
|
+
return id;
|
197
|
+
}
|
198
|
+
|
199
|
+
|
200
|
+
/**
|
201
|
+
* Returns a time based number that changes every 30 seconds
|
202
|
+
*
|
203
|
+
* @param {number} [timeMs=sinceMs()]
|
204
|
+
* Custom time value to be used instead of sinceMs()
|
205
|
+
*
|
206
|
+
* @returns {number} time based numerical that changes every 30 seconds
|
207
|
+
*/
|
208
|
+
export function getTimeBasedNumber30s( timeMs )
|
209
|
+
{
|
210
|
+
if( !timeMs )
|
211
|
+
{
|
212
|
+
timeMs = sinceMs();
|
213
|
+
}
|
214
|
+
|
215
|
+
// @note do not use bitwise shift since it only works on 32 bit numbers!
|
216
|
+
return Math.floor( timeMs / 30000 );
|
217
|
+
}
|
218
|
+
|
219
|
+
|
220
|
+
/**
|
221
|
+
* Returns two character base58 encoded string that changes every 10
|
222
|
+
* milliseconds
|
223
|
+
*
|
224
|
+
* - The function output changes every 9 milliseconds
|
225
|
+
* - Returns a two character string
|
226
|
+
* - The string is base58 encoded
|
227
|
+
* - After 58 * 58 * 10ms = 33,6 seconds, the function output repeats
|
228
|
+
*
|
229
|
+
* @param {number} [timeMs]
|
230
|
+
* Custom time value to be used instead of Date.now()
|
231
|
+
*
|
232
|
+
* @returns {string} time based value
|
233
|
+
*/
|
234
|
+
export function getTwoChar10ms( timeMs )
|
235
|
+
{
|
236
|
+
const now = timeMs || Date.now();
|
237
|
+
|
238
|
+
// @note
|
239
|
+
// do not use bitwise shift since it only works on 32 bit numbers
|
240
|
+
const num = Math.floor( now / 10 ) % 3364;
|
241
|
+
|
242
|
+
if( num >= 58 )
|
243
|
+
{
|
244
|
+
return base58fromNumber( num );
|
245
|
+
}
|
246
|
+
else {
|
247
|
+
return '1' + base58fromNumber( num );
|
248
|
+
}
|
249
|
+
}
|