@andrew_l/snowflake 0.2.20

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2024 Andrew L. <andrew.io.dev@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # Snowflake - Generate unique IDs in a distributed environment at scale
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ ![license][license-src]
5
+ [![bundle][bundle-src]][bundle-href]
6
+
7
+ There is a bit improved version of [@sapphire/snowflake](https://github.com/sapphiredev/utilities/tree/main/packages/snowflake) package by using javascript numbers and Uint8Array buffer.
8
+
9
+ ⚡ **Benchmark**
10
+
11
+ ```
12
+ name hz rme samples
13
+ · sapphire 10,690,009.83 ±0.62% 10690010
14
+ · andrew (bigint) 11,704,038.89 ±0.03% 11704039
15
+ · andrew (buffer) 13,808,748.82 ±0.37% 13808749
16
+ · andrew (buffer unsafe) 16,023,413.95 ±0.04% 16023414 fastest
17
+ ```
18
+
19
+ <!-- install placeholder -->
20
+
21
+ ## 🚀 Example Usage
22
+
23
+ ### Basic Example
24
+
25
+ ```javascript
26
+ import { Snowflake } from '@andrew_l/snowflake';
27
+
28
+ // Define a custom epoch
29
+ const epoch = 1751810749563;
30
+
31
+ // Create an instance of Snowflake
32
+ const snowflake = new Snowflake({ epoch });
33
+
34
+ // Generate a snowflake with the given epoch
35
+ const uniqueId = snowflake.generate();
36
+
37
+ // Generate a snowflake with the given epoch
38
+ const uniqueIdBuffer = snowflake.generateBuffer();
39
+ ```
40
+
41
+ ### Stripe Style
42
+
43
+ ```javascript
44
+ import { Snowflake } from '@andrew_l/snowflake';
45
+ import { base62, bigIntFromBytes } from '@andrew_l/toolkit';
46
+
47
+ // Create an instance of Snowflake
48
+ const snowflake = new Snowflake({ epoch: 1288834974657 });
49
+
50
+ // Generate a snowflake with the given epoch
51
+ const customerId = 'cus_' + base62.encode(snowflake.generateBuffer());
52
+
53
+ // e.g. cus_2JRkp89kSZs
54
+ console.log('customer id =', customerId);
55
+
56
+ // Extract the numeric value by decoding the base62 portion
57
+ const customerIdNumber = bigIntFromBytes(base62.decode(customerId.slice(4)));
58
+
59
+ // e.g. 1941863457523503104n
60
+ console.log('customer id (number) =', customerIdNumber);
61
+ ```
62
+
63
+ <!-- Badges -->
64
+
65
+ [npm-version-src]: https://img.shields.io/npm/v/@andrew_l/snowflake?style=flat
66
+ [npm-version-href]: https://npmjs.com/package/@andrew_l/snowflake
67
+ [bundle-src]: https://img.shields.io/bundlephobia/min/@andrew_l/snowflake?style=flat
68
+ [bundle-href]: https://bundlephobia.com/result?p=@andrew_l/snowflake
69
+ [license-src]: https://img.shields.io/npm/l/@andrew_l/snowflake?style=flat
package/dist/index.cjs ADDED
@@ -0,0 +1,230 @@
1
+ 'use strict';
2
+
3
+ const toolkit = require('@andrew_l/toolkit');
4
+
5
+ var MAX_WORKER_ID = 31;
6
+ var MAX_PROCESS_ID = 31;
7
+ var MAX_INCREMENT = 4095;
8
+ class Snowflake {
9
+ /**
10
+ * Alias for {@link deconstruct}
11
+ */
12
+ decode = this.deconstruct;
13
+ /**
14
+ * Internal reference of the epoch passed in the constructor
15
+ * @internal
16
+ */
17
+ _epoch;
18
+ /**
19
+ * Internal incrementor for generating snowflakes
20
+ * @internal
21
+ */
22
+ _increment = 0;
23
+ /**
24
+ * The process ID that will be used by default in the generate method
25
+ * @internal
26
+ */
27
+ _processId = 1;
28
+ /**
29
+ * The worker ID that will be used by default in the generate method
30
+ * @internal
31
+ */
32
+ _workerId = 0;
33
+ /**
34
+ * @internal
35
+ */
36
+ _buffer;
37
+ /**
38
+ * @param epoch the epoch to use
39
+ */
40
+ constructor(opts) {
41
+ if (toolkit.isDate(opts) || toolkit.isNumber(opts)) {
42
+ this._epoch = toolkit.timestampMs(opts);
43
+ } else if (toolkit.isBigInt(opts)) {
44
+ this._epoch = toolkit.timestampMs(Number(opts));
45
+ } else {
46
+ const { increment = 0, processId = 1, workerId = 0, epoch } = opts;
47
+ this._epoch = toolkit.timestampMs(toolkit.isBigInt(epoch) ? Number(epoch) : epoch);
48
+ this.workerId = workerId;
49
+ this.processId = processId;
50
+ this._increment = Number(increment) & MAX_INCREMENT;
51
+ }
52
+ this._buffer = new Uint8Array(8);
53
+ }
54
+ /**
55
+ * The epoch for this snowflake, as a number
56
+ */
57
+ get epoch() {
58
+ return this._epoch;
59
+ }
60
+ /**
61
+ * Gets the configured process ID
62
+ */
63
+ get processId() {
64
+ return this._processId;
65
+ }
66
+ /**
67
+ * Sets the process ID that will be used by default for the {@link generate} method
68
+ * @param value The new value, will be masked with `0b11111`
69
+ */
70
+ set processId(value) {
71
+ this._processId = Number(value) & MAX_PROCESS_ID;
72
+ }
73
+ /**
74
+ * Gets the configured worker ID
75
+ */
76
+ get workerId() {
77
+ return this._workerId;
78
+ }
79
+ /**
80
+ * Sets the worker ID that will be used by default for the {@link generate} method
81
+ * @param value The new value, will be masked with `0b11111`
82
+ */
83
+ set workerId(value) {
84
+ this._workerId = Number(value) & MAX_WORKER_ID;
85
+ }
86
+ /**
87
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
88
+ */
89
+ generate(timestamp = Date.now()) {
90
+ if (timestamp instanceof Date) timestamp = timestamp.getTime();
91
+ if (!toolkit.isNumber(timestamp)) {
92
+ throw new Error(
93
+ `"timestamp" argument must be a number or Date (received ${typeof timestamp})`
94
+ );
95
+ }
96
+ var increment = this._increment;
97
+ this._increment = this._increment + 1 & MAX_INCREMENT;
98
+ return BigInt(timestamp - this._epoch) << 22n | BigInt(this._workerId & MAX_WORKER_ID) << 17n | BigInt(this._processId & MAX_PROCESS_ID) << 12n | BigInt(increment & MAX_INCREMENT);
99
+ }
100
+ /**
101
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
102
+ *
103
+ * ⚠️ Returns a reference to the **same** internal `Uint8Array` instance.
104
+ * Its contents may be overwritten on the next ID generation call.
105
+ *
106
+ * This method is intended for high-performance scenarios where you
107
+ * immediately transform the buffer (e.g., to base62) before calling again.
108
+ * Avoid storing or mutating the returned buffer directly.
109
+ */
110
+ generateBufferUnsafe(timestamp = Date.now()) {
111
+ if (timestamp instanceof Date) timestamp = timestamp.getTime();
112
+ if (!toolkit.isNumber(timestamp)) {
113
+ throw new Error(
114
+ `"timestamp" argument must be a number or Date (received ${typeof timestamp})`
115
+ );
116
+ }
117
+ var increment = this._increment;
118
+ this._increment = this._increment + 1 & MAX_INCREMENT;
119
+ var timestampDelta = timestamp - this._epoch;
120
+ var timestampHigh = Math.floor(timestampDelta / 4294967295);
121
+ var timestampLow = timestampDelta >>> 0;
122
+ var high32 = (timestampHigh << 22 | timestampLow >>> 10) >>> 0;
123
+ var low32 = (timestampLow << 22 | this._workerId << 17 | this._processId << 12 | increment & MAX_INCREMENT) >>> 0;
124
+ var buffer = this._buffer;
125
+ buffer[0] = high32 >>> 24;
126
+ buffer[1] = high32 >>> 16;
127
+ buffer[2] = high32 >>> 8;
128
+ buffer[3] = high32;
129
+ buffer[4] = low32 >>> 24;
130
+ buffer[5] = low32 >>> 16;
131
+ buffer[6] = low32 >>> 8;
132
+ buffer[7] = low32;
133
+ return buffer;
134
+ }
135
+ /**
136
+ * Generates a snowflake given an epoch and optionally a timestamp
137
+ * @example
138
+ * ```typescript
139
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
140
+ * const snowflake = new Snowflake({ epoch }).generate();
141
+ * ```
142
+ * @returns A unique snowflake as Uint8Array
143
+ */
144
+ generateBuffer(timestamp = Date.now()) {
145
+ this.generateBufferUnsafe(timestamp);
146
+ return new Uint8Array(this._buffer);
147
+ }
148
+ /**
149
+ * Deconstructs a snowflake given a snowflake ID
150
+ * @param id the snowflake to deconstruct
151
+ * @returns a deconstructed snowflake
152
+ * @example
153
+ * ```typescript
154
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
155
+ * const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');
156
+ * ```
157
+ */
158
+ deconstruct(id) {
159
+ var high32, low32;
160
+ if (id instanceof Uint8Array) {
161
+ high32 = (id[0] << 24 | id[1] << 16 | id[2] << 8 | id[3]) >>> 0;
162
+ low32 = (id[4] << 24 | id[5] << 16 | id[6] << 8 | id[7]) >>> 0;
163
+ } else if (toolkit.isBigInt(id)) {
164
+ return this.deconstruct(toolkit.bigIntBytes(id));
165
+ } else {
166
+ return this.deconstruct(toolkit.bigIntBytes(BigInt(id)));
167
+ }
168
+ return {
169
+ id: BigInt(high32) * 0x100000000n + BigInt(low32),
170
+ timestamp: high32 * 1024 + (low32 >>> 22) + this._epoch,
171
+ workerId: low32 >>> 17 & MAX_WORKER_ID,
172
+ processId: low32 >>> 12 & MAX_PROCESS_ID,
173
+ increment: low32 & MAX_INCREMENT,
174
+ epoch: this._epoch
175
+ };
176
+ }
177
+ /**
178
+ * Retrieves the timestamp field's value from a snowflake.
179
+ * @param id The snowflake to get the timestamp value from.
180
+ * @returns The UNIX timestamp that is stored in `id`.
181
+ */
182
+ timestampFrom(id) {
183
+ if (toolkit.isString(id) || toolkit.isBigInt(id)) {
184
+ return this.timestampFrom(Snowflake.bufferFrom(id));
185
+ }
186
+ var high32 = (id[0] << 24 | id[1] << 16 | id[2] << 8 | id[3]) >>> 0;
187
+ var low32 = (id[4] << 24 | id[5] << 16 | id[6] << 8 | id[7]) >>> 0;
188
+ return high32 * 1024 + (low32 >>> 22) + this._epoch;
189
+ }
190
+ /**
191
+ * Returns a number indicating whether a reference snowflake comes before, or after, or is same as the given
192
+ * snowflake in sort order.
193
+ * @param a The first snowflake to compare.
194
+ * @param b The second snowflake to compare.
195
+ * @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.
196
+ */
197
+ static compare(a, b) {
198
+ if (toolkit.isString(a)) {
199
+ a = BigInt(a);
200
+ } else if (a instanceof Uint8Array) {
201
+ a = toolkit.bigIntFromBytes(a);
202
+ }
203
+ if (toolkit.isString(b)) {
204
+ b = BigInt(b);
205
+ } else if (b instanceof Uint8Array) {
206
+ b = toolkit.bigIntFromBytes(b);
207
+ }
208
+ return a === b ? 0 : a < b ? -1 : 1;
209
+ }
210
+ /**
211
+ * Parse value as Uint8Array buffer
212
+ */
213
+ static bufferFrom(value) {
214
+ if (toolkit.isString(value)) value = BigInt(value);
215
+ var buf = toolkit.bigIntBytes(value);
216
+ var bufSize = buf.byteLength;
217
+ if (buf.byteLength < 8) {
218
+ var buf2 = new Uint8Array(8);
219
+ buf2.set(buf, 8 - bufSize);
220
+ buf = buf2;
221
+ }
222
+ return buf;
223
+ }
224
+ }
225
+
226
+ exports.MAX_INCREMENT = MAX_INCREMENT;
227
+ exports.MAX_PROCESS_ID = MAX_PROCESS_ID;
228
+ exports.MAX_WORKER_ID = MAX_WORKER_ID;
229
+ exports.Snowflake = Snowflake;
230
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/Snowflake.ts"],"sourcesContent":["/**\n * Based on: https://github.com/sapphiredev/utilities/blob/main/packages/snowflake/src/lib/Snowflake.ts\n */\nimport {\n bigIntBytes,\n bigIntFromBytes,\n isBigInt,\n isDate,\n isNumber,\n isString,\n timestampMs,\n} from '@andrew_l/toolkit';\n\n/**\n * Object returned by Snowflake#deconstruct\n */\nexport interface DeconstructedSnowflake {\n /**\n * The id as a number\n */\n id: bigint;\n\n /**\n * The timestamp stored in the snowflake\n */\n timestamp: number;\n\n /**\n * The worker id stored in the snowflake\n */\n workerId: number;\n\n /**\n * The process id stored in the snowflake\n */\n processId: number;\n\n /**\n * The increment stored in the snowflake\n */\n increment: number;\n\n /**\n * The epoch to use in the snowflake\n */\n epoch: number;\n}\n\n/**\n * Options for Snowflake\n */\nexport interface SnowflakeOptions {\n /**\n * Timestamp or date of the snowflake to generate\n */\n epoch: number | bigint | Date;\n\n /**\n * The increment to use\n * @default 0\n * @remark keep in mind that this number is auto-incremented between generate calls\n */\n increment?: number | bigint;\n\n /**\n * The worker ID to use, will be truncated to 5 bits (0-31)\n * @default 0\n */\n workerId?: number | bigint;\n\n /**\n * The process ID to use, will be truncated to 5 bits (0-31)\n * @default 1\n */\n processId?: number | bigint;\n}\n\n/**\n * The maximum value the `workerId` field accepts in snowflakes.\n */\nexport var MAX_WORKER_ID = 0x1f;\n\n/**\n * The maximum value the `processId` field accepts in snowflakes.\n */\nexport var MAX_PROCESS_ID = 0x1f;\n\n/**\n * The maximum value the `increment` field accepts in snowflakes.\n */\nexport var MAX_INCREMENT = 0xfff;\n\n/**\n * A class for generating and deconstructing Twitter snowflakes.\n *\n * A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake}\n * is a 64-bit unsigned integer with 4 fields that have a fixed epoch value.\n *\n * If we have a snowflake `266241948824764416` we can represent it as binary:\n * ```\n * 64 22 17 12 0\n * 000000111011000111100001101001000101000000 00001 00000 000000000000\n * number of ms since epoch worker pid increment\n * ```\n *\n * @group Main\n */\nexport class Snowflake {\n /**\n * Alias for {@link deconstruct}\n */\n public decode = this.deconstruct;\n\n /**\n * Internal reference of the epoch passed in the constructor\n * @internal\n */\n private readonly _epoch: number;\n\n /**\n * Internal incrementor for generating snowflakes\n * @internal\n */\n private _increment = 0;\n\n /**\n * The process ID that will be used by default in the generate method\n * @internal\n */\n private _processId = 1;\n\n /**\n * The worker ID that will be used by default in the generate method\n * @internal\n */\n private _workerId = 0;\n\n /**\n * @internal\n */\n private _buffer: Uint8Array;\n\n /**\n * @param epoch the epoch to use\n */\n public constructor(opts: SnowflakeOptions | Date | number | bigint) {\n if (isDate(opts) || isNumber(opts)) {\n this._epoch = timestampMs(opts);\n } else if (isBigInt(opts)) {\n this._epoch = timestampMs(Number(opts));\n } else {\n const { increment = 0, processId = 1, workerId = 0, epoch } = opts;\n this._epoch = timestampMs(isBigInt(epoch) ? Number(epoch) : epoch);\n this.workerId = workerId;\n this.processId = processId;\n this._increment = Number(increment) & MAX_INCREMENT;\n }\n\n this._buffer = new Uint8Array(8);\n }\n\n /**\n * The epoch for this snowflake, as a number\n */\n public get epoch(): number {\n return this._epoch;\n }\n\n /**\n * Gets the configured process ID\n */\n public get processId(): number {\n return this._processId;\n }\n\n /**\n * Sets the process ID that will be used by default for the {@link generate} method\n * @param value The new value, will be masked with `0b11111`\n */\n public set processId(value: number | bigint) {\n this._processId = Number(value) & MAX_PROCESS_ID;\n }\n\n /**\n * Gets the configured worker ID\n */\n public get workerId(): number {\n return this._workerId;\n }\n\n /**\n * Sets the worker ID that will be used by default for the {@link generate} method\n * @param value The new value, will be masked with `0b11111`\n */\n public set workerId(value: number | bigint) {\n this._workerId = Number(value) & MAX_WORKER_ID;\n }\n\n /**\n * Generates a Snowflake ID as a `Uint8Array` buffer.\n */\n public generate(timestamp: Date | number = Date.now()): bigint {\n if (timestamp instanceof Date) timestamp = timestamp.getTime();\n if (!isNumber(timestamp)) {\n throw new Error(\n `\"timestamp\" argument must be a number or Date (received ${typeof timestamp})`,\n );\n }\n\n var increment = this._increment;\n this._increment = (this._increment + 1) & MAX_INCREMENT;\n\n return (\n (BigInt(timestamp - this._epoch) << 22n) |\n (BigInt(this._workerId & MAX_WORKER_ID) << 17n) |\n (BigInt(this._processId & MAX_PROCESS_ID) << 12n) |\n BigInt(increment & MAX_INCREMENT)\n );\n }\n\n /**\n * Generates a Snowflake ID as a `Uint8Array` buffer.\n *\n * ⚠️ Returns a reference to the **same** internal `Uint8Array` instance.\n * Its contents may be overwritten on the next ID generation call.\n *\n * This method is intended for high-performance scenarios where you\n * immediately transform the buffer (e.g., to base62) before calling again.\n * Avoid storing or mutating the returned buffer directly.\n */\n public generateBufferUnsafe(timestamp: Date | number = Date.now()) {\n if (timestamp instanceof Date) timestamp = timestamp.getTime();\n if (!isNumber(timestamp)) {\n throw new Error(\n `\"timestamp\" argument must be a number or Date (received ${typeof timestamp})`,\n );\n }\n\n var increment = this._increment;\n this._increment = (this._increment + 1) & MAX_INCREMENT;\n\n // Calculate the timestamp delta\n var timestampDelta = timestamp - this._epoch;\n\n // Split into 32-bit parts for bitwise operations\n var timestampHigh = Math.floor(timestampDelta / 0xffffffff);\n var timestampLow = timestampDelta >>> 0;\n\n var high32 = ((timestampHigh << 22) | (timestampLow >>> 10)) >>> 0;\n var low32 =\n ((timestampLow << 22) |\n (this._workerId << 17) |\n (this._processId << 12) |\n (increment & MAX_INCREMENT)) >>>\n 0;\n\n var buffer = this._buffer;\n\n buffer[0] = high32 >>> 24;\n buffer[1] = high32 >>> 16;\n buffer[2] = high32 >>> 8;\n buffer[3] = high32;\n buffer[4] = low32 >>> 24;\n buffer[5] = low32 >>> 16;\n buffer[6] = low32 >>> 8;\n buffer[7] = low32;\n\n return buffer;\n }\n\n /**\n * Generates a snowflake given an epoch and optionally a timestamp\n * @example\n * ```typescript\n * const epoch = new Date('2000-01-01T00:00:00.000Z');\n * const snowflake = new Snowflake({ epoch }).generate();\n * ```\n * @returns A unique snowflake as Uint8Array\n */\n public generateBuffer(timestamp: Date | number = Date.now()) {\n this.generateBufferUnsafe(timestamp);\n return new Uint8Array(this._buffer);\n }\n\n /**\n * Deconstructs a snowflake given a snowflake ID\n * @param id the snowflake to deconstruct\n * @returns a deconstructed snowflake\n * @example\n * ```typescript\n * const epoch = new Date('2000-01-01T00:00:00.000Z');\n * const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');\n * ```\n */\n public deconstruct(id: string | bigint | Uint8Array): DeconstructedSnowflake {\n var high32: number, low32: number;\n\n if (id instanceof Uint8Array) {\n // Convert from Uint8Array\n high32 = ((id[0] << 24) | (id[1] << 16) | (id[2] << 8) | id[3]) >>> 0;\n low32 = ((id[4] << 24) | (id[5] << 16) | (id[6] << 8) | id[7]) >>> 0;\n } else if (isBigInt(id)) {\n return this.deconstruct(bigIntBytes(id));\n } else {\n // Convert from string\n return this.deconstruct(bigIntBytes(BigInt(id)));\n }\n\n return {\n id: BigInt(high32) * 0x100000000n + BigInt(low32),\n timestamp: high32 * 0x400 + (low32 >>> 22) + this._epoch,\n workerId: (low32 >>> 17) & MAX_WORKER_ID,\n processId: (low32 >>> 12) & MAX_PROCESS_ID,\n increment: low32 & MAX_INCREMENT,\n epoch: this._epoch,\n };\n }\n\n /**\n * Retrieves the timestamp field's value from a snowflake.\n * @param id The snowflake to get the timestamp value from.\n * @returns The UNIX timestamp that is stored in `id`.\n */\n public timestampFrom(id: string | bigint | Uint8Array): number {\n if (isString(id) || isBigInt(id)) {\n return this.timestampFrom(Snowflake.bufferFrom(id));\n }\n\n var high32 = ((id[0] << 24) | (id[1] << 16) | (id[2] << 8) | id[3]) >>> 0;\n var low32 = ((id[4] << 24) | (id[5] << 16) | (id[6] << 8) | id[7]) >>> 0;\n\n return high32 * 0x400 + (low32 >>> 22) + this._epoch;\n }\n\n /**\n * Returns a number indicating whether a reference snowflake comes before, or after, or is same as the given\n * snowflake in sort order.\n * @param a The first snowflake to compare.\n * @param b The second snowflake to compare.\n * @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.\n */\n public static compare(\n a: string | bigint | Uint8Array,\n b: string | bigint | Uint8Array,\n ): -1 | 0 | 1 {\n if (isString(a)) {\n a = BigInt(a);\n } else if (a instanceof Uint8Array) {\n a = bigIntFromBytes(a);\n }\n\n if (isString(b)) {\n b = BigInt(b);\n } else if (b instanceof Uint8Array) {\n b = bigIntFromBytes(b);\n }\n\n return a === b ? 0 : a < b ? -1 : 1;\n }\n\n /**\n * Parse value as Uint8Array buffer\n */\n public static bufferFrom(value: bigint | string): Uint8Array {\n if (isString(value)) value = BigInt(value);\n\n var buf = bigIntBytes(value);\n var bufSize = buf.byteLength;\n\n // Add padding\n if (buf.byteLength < 8) {\n var buf2 = new Uint8Array(8);\n buf2.set(buf, 8 - bufSize);\n buf = buf2;\n }\n\n return buf;\n }\n}\n"],"names":["isDate","isNumber","timestampMs","isBigInt","bigIntBytes","isString","bigIntFromBytes"],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Object returned by Snowflake#deconstruct
3
+ */
4
+ interface DeconstructedSnowflake {
5
+ /**
6
+ * The id as a number
7
+ */
8
+ id: bigint;
9
+ /**
10
+ * The timestamp stored in the snowflake
11
+ */
12
+ timestamp: number;
13
+ /**
14
+ * The worker id stored in the snowflake
15
+ */
16
+ workerId: number;
17
+ /**
18
+ * The process id stored in the snowflake
19
+ */
20
+ processId: number;
21
+ /**
22
+ * The increment stored in the snowflake
23
+ */
24
+ increment: number;
25
+ /**
26
+ * The epoch to use in the snowflake
27
+ */
28
+ epoch: number;
29
+ }
30
+ /**
31
+ * Options for Snowflake
32
+ */
33
+ interface SnowflakeOptions {
34
+ /**
35
+ * Timestamp or date of the snowflake to generate
36
+ */
37
+ epoch: number | bigint | Date;
38
+ /**
39
+ * The increment to use
40
+ * @default 0
41
+ * @remark keep in mind that this number is auto-incremented between generate calls
42
+ */
43
+ increment?: number | bigint;
44
+ /**
45
+ * The worker ID to use, will be truncated to 5 bits (0-31)
46
+ * @default 0
47
+ */
48
+ workerId?: number | bigint;
49
+ /**
50
+ * The process ID to use, will be truncated to 5 bits (0-31)
51
+ * @default 1
52
+ */
53
+ processId?: number | bigint;
54
+ }
55
+ /**
56
+ * The maximum value the `workerId` field accepts in snowflakes.
57
+ */
58
+ declare var MAX_WORKER_ID: number;
59
+ /**
60
+ * The maximum value the `processId` field accepts in snowflakes.
61
+ */
62
+ declare var MAX_PROCESS_ID: number;
63
+ /**
64
+ * The maximum value the `increment` field accepts in snowflakes.
65
+ */
66
+ declare var MAX_INCREMENT: number;
67
+ /**
68
+ * A class for generating and deconstructing Twitter snowflakes.
69
+ *
70
+ * A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake}
71
+ * is a 64-bit unsigned integer with 4 fields that have a fixed epoch value.
72
+ *
73
+ * If we have a snowflake `266241948824764416` we can represent it as binary:
74
+ * ```
75
+ * 64 22 17 12 0
76
+ * 000000111011000111100001101001000101000000 00001 00000 000000000000
77
+ * number of ms since epoch worker pid increment
78
+ * ```
79
+ *
80
+ * @group Main
81
+ */
82
+ declare class Snowflake {
83
+ /**
84
+ * Alias for {@link deconstruct}
85
+ */
86
+ decode: (id: string | bigint | Uint8Array) => DeconstructedSnowflake;
87
+ /**
88
+ * Internal reference of the epoch passed in the constructor
89
+ * @internal
90
+ */
91
+ private readonly _epoch;
92
+ /**
93
+ * Internal incrementor for generating snowflakes
94
+ * @internal
95
+ */
96
+ private _increment;
97
+ /**
98
+ * The process ID that will be used by default in the generate method
99
+ * @internal
100
+ */
101
+ private _processId;
102
+ /**
103
+ * The worker ID that will be used by default in the generate method
104
+ * @internal
105
+ */
106
+ private _workerId;
107
+ /**
108
+ * @internal
109
+ */
110
+ private _buffer;
111
+ /**
112
+ * @param epoch the epoch to use
113
+ */
114
+ constructor(opts: SnowflakeOptions | Date | number | bigint);
115
+ /**
116
+ * The epoch for this snowflake, as a number
117
+ */
118
+ get epoch(): number;
119
+ /**
120
+ * Gets the configured process ID
121
+ */
122
+ get processId(): number;
123
+ /**
124
+ * Sets the process ID that will be used by default for the {@link generate} method
125
+ * @param value The new value, will be masked with `0b11111`
126
+ */
127
+ set processId(value: number | bigint);
128
+ /**
129
+ * Gets the configured worker ID
130
+ */
131
+ get workerId(): number;
132
+ /**
133
+ * Sets the worker ID that will be used by default for the {@link generate} method
134
+ * @param value The new value, will be masked with `0b11111`
135
+ */
136
+ set workerId(value: number | bigint);
137
+ /**
138
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
139
+ */
140
+ generate(timestamp?: Date | number): bigint;
141
+ /**
142
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
143
+ *
144
+ * ⚠️ Returns a reference to the **same** internal `Uint8Array` instance.
145
+ * Its contents may be overwritten on the next ID generation call.
146
+ *
147
+ * This method is intended for high-performance scenarios where you
148
+ * immediately transform the buffer (e.g., to base62) before calling again.
149
+ * Avoid storing or mutating the returned buffer directly.
150
+ */
151
+ generateBufferUnsafe(timestamp?: Date | number): Uint8Array;
152
+ /**
153
+ * Generates a snowflake given an epoch and optionally a timestamp
154
+ * @example
155
+ * ```typescript
156
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
157
+ * const snowflake = new Snowflake({ epoch }).generate();
158
+ * ```
159
+ * @returns A unique snowflake as Uint8Array
160
+ */
161
+ generateBuffer(timestamp?: Date | number): Uint8Array;
162
+ /**
163
+ * Deconstructs a snowflake given a snowflake ID
164
+ * @param id the snowflake to deconstruct
165
+ * @returns a deconstructed snowflake
166
+ * @example
167
+ * ```typescript
168
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
169
+ * const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');
170
+ * ```
171
+ */
172
+ deconstruct(id: string | bigint | Uint8Array): DeconstructedSnowflake;
173
+ /**
174
+ * Retrieves the timestamp field's value from a snowflake.
175
+ * @param id The snowflake to get the timestamp value from.
176
+ * @returns The UNIX timestamp that is stored in `id`.
177
+ */
178
+ timestampFrom(id: string | bigint | Uint8Array): number;
179
+ /**
180
+ * Returns a number indicating whether a reference snowflake comes before, or after, or is same as the given
181
+ * snowflake in sort order.
182
+ * @param a The first snowflake to compare.
183
+ * @param b The second snowflake to compare.
184
+ * @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.
185
+ */
186
+ static compare(a: string | bigint | Uint8Array, b: string | bigint | Uint8Array): -1 | 0 | 1;
187
+ /**
188
+ * Parse value as Uint8Array buffer
189
+ */
190
+ static bufferFrom(value: bigint | string): Uint8Array;
191
+ }
192
+
193
+ export { type DeconstructedSnowflake, MAX_INCREMENT, MAX_PROCESS_ID, MAX_WORKER_ID, Snowflake, type SnowflakeOptions };
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Object returned by Snowflake#deconstruct
3
+ */
4
+ interface DeconstructedSnowflake {
5
+ /**
6
+ * The id as a number
7
+ */
8
+ id: bigint;
9
+ /**
10
+ * The timestamp stored in the snowflake
11
+ */
12
+ timestamp: number;
13
+ /**
14
+ * The worker id stored in the snowflake
15
+ */
16
+ workerId: number;
17
+ /**
18
+ * The process id stored in the snowflake
19
+ */
20
+ processId: number;
21
+ /**
22
+ * The increment stored in the snowflake
23
+ */
24
+ increment: number;
25
+ /**
26
+ * The epoch to use in the snowflake
27
+ */
28
+ epoch: number;
29
+ }
30
+ /**
31
+ * Options for Snowflake
32
+ */
33
+ interface SnowflakeOptions {
34
+ /**
35
+ * Timestamp or date of the snowflake to generate
36
+ */
37
+ epoch: number | bigint | Date;
38
+ /**
39
+ * The increment to use
40
+ * @default 0
41
+ * @remark keep in mind that this number is auto-incremented between generate calls
42
+ */
43
+ increment?: number | bigint;
44
+ /**
45
+ * The worker ID to use, will be truncated to 5 bits (0-31)
46
+ * @default 0
47
+ */
48
+ workerId?: number | bigint;
49
+ /**
50
+ * The process ID to use, will be truncated to 5 bits (0-31)
51
+ * @default 1
52
+ */
53
+ processId?: number | bigint;
54
+ }
55
+ /**
56
+ * The maximum value the `workerId` field accepts in snowflakes.
57
+ */
58
+ declare var MAX_WORKER_ID: number;
59
+ /**
60
+ * The maximum value the `processId` field accepts in snowflakes.
61
+ */
62
+ declare var MAX_PROCESS_ID: number;
63
+ /**
64
+ * The maximum value the `increment` field accepts in snowflakes.
65
+ */
66
+ declare var MAX_INCREMENT: number;
67
+ /**
68
+ * A class for generating and deconstructing Twitter snowflakes.
69
+ *
70
+ * A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake}
71
+ * is a 64-bit unsigned integer with 4 fields that have a fixed epoch value.
72
+ *
73
+ * If we have a snowflake `266241948824764416` we can represent it as binary:
74
+ * ```
75
+ * 64 22 17 12 0
76
+ * 000000111011000111100001101001000101000000 00001 00000 000000000000
77
+ * number of ms since epoch worker pid increment
78
+ * ```
79
+ *
80
+ * @group Main
81
+ */
82
+ declare class Snowflake {
83
+ /**
84
+ * Alias for {@link deconstruct}
85
+ */
86
+ decode: (id: string | bigint | Uint8Array) => DeconstructedSnowflake;
87
+ /**
88
+ * Internal reference of the epoch passed in the constructor
89
+ * @internal
90
+ */
91
+ private readonly _epoch;
92
+ /**
93
+ * Internal incrementor for generating snowflakes
94
+ * @internal
95
+ */
96
+ private _increment;
97
+ /**
98
+ * The process ID that will be used by default in the generate method
99
+ * @internal
100
+ */
101
+ private _processId;
102
+ /**
103
+ * The worker ID that will be used by default in the generate method
104
+ * @internal
105
+ */
106
+ private _workerId;
107
+ /**
108
+ * @internal
109
+ */
110
+ private _buffer;
111
+ /**
112
+ * @param epoch the epoch to use
113
+ */
114
+ constructor(opts: SnowflakeOptions | Date | number | bigint);
115
+ /**
116
+ * The epoch for this snowflake, as a number
117
+ */
118
+ get epoch(): number;
119
+ /**
120
+ * Gets the configured process ID
121
+ */
122
+ get processId(): number;
123
+ /**
124
+ * Sets the process ID that will be used by default for the {@link generate} method
125
+ * @param value The new value, will be masked with `0b11111`
126
+ */
127
+ set processId(value: number | bigint);
128
+ /**
129
+ * Gets the configured worker ID
130
+ */
131
+ get workerId(): number;
132
+ /**
133
+ * Sets the worker ID that will be used by default for the {@link generate} method
134
+ * @param value The new value, will be masked with `0b11111`
135
+ */
136
+ set workerId(value: number | bigint);
137
+ /**
138
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
139
+ */
140
+ generate(timestamp?: Date | number): bigint;
141
+ /**
142
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
143
+ *
144
+ * ⚠️ Returns a reference to the **same** internal `Uint8Array` instance.
145
+ * Its contents may be overwritten on the next ID generation call.
146
+ *
147
+ * This method is intended for high-performance scenarios where you
148
+ * immediately transform the buffer (e.g., to base62) before calling again.
149
+ * Avoid storing or mutating the returned buffer directly.
150
+ */
151
+ generateBufferUnsafe(timestamp?: Date | number): Uint8Array;
152
+ /**
153
+ * Generates a snowflake given an epoch and optionally a timestamp
154
+ * @example
155
+ * ```typescript
156
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
157
+ * const snowflake = new Snowflake({ epoch }).generate();
158
+ * ```
159
+ * @returns A unique snowflake as Uint8Array
160
+ */
161
+ generateBuffer(timestamp?: Date | number): Uint8Array;
162
+ /**
163
+ * Deconstructs a snowflake given a snowflake ID
164
+ * @param id the snowflake to deconstruct
165
+ * @returns a deconstructed snowflake
166
+ * @example
167
+ * ```typescript
168
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
169
+ * const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');
170
+ * ```
171
+ */
172
+ deconstruct(id: string | bigint | Uint8Array): DeconstructedSnowflake;
173
+ /**
174
+ * Retrieves the timestamp field's value from a snowflake.
175
+ * @param id The snowflake to get the timestamp value from.
176
+ * @returns The UNIX timestamp that is stored in `id`.
177
+ */
178
+ timestampFrom(id: string | bigint | Uint8Array): number;
179
+ /**
180
+ * Returns a number indicating whether a reference snowflake comes before, or after, or is same as the given
181
+ * snowflake in sort order.
182
+ * @param a The first snowflake to compare.
183
+ * @param b The second snowflake to compare.
184
+ * @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.
185
+ */
186
+ static compare(a: string | bigint | Uint8Array, b: string | bigint | Uint8Array): -1 | 0 | 1;
187
+ /**
188
+ * Parse value as Uint8Array buffer
189
+ */
190
+ static bufferFrom(value: bigint | string): Uint8Array;
191
+ }
192
+
193
+ export { type DeconstructedSnowflake, MAX_INCREMENT, MAX_PROCESS_ID, MAX_WORKER_ID, Snowflake, type SnowflakeOptions };
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Object returned by Snowflake#deconstruct
3
+ */
4
+ interface DeconstructedSnowflake {
5
+ /**
6
+ * The id as a number
7
+ */
8
+ id: bigint;
9
+ /**
10
+ * The timestamp stored in the snowflake
11
+ */
12
+ timestamp: number;
13
+ /**
14
+ * The worker id stored in the snowflake
15
+ */
16
+ workerId: number;
17
+ /**
18
+ * The process id stored in the snowflake
19
+ */
20
+ processId: number;
21
+ /**
22
+ * The increment stored in the snowflake
23
+ */
24
+ increment: number;
25
+ /**
26
+ * The epoch to use in the snowflake
27
+ */
28
+ epoch: number;
29
+ }
30
+ /**
31
+ * Options for Snowflake
32
+ */
33
+ interface SnowflakeOptions {
34
+ /**
35
+ * Timestamp or date of the snowflake to generate
36
+ */
37
+ epoch: number | bigint | Date;
38
+ /**
39
+ * The increment to use
40
+ * @default 0
41
+ * @remark keep in mind that this number is auto-incremented between generate calls
42
+ */
43
+ increment?: number | bigint;
44
+ /**
45
+ * The worker ID to use, will be truncated to 5 bits (0-31)
46
+ * @default 0
47
+ */
48
+ workerId?: number | bigint;
49
+ /**
50
+ * The process ID to use, will be truncated to 5 bits (0-31)
51
+ * @default 1
52
+ */
53
+ processId?: number | bigint;
54
+ }
55
+ /**
56
+ * The maximum value the `workerId` field accepts in snowflakes.
57
+ */
58
+ declare var MAX_WORKER_ID: number;
59
+ /**
60
+ * The maximum value the `processId` field accepts in snowflakes.
61
+ */
62
+ declare var MAX_PROCESS_ID: number;
63
+ /**
64
+ * The maximum value the `increment` field accepts in snowflakes.
65
+ */
66
+ declare var MAX_INCREMENT: number;
67
+ /**
68
+ * A class for generating and deconstructing Twitter snowflakes.
69
+ *
70
+ * A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake}
71
+ * is a 64-bit unsigned integer with 4 fields that have a fixed epoch value.
72
+ *
73
+ * If we have a snowflake `266241948824764416` we can represent it as binary:
74
+ * ```
75
+ * 64 22 17 12 0
76
+ * 000000111011000111100001101001000101000000 00001 00000 000000000000
77
+ * number of ms since epoch worker pid increment
78
+ * ```
79
+ *
80
+ * @group Main
81
+ */
82
+ declare class Snowflake {
83
+ /**
84
+ * Alias for {@link deconstruct}
85
+ */
86
+ decode: (id: string | bigint | Uint8Array) => DeconstructedSnowflake;
87
+ /**
88
+ * Internal reference of the epoch passed in the constructor
89
+ * @internal
90
+ */
91
+ private readonly _epoch;
92
+ /**
93
+ * Internal incrementor for generating snowflakes
94
+ * @internal
95
+ */
96
+ private _increment;
97
+ /**
98
+ * The process ID that will be used by default in the generate method
99
+ * @internal
100
+ */
101
+ private _processId;
102
+ /**
103
+ * The worker ID that will be used by default in the generate method
104
+ * @internal
105
+ */
106
+ private _workerId;
107
+ /**
108
+ * @internal
109
+ */
110
+ private _buffer;
111
+ /**
112
+ * @param epoch the epoch to use
113
+ */
114
+ constructor(opts: SnowflakeOptions | Date | number | bigint);
115
+ /**
116
+ * The epoch for this snowflake, as a number
117
+ */
118
+ get epoch(): number;
119
+ /**
120
+ * Gets the configured process ID
121
+ */
122
+ get processId(): number;
123
+ /**
124
+ * Sets the process ID that will be used by default for the {@link generate} method
125
+ * @param value The new value, will be masked with `0b11111`
126
+ */
127
+ set processId(value: number | bigint);
128
+ /**
129
+ * Gets the configured worker ID
130
+ */
131
+ get workerId(): number;
132
+ /**
133
+ * Sets the worker ID that will be used by default for the {@link generate} method
134
+ * @param value The new value, will be masked with `0b11111`
135
+ */
136
+ set workerId(value: number | bigint);
137
+ /**
138
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
139
+ */
140
+ generate(timestamp?: Date | number): bigint;
141
+ /**
142
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
143
+ *
144
+ * ⚠️ Returns a reference to the **same** internal `Uint8Array` instance.
145
+ * Its contents may be overwritten on the next ID generation call.
146
+ *
147
+ * This method is intended for high-performance scenarios where you
148
+ * immediately transform the buffer (e.g., to base62) before calling again.
149
+ * Avoid storing or mutating the returned buffer directly.
150
+ */
151
+ generateBufferUnsafe(timestamp?: Date | number): Uint8Array;
152
+ /**
153
+ * Generates a snowflake given an epoch and optionally a timestamp
154
+ * @example
155
+ * ```typescript
156
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
157
+ * const snowflake = new Snowflake({ epoch }).generate();
158
+ * ```
159
+ * @returns A unique snowflake as Uint8Array
160
+ */
161
+ generateBuffer(timestamp?: Date | number): Uint8Array;
162
+ /**
163
+ * Deconstructs a snowflake given a snowflake ID
164
+ * @param id the snowflake to deconstruct
165
+ * @returns a deconstructed snowflake
166
+ * @example
167
+ * ```typescript
168
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
169
+ * const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');
170
+ * ```
171
+ */
172
+ deconstruct(id: string | bigint | Uint8Array): DeconstructedSnowflake;
173
+ /**
174
+ * Retrieves the timestamp field's value from a snowflake.
175
+ * @param id The snowflake to get the timestamp value from.
176
+ * @returns The UNIX timestamp that is stored in `id`.
177
+ */
178
+ timestampFrom(id: string | bigint | Uint8Array): number;
179
+ /**
180
+ * Returns a number indicating whether a reference snowflake comes before, or after, or is same as the given
181
+ * snowflake in sort order.
182
+ * @param a The first snowflake to compare.
183
+ * @param b The second snowflake to compare.
184
+ * @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.
185
+ */
186
+ static compare(a: string | bigint | Uint8Array, b: string | bigint | Uint8Array): -1 | 0 | 1;
187
+ /**
188
+ * Parse value as Uint8Array buffer
189
+ */
190
+ static bufferFrom(value: bigint | string): Uint8Array;
191
+ }
192
+
193
+ export { type DeconstructedSnowflake, MAX_INCREMENT, MAX_PROCESS_ID, MAX_WORKER_ID, Snowflake, type SnowflakeOptions };
package/dist/index.mjs ADDED
@@ -0,0 +1,225 @@
1
+ import { isDate, isNumber, timestampMs, isBigInt, bigIntBytes, isString, bigIntFromBytes } from '@andrew_l/toolkit';
2
+
3
+ var MAX_WORKER_ID = 31;
4
+ var MAX_PROCESS_ID = 31;
5
+ var MAX_INCREMENT = 4095;
6
+ class Snowflake {
7
+ /**
8
+ * Alias for {@link deconstruct}
9
+ */
10
+ decode = this.deconstruct;
11
+ /**
12
+ * Internal reference of the epoch passed in the constructor
13
+ * @internal
14
+ */
15
+ _epoch;
16
+ /**
17
+ * Internal incrementor for generating snowflakes
18
+ * @internal
19
+ */
20
+ _increment = 0;
21
+ /**
22
+ * The process ID that will be used by default in the generate method
23
+ * @internal
24
+ */
25
+ _processId = 1;
26
+ /**
27
+ * The worker ID that will be used by default in the generate method
28
+ * @internal
29
+ */
30
+ _workerId = 0;
31
+ /**
32
+ * @internal
33
+ */
34
+ _buffer;
35
+ /**
36
+ * @param epoch the epoch to use
37
+ */
38
+ constructor(opts) {
39
+ if (isDate(opts) || isNumber(opts)) {
40
+ this._epoch = timestampMs(opts);
41
+ } else if (isBigInt(opts)) {
42
+ this._epoch = timestampMs(Number(opts));
43
+ } else {
44
+ const { increment = 0, processId = 1, workerId = 0, epoch } = opts;
45
+ this._epoch = timestampMs(isBigInt(epoch) ? Number(epoch) : epoch);
46
+ this.workerId = workerId;
47
+ this.processId = processId;
48
+ this._increment = Number(increment) & MAX_INCREMENT;
49
+ }
50
+ this._buffer = new Uint8Array(8);
51
+ }
52
+ /**
53
+ * The epoch for this snowflake, as a number
54
+ */
55
+ get epoch() {
56
+ return this._epoch;
57
+ }
58
+ /**
59
+ * Gets the configured process ID
60
+ */
61
+ get processId() {
62
+ return this._processId;
63
+ }
64
+ /**
65
+ * Sets the process ID that will be used by default for the {@link generate} method
66
+ * @param value The new value, will be masked with `0b11111`
67
+ */
68
+ set processId(value) {
69
+ this._processId = Number(value) & MAX_PROCESS_ID;
70
+ }
71
+ /**
72
+ * Gets the configured worker ID
73
+ */
74
+ get workerId() {
75
+ return this._workerId;
76
+ }
77
+ /**
78
+ * Sets the worker ID that will be used by default for the {@link generate} method
79
+ * @param value The new value, will be masked with `0b11111`
80
+ */
81
+ set workerId(value) {
82
+ this._workerId = Number(value) & MAX_WORKER_ID;
83
+ }
84
+ /**
85
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
86
+ */
87
+ generate(timestamp = Date.now()) {
88
+ if (timestamp instanceof Date) timestamp = timestamp.getTime();
89
+ if (!isNumber(timestamp)) {
90
+ throw new Error(
91
+ `"timestamp" argument must be a number or Date (received ${typeof timestamp})`
92
+ );
93
+ }
94
+ var increment = this._increment;
95
+ this._increment = this._increment + 1 & MAX_INCREMENT;
96
+ return BigInt(timestamp - this._epoch) << 22n | BigInt(this._workerId & MAX_WORKER_ID) << 17n | BigInt(this._processId & MAX_PROCESS_ID) << 12n | BigInt(increment & MAX_INCREMENT);
97
+ }
98
+ /**
99
+ * Generates a Snowflake ID as a `Uint8Array` buffer.
100
+ *
101
+ * ⚠️ Returns a reference to the **same** internal `Uint8Array` instance.
102
+ * Its contents may be overwritten on the next ID generation call.
103
+ *
104
+ * This method is intended for high-performance scenarios where you
105
+ * immediately transform the buffer (e.g., to base62) before calling again.
106
+ * Avoid storing or mutating the returned buffer directly.
107
+ */
108
+ generateBufferUnsafe(timestamp = Date.now()) {
109
+ if (timestamp instanceof Date) timestamp = timestamp.getTime();
110
+ if (!isNumber(timestamp)) {
111
+ throw new Error(
112
+ `"timestamp" argument must be a number or Date (received ${typeof timestamp})`
113
+ );
114
+ }
115
+ var increment = this._increment;
116
+ this._increment = this._increment + 1 & MAX_INCREMENT;
117
+ var timestampDelta = timestamp - this._epoch;
118
+ var timestampHigh = Math.floor(timestampDelta / 4294967295);
119
+ var timestampLow = timestampDelta >>> 0;
120
+ var high32 = (timestampHigh << 22 | timestampLow >>> 10) >>> 0;
121
+ var low32 = (timestampLow << 22 | this._workerId << 17 | this._processId << 12 | increment & MAX_INCREMENT) >>> 0;
122
+ var buffer = this._buffer;
123
+ buffer[0] = high32 >>> 24;
124
+ buffer[1] = high32 >>> 16;
125
+ buffer[2] = high32 >>> 8;
126
+ buffer[3] = high32;
127
+ buffer[4] = low32 >>> 24;
128
+ buffer[5] = low32 >>> 16;
129
+ buffer[6] = low32 >>> 8;
130
+ buffer[7] = low32;
131
+ return buffer;
132
+ }
133
+ /**
134
+ * Generates a snowflake given an epoch and optionally a timestamp
135
+ * @example
136
+ * ```typescript
137
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
138
+ * const snowflake = new Snowflake({ epoch }).generate();
139
+ * ```
140
+ * @returns A unique snowflake as Uint8Array
141
+ */
142
+ generateBuffer(timestamp = Date.now()) {
143
+ this.generateBufferUnsafe(timestamp);
144
+ return new Uint8Array(this._buffer);
145
+ }
146
+ /**
147
+ * Deconstructs a snowflake given a snowflake ID
148
+ * @param id the snowflake to deconstruct
149
+ * @returns a deconstructed snowflake
150
+ * @example
151
+ * ```typescript
152
+ * const epoch = new Date('2000-01-01T00:00:00.000Z');
153
+ * const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');
154
+ * ```
155
+ */
156
+ deconstruct(id) {
157
+ var high32, low32;
158
+ if (id instanceof Uint8Array) {
159
+ high32 = (id[0] << 24 | id[1] << 16 | id[2] << 8 | id[3]) >>> 0;
160
+ low32 = (id[4] << 24 | id[5] << 16 | id[6] << 8 | id[7]) >>> 0;
161
+ } else if (isBigInt(id)) {
162
+ return this.deconstruct(bigIntBytes(id));
163
+ } else {
164
+ return this.deconstruct(bigIntBytes(BigInt(id)));
165
+ }
166
+ return {
167
+ id: BigInt(high32) * 0x100000000n + BigInt(low32),
168
+ timestamp: high32 * 1024 + (low32 >>> 22) + this._epoch,
169
+ workerId: low32 >>> 17 & MAX_WORKER_ID,
170
+ processId: low32 >>> 12 & MAX_PROCESS_ID,
171
+ increment: low32 & MAX_INCREMENT,
172
+ epoch: this._epoch
173
+ };
174
+ }
175
+ /**
176
+ * Retrieves the timestamp field's value from a snowflake.
177
+ * @param id The snowflake to get the timestamp value from.
178
+ * @returns The UNIX timestamp that is stored in `id`.
179
+ */
180
+ timestampFrom(id) {
181
+ if (isString(id) || isBigInt(id)) {
182
+ return this.timestampFrom(Snowflake.bufferFrom(id));
183
+ }
184
+ var high32 = (id[0] << 24 | id[1] << 16 | id[2] << 8 | id[3]) >>> 0;
185
+ var low32 = (id[4] << 24 | id[5] << 16 | id[6] << 8 | id[7]) >>> 0;
186
+ return high32 * 1024 + (low32 >>> 22) + this._epoch;
187
+ }
188
+ /**
189
+ * Returns a number indicating whether a reference snowflake comes before, or after, or is same as the given
190
+ * snowflake in sort order.
191
+ * @param a The first snowflake to compare.
192
+ * @param b The second snowflake to compare.
193
+ * @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.
194
+ */
195
+ static compare(a, b) {
196
+ if (isString(a)) {
197
+ a = BigInt(a);
198
+ } else if (a instanceof Uint8Array) {
199
+ a = bigIntFromBytes(a);
200
+ }
201
+ if (isString(b)) {
202
+ b = BigInt(b);
203
+ } else if (b instanceof Uint8Array) {
204
+ b = bigIntFromBytes(b);
205
+ }
206
+ return a === b ? 0 : a < b ? -1 : 1;
207
+ }
208
+ /**
209
+ * Parse value as Uint8Array buffer
210
+ */
211
+ static bufferFrom(value) {
212
+ if (isString(value)) value = BigInt(value);
213
+ var buf = bigIntBytes(value);
214
+ var bufSize = buf.byteLength;
215
+ if (buf.byteLength < 8) {
216
+ var buf2 = new Uint8Array(8);
217
+ buf2.set(buf, 8 - bufSize);
218
+ buf = buf2;
219
+ }
220
+ return buf;
221
+ }
222
+ }
223
+
224
+ export { MAX_INCREMENT, MAX_PROCESS_ID, MAX_WORKER_ID, Snowflake };
225
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/Snowflake.ts"],"sourcesContent":["/**\n * Based on: https://github.com/sapphiredev/utilities/blob/main/packages/snowflake/src/lib/Snowflake.ts\n */\nimport {\n bigIntBytes,\n bigIntFromBytes,\n isBigInt,\n isDate,\n isNumber,\n isString,\n timestampMs,\n} from '@andrew_l/toolkit';\n\n/**\n * Object returned by Snowflake#deconstruct\n */\nexport interface DeconstructedSnowflake {\n /**\n * The id as a number\n */\n id: bigint;\n\n /**\n * The timestamp stored in the snowflake\n */\n timestamp: number;\n\n /**\n * The worker id stored in the snowflake\n */\n workerId: number;\n\n /**\n * The process id stored in the snowflake\n */\n processId: number;\n\n /**\n * The increment stored in the snowflake\n */\n increment: number;\n\n /**\n * The epoch to use in the snowflake\n */\n epoch: number;\n}\n\n/**\n * Options for Snowflake\n */\nexport interface SnowflakeOptions {\n /**\n * Timestamp or date of the snowflake to generate\n */\n epoch: number | bigint | Date;\n\n /**\n * The increment to use\n * @default 0\n * @remark keep in mind that this number is auto-incremented between generate calls\n */\n increment?: number | bigint;\n\n /**\n * The worker ID to use, will be truncated to 5 bits (0-31)\n * @default 0\n */\n workerId?: number | bigint;\n\n /**\n * The process ID to use, will be truncated to 5 bits (0-31)\n * @default 1\n */\n processId?: number | bigint;\n}\n\n/**\n * The maximum value the `workerId` field accepts in snowflakes.\n */\nexport var MAX_WORKER_ID = 0x1f;\n\n/**\n * The maximum value the `processId` field accepts in snowflakes.\n */\nexport var MAX_PROCESS_ID = 0x1f;\n\n/**\n * The maximum value the `increment` field accepts in snowflakes.\n */\nexport var MAX_INCREMENT = 0xfff;\n\n/**\n * A class for generating and deconstructing Twitter snowflakes.\n *\n * A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake}\n * is a 64-bit unsigned integer with 4 fields that have a fixed epoch value.\n *\n * If we have a snowflake `266241948824764416` we can represent it as binary:\n * ```\n * 64 22 17 12 0\n * 000000111011000111100001101001000101000000 00001 00000 000000000000\n * number of ms since epoch worker pid increment\n * ```\n *\n * @group Main\n */\nexport class Snowflake {\n /**\n * Alias for {@link deconstruct}\n */\n public decode = this.deconstruct;\n\n /**\n * Internal reference of the epoch passed in the constructor\n * @internal\n */\n private readonly _epoch: number;\n\n /**\n * Internal incrementor for generating snowflakes\n * @internal\n */\n private _increment = 0;\n\n /**\n * The process ID that will be used by default in the generate method\n * @internal\n */\n private _processId = 1;\n\n /**\n * The worker ID that will be used by default in the generate method\n * @internal\n */\n private _workerId = 0;\n\n /**\n * @internal\n */\n private _buffer: Uint8Array;\n\n /**\n * @param epoch the epoch to use\n */\n public constructor(opts: SnowflakeOptions | Date | number | bigint) {\n if (isDate(opts) || isNumber(opts)) {\n this._epoch = timestampMs(opts);\n } else if (isBigInt(opts)) {\n this._epoch = timestampMs(Number(opts));\n } else {\n const { increment = 0, processId = 1, workerId = 0, epoch } = opts;\n this._epoch = timestampMs(isBigInt(epoch) ? Number(epoch) : epoch);\n this.workerId = workerId;\n this.processId = processId;\n this._increment = Number(increment) & MAX_INCREMENT;\n }\n\n this._buffer = new Uint8Array(8);\n }\n\n /**\n * The epoch for this snowflake, as a number\n */\n public get epoch(): number {\n return this._epoch;\n }\n\n /**\n * Gets the configured process ID\n */\n public get processId(): number {\n return this._processId;\n }\n\n /**\n * Sets the process ID that will be used by default for the {@link generate} method\n * @param value The new value, will be masked with `0b11111`\n */\n public set processId(value: number | bigint) {\n this._processId = Number(value) & MAX_PROCESS_ID;\n }\n\n /**\n * Gets the configured worker ID\n */\n public get workerId(): number {\n return this._workerId;\n }\n\n /**\n * Sets the worker ID that will be used by default for the {@link generate} method\n * @param value The new value, will be masked with `0b11111`\n */\n public set workerId(value: number | bigint) {\n this._workerId = Number(value) & MAX_WORKER_ID;\n }\n\n /**\n * Generates a Snowflake ID as a `Uint8Array` buffer.\n */\n public generate(timestamp: Date | number = Date.now()): bigint {\n if (timestamp instanceof Date) timestamp = timestamp.getTime();\n if (!isNumber(timestamp)) {\n throw new Error(\n `\"timestamp\" argument must be a number or Date (received ${typeof timestamp})`,\n );\n }\n\n var increment = this._increment;\n this._increment = (this._increment + 1) & MAX_INCREMENT;\n\n return (\n (BigInt(timestamp - this._epoch) << 22n) |\n (BigInt(this._workerId & MAX_WORKER_ID) << 17n) |\n (BigInt(this._processId & MAX_PROCESS_ID) << 12n) |\n BigInt(increment & MAX_INCREMENT)\n );\n }\n\n /**\n * Generates a Snowflake ID as a `Uint8Array` buffer.\n *\n * ⚠️ Returns a reference to the **same** internal `Uint8Array` instance.\n * Its contents may be overwritten on the next ID generation call.\n *\n * This method is intended for high-performance scenarios where you\n * immediately transform the buffer (e.g., to base62) before calling again.\n * Avoid storing or mutating the returned buffer directly.\n */\n public generateBufferUnsafe(timestamp: Date | number = Date.now()) {\n if (timestamp instanceof Date) timestamp = timestamp.getTime();\n if (!isNumber(timestamp)) {\n throw new Error(\n `\"timestamp\" argument must be a number or Date (received ${typeof timestamp})`,\n );\n }\n\n var increment = this._increment;\n this._increment = (this._increment + 1) & MAX_INCREMENT;\n\n // Calculate the timestamp delta\n var timestampDelta = timestamp - this._epoch;\n\n // Split into 32-bit parts for bitwise operations\n var timestampHigh = Math.floor(timestampDelta / 0xffffffff);\n var timestampLow = timestampDelta >>> 0;\n\n var high32 = ((timestampHigh << 22) | (timestampLow >>> 10)) >>> 0;\n var low32 =\n ((timestampLow << 22) |\n (this._workerId << 17) |\n (this._processId << 12) |\n (increment & MAX_INCREMENT)) >>>\n 0;\n\n var buffer = this._buffer;\n\n buffer[0] = high32 >>> 24;\n buffer[1] = high32 >>> 16;\n buffer[2] = high32 >>> 8;\n buffer[3] = high32;\n buffer[4] = low32 >>> 24;\n buffer[5] = low32 >>> 16;\n buffer[6] = low32 >>> 8;\n buffer[7] = low32;\n\n return buffer;\n }\n\n /**\n * Generates a snowflake given an epoch and optionally a timestamp\n * @example\n * ```typescript\n * const epoch = new Date('2000-01-01T00:00:00.000Z');\n * const snowflake = new Snowflake({ epoch }).generate();\n * ```\n * @returns A unique snowflake as Uint8Array\n */\n public generateBuffer(timestamp: Date | number = Date.now()) {\n this.generateBufferUnsafe(timestamp);\n return new Uint8Array(this._buffer);\n }\n\n /**\n * Deconstructs a snowflake given a snowflake ID\n * @param id the snowflake to deconstruct\n * @returns a deconstructed snowflake\n * @example\n * ```typescript\n * const epoch = new Date('2000-01-01T00:00:00.000Z');\n * const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');\n * ```\n */\n public deconstruct(id: string | bigint | Uint8Array): DeconstructedSnowflake {\n var high32: number, low32: number;\n\n if (id instanceof Uint8Array) {\n // Convert from Uint8Array\n high32 = ((id[0] << 24) | (id[1] << 16) | (id[2] << 8) | id[3]) >>> 0;\n low32 = ((id[4] << 24) | (id[5] << 16) | (id[6] << 8) | id[7]) >>> 0;\n } else if (isBigInt(id)) {\n return this.deconstruct(bigIntBytes(id));\n } else {\n // Convert from string\n return this.deconstruct(bigIntBytes(BigInt(id)));\n }\n\n return {\n id: BigInt(high32) * 0x100000000n + BigInt(low32),\n timestamp: high32 * 0x400 + (low32 >>> 22) + this._epoch,\n workerId: (low32 >>> 17) & MAX_WORKER_ID,\n processId: (low32 >>> 12) & MAX_PROCESS_ID,\n increment: low32 & MAX_INCREMENT,\n epoch: this._epoch,\n };\n }\n\n /**\n * Retrieves the timestamp field's value from a snowflake.\n * @param id The snowflake to get the timestamp value from.\n * @returns The UNIX timestamp that is stored in `id`.\n */\n public timestampFrom(id: string | bigint | Uint8Array): number {\n if (isString(id) || isBigInt(id)) {\n return this.timestampFrom(Snowflake.bufferFrom(id));\n }\n\n var high32 = ((id[0] << 24) | (id[1] << 16) | (id[2] << 8) | id[3]) >>> 0;\n var low32 = ((id[4] << 24) | (id[5] << 16) | (id[6] << 8) | id[7]) >>> 0;\n\n return high32 * 0x400 + (low32 >>> 22) + this._epoch;\n }\n\n /**\n * Returns a number indicating whether a reference snowflake comes before, or after, or is same as the given\n * snowflake in sort order.\n * @param a The first snowflake to compare.\n * @param b The second snowflake to compare.\n * @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.\n */\n public static compare(\n a: string | bigint | Uint8Array,\n b: string | bigint | Uint8Array,\n ): -1 | 0 | 1 {\n if (isString(a)) {\n a = BigInt(a);\n } else if (a instanceof Uint8Array) {\n a = bigIntFromBytes(a);\n }\n\n if (isString(b)) {\n b = BigInt(b);\n } else if (b instanceof Uint8Array) {\n b = bigIntFromBytes(b);\n }\n\n return a === b ? 0 : a < b ? -1 : 1;\n }\n\n /**\n * Parse value as Uint8Array buffer\n */\n public static bufferFrom(value: bigint | string): Uint8Array {\n if (isString(value)) value = BigInt(value);\n\n var buf = bigIntBytes(value);\n var bufSize = buf.byteLength;\n\n // Add padding\n if (buf.byteLength < 8) {\n var buf2 = new Uint8Array(8);\n buf2.set(buf, 8 - bufSize);\n buf = buf2;\n }\n\n return buf;\n }\n}\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@andrew_l/snowflake",
3
+ "version": "0.2.20",
4
+ "description": "Another implementation of snowflake id generator.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "keywords": [
8
+ "snowflake",
9
+ "binary",
10
+ "buffer",
11
+ "serialization",
12
+ "deserialization"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/men232/toolkit.git",
17
+ "directory": "packages/snowflake"
18
+ },
19
+ "exports": {
20
+ ".": {
21
+ "import": "./dist/index.mjs",
22
+ "require": "./dist/index.cjs"
23
+ }
24
+ },
25
+ "main": "./dist/index.cjs",
26
+ "types": "./dist/index.d.ts",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "dependencies": {
31
+ "@andrew_l/toolkit": "0.2.20"
32
+ },
33
+ "devDependencies": {
34
+ "@sapphire/snowflake": "^3.5.5",
35
+ "@types/node": "22.10.5",
36
+ "typescript": "~5.6.2",
37
+ "unbuild": "3.0.0-rc.11",
38
+ "vitest": "^2.1.3"
39
+ },
40
+ "scripts": {
41
+ "build": "unbuild",
42
+ "test": "vitest run --typecheck",
43
+ "test:watch": "vitest watch --typecheck",
44
+ "benchmark": "vitest bench watch ./benchmark",
45
+ "benchmark:watch": "vitest bench watch ./benchmark"
46
+ }
47
+ }