@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.
@@ -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';
@@ -15,5 +15,4 @@ export const INTERVALS_MS: {
15
15
  "two-weekly": number;
16
16
  "four-weekly": number;
17
17
  };
18
- export const TIME_2020_01_01: 1577836800000;
19
- export const TIME_2100_01_01: 4102444800000;
18
+ export const TIME_2025_01_01: 1577836800000;
@@ -24,5 +24,5 @@ export const INTERVALS_MS = {
24
24
 
25
25
  // > Offsets
26
26
 
27
- export const TIME_2020_01_01 = 1577836800000; // 2020-01-01T00:00:00.000Z
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 {Promise} promise that resolves after a specified timeout
13
+ * @returns {HkPromise} promise that resolves after a specified timeout
14
14
  */
15
- export function delay(delayOrMinDelayMs: number, maxDelayMs?: number): Promise<any>;
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 TIME_2020_01_01
18
+ * reference time stamp TIME_2025_01_01
19
19
  *
20
- * @param {number} [sinceMs=TIME_2020_01_01]
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 English name of the month
56
+ * - Returns the month name using Intl.DateTimeFormat
57
+ * - By default uses English locale, but locale can be specified
57
58
  *
58
- * - Use the output as label in combination with the functions
59
- * text() and translate() for international month names
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
- * e.g.
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
- * setTranslations()
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): string;
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 English name of the day
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
- * e.g.
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
- * setTranslations()
85
- * ...
80
+ * @param {Object} [options]
81
+ * @param {'narrow'|'short'|'long'} [options.weekday='long']
82
+ * @param {string} [options.timeZone] - Optional timezone
86
83
  *
87
- * text( getDayName( new Date() ) );
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): string;
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: Date | number): number;
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: Date | number): number;
114
- export const SECOND_MS: 1000;
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';
@@ -28,24 +28,16 @@
28
28
  * }).format(d);
29
29
  */
30
30
 
31
- /* ------------------------------------------------------------------ Imports */
32
-
33
- import * as expect from '../expect/index.js';
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 {Promise} promise that resolves after a specified timeout
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 TIME_2020_01_01
89
+ * reference time stamp TIME_2025_01_01
100
90
  *
101
- * @param {number} [sinceMs=TIME_2020_01_01]
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 = TIME_2020_01_01) {
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().padEnd(3, '0')}`;
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 English name of the month
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
- * setTranslations()
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
- * text( getMonthName( new Date() ) );
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
- throw new Error('Not implemented yet');
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 English name of the day
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
- * e.g.
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
- * setTranslations()
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 (English)
256
+ * @returns {string} name of the day in the specified locale
279
257
  */
280
- export function getDayName(dateOrTimestamp) {
281
- throw new Error('Not implemented yet');
282
- // return DAY_NAME_LABELS_EN[toDate(dateOrTimestamp).getDay()];
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkdigital/lib-sveltekit",
3
- "version": "0.1.58",
3
+ "version": "0.1.60",
4
4
  "author": {
5
5
  "name": "HKdigital",
6
6
  "url": "https://hkdigital.nl"