@toolkit-f/snowflake-id 1.0.0 → 1.0.1
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/README.md +632 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/maulik-mk/Snowflake-Id/main/public/image.png" alt="Snowflake ID Logo" width="600" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://www.npmjs.com/package/@toolkit-f/snowflake-id"><img src="https://img.shields.io/npm/v/@toolkit-f/snowflake-id.svg" alt="npm version"></a>
|
|
8
|
+
<a href="https://www.npmjs.com/package/@toolkit-f/snowflake-id"><img src="https://img.shields.io/npm/dm/@toolkit-f/snowflake-id.svg" alt="npm downloads"></a>
|
|
9
|
+
<a href="https://github.com/maulik-mk/Snowflake-Id/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@toolkit-f/snowflake-id.svg" alt="license"></a>
|
|
10
|
+
<img src="https://img.shields.io/badge/TypeScript-Ready-blue.svg" alt="TypeScript">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
A Snowflake ID generator for Node.js • No dependencies • TypeScript support
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
# Snowflake-ID
|
|
18
|
+
|
|
19
|
+
Snowflake IDs are 64-bit unique identifiers. Sortable by time and can be generated across multiple servers without coordination and collision.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
| 41 bits - Timestamp | 10 bits - Machine ID | 12 bits - Sequence |
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
- Generates unique IDs across distributed systems
|
|
28
|
+
- Works with CommonJS and ESM
|
|
29
|
+
- Full TypeScript support
|
|
30
|
+
- Parse IDs to extract timestamp, machine ID, and sequence
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
### npm
|
|
37
|
+
```bash
|
|
38
|
+
npm install @toolkit-f/snowflake-id
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Yarn
|
|
42
|
+
```bash
|
|
43
|
+
yarn add @toolkit-f/snowflake-id
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### pnpm
|
|
47
|
+
```bash
|
|
48
|
+
pnpm add @toolkit-f/snowflake-id
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Bun
|
|
52
|
+
```bash
|
|
53
|
+
bun add @toolkit-f/snowflake-id
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
### Generate IDs
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { SnowflakeGenerator } from '@toolkit-f/snowflake-id';
|
|
64
|
+
|
|
65
|
+
// Create a generator with a unique machine ID (0-1023)
|
|
66
|
+
const generator = new SnowflakeGenerator({ machineId: 1 });
|
|
67
|
+
|
|
68
|
+
// Generate as BigInt
|
|
69
|
+
const id = generator.nextId();
|
|
70
|
+
console.log(id); // 136941813297541120n
|
|
71
|
+
|
|
72
|
+
// Generate as String (recommended for JSON/APIs)
|
|
73
|
+
const idString = generator.nextIdString();
|
|
74
|
+
console.log(idString); // "136941813297541121"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Parse Existing IDs
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { parseSnowflake } from '@toolkit-f/snowflake-id';
|
|
81
|
+
|
|
82
|
+
const parts = parseSnowflake('136941813297545217');
|
|
83
|
+
console.log(parts);
|
|
84
|
+
// {
|
|
85
|
+
// id: 136941813297545217n,
|
|
86
|
+
// timestamp: 2024-01-16T09:09:25.000Z,
|
|
87
|
+
// machineId: 1,
|
|
88
|
+
// sequence: 1
|
|
89
|
+
// }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### CommonJS Support
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
const { SnowflakeGenerator } = require('@toolkit-f/snowflake-id');
|
|
96
|
+
|
|
97
|
+
const generator = new SnowflakeGenerator({ machineId: 1 });
|
|
98
|
+
console.log(generator.nextIdString());
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## API Reference
|
|
104
|
+
|
|
105
|
+
### Core Class: `SnowflakeGenerator`
|
|
106
|
+
|
|
107
|
+
#### Constructor
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
new SnowflakeGenerator(config: SnowflakeConfig)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
| Parameter | Type | Required | Default | Description |
|
|
114
|
+
|-----------|------|----------|---------|-------------|
|
|
115
|
+
| `machineId` | `number` | Yes | - | Unique ID for this machine/worker (0-1023) |
|
|
116
|
+
| `epoch` | `number` | No | `1704067200000` (Jan 1, 2024) | Custom epoch in milliseconds |
|
|
117
|
+
| `clockMoveBackAction` | `'throw'` \| `'wait'` | No | `'throw'` | Behavior when system clock drifts backwards |
|
|
118
|
+
|
|
119
|
+
**Example:**
|
|
120
|
+
```typescript
|
|
121
|
+
import { SnowflakeGenerator } from '@toolkit-f/snowflake-id';
|
|
122
|
+
|
|
123
|
+
const generator = new SnowflakeGenerator({
|
|
124
|
+
machineId: 5,
|
|
125
|
+
epoch: 1609459200000, // Jan 1, 2021
|
|
126
|
+
clockMoveBackAction: 'wait' // Wait instead of throwing error
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
#### `nextId(): bigint`
|
|
133
|
+
|
|
134
|
+
Generates the next unique ID as a `bigint`.
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const generator = new SnowflakeGenerator({ machineId: 1 });
|
|
138
|
+
|
|
139
|
+
console.log(generator.nextId());
|
|
140
|
+
// 136941813297541120n
|
|
141
|
+
|
|
142
|
+
console.log(generator.nextId());
|
|
143
|
+
// 136941813297541121n
|
|
144
|
+
|
|
145
|
+
console.log(generator.nextId());
|
|
146
|
+
// 136941813297545216n
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
#### `nextIdString(): string`
|
|
152
|
+
|
|
153
|
+
Generates the next unique ID as a `string`.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const generator = new SnowflakeGenerator({ machineId: 1 });
|
|
157
|
+
|
|
158
|
+
console.log(generator.nextIdString());
|
|
159
|
+
// "136941813297541120"
|
|
160
|
+
|
|
161
|
+
console.log(generator.nextIdString());
|
|
162
|
+
// "136941813297541121"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
#### `getMachineId(): number`
|
|
168
|
+
|
|
169
|
+
Returns the configured machine ID.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
const generator = new SnowflakeGenerator({ machineId: 42 });
|
|
173
|
+
|
|
174
|
+
console.log(generator.getMachineId());
|
|
175
|
+
// 42
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
#### `getEpoch(): number`
|
|
181
|
+
|
|
182
|
+
Returns the configured epoch timestamp.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
const generator = new SnowflakeGenerator({ machineId: 1 });
|
|
186
|
+
|
|
187
|
+
console.log(generator.getEpoch());
|
|
188
|
+
// 1704067200000
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
#### `getSequence(): number`
|
|
194
|
+
|
|
195
|
+
Returns the current sequence number.
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
const generator = new SnowflakeGenerator({ machineId: 1 });
|
|
199
|
+
|
|
200
|
+
generator.nextId();
|
|
201
|
+
console.log(generator.getSequence());
|
|
202
|
+
// 0
|
|
203
|
+
|
|
204
|
+
generator.nextId();
|
|
205
|
+
console.log(generator.getSequence());
|
|
206
|
+
// 1
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
#### `getLastTimestamp(): number`
|
|
212
|
+
|
|
213
|
+
Returns the timestamp of the last generated ID.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const generator = new SnowflakeGenerator({ machineId: 1 });
|
|
217
|
+
|
|
218
|
+
generator.nextId();
|
|
219
|
+
console.log(generator.getLastTimestamp());
|
|
220
|
+
// 1737017365000
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### Factory Function: `createGenerator`
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
createGenerator(config: SnowflakeConfig): SnowflakeGenerator
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Alternative way to create a generator instance.
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import { createGenerator } from '@toolkit-f/snowflake-id';
|
|
235
|
+
|
|
236
|
+
const generator = createGenerator({ machineId: 1 });
|
|
237
|
+
|
|
238
|
+
console.log(generator.nextId());
|
|
239
|
+
// 136941813297541120n
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
### Utility Functions
|
|
245
|
+
|
|
246
|
+
#### `parseSnowflake(id, epoch?): SnowflakeParts`
|
|
247
|
+
|
|
248
|
+
Deconstructs a Snowflake ID into its components.
|
|
249
|
+
|
|
250
|
+
| Parameter | Type | Required | Default | Description |
|
|
251
|
+
|-----------|------|----------|---------|-------------|
|
|
252
|
+
| `id` | `bigint` \| `string` | Yes | - | The Snowflake ID to parse |
|
|
253
|
+
| `epoch` | `number` | No | `1704067200000` | Custom epoch used during generation |
|
|
254
|
+
|
|
255
|
+
**Returns:** `SnowflakeParts`
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
import { parseSnowflake } from '@toolkit-f/snowflake-id';
|
|
259
|
+
|
|
260
|
+
const parts = parseSnowflake('136941813297545217');
|
|
261
|
+
console.log(parts);
|
|
262
|
+
// {
|
|
263
|
+
// id: 136941813297545217n,
|
|
264
|
+
// timestamp: 2024-01-16T09:09:25.000Z,
|
|
265
|
+
// timestampMs: 1737017365000,
|
|
266
|
+
// machineId: 1,
|
|
267
|
+
// sequence: 1
|
|
268
|
+
// }
|
|
269
|
+
|
|
270
|
+
const parts2 = parseSnowflake(136941813297545217n);
|
|
271
|
+
console.log(parts2);
|
|
272
|
+
// {
|
|
273
|
+
// id: 136941813297545217n,
|
|
274
|
+
// timestamp: 2024-01-16T09:09:25.000Z,
|
|
275
|
+
// timestampMs: 1737017365000,
|
|
276
|
+
// machineId: 1,
|
|
277
|
+
// sequence: 1
|
|
278
|
+
// }
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
#### `stringifySnowflakeParts(parts): SnowflakePartsJSON`
|
|
284
|
+
|
|
285
|
+
Converts SnowflakeParts to a JSON-serializable format.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import { parseSnowflake, stringifySnowflakeParts } from '@toolkit-f/snowflake-id';
|
|
289
|
+
|
|
290
|
+
const parts = parseSnowflake('136941813297545217');
|
|
291
|
+
const json = stringifySnowflakeParts(parts);
|
|
292
|
+
|
|
293
|
+
console.log(json);
|
|
294
|
+
// {
|
|
295
|
+
// id: "136941813297545217",
|
|
296
|
+
// timestamp: "2024-01-16T09:09:25.000Z",
|
|
297
|
+
// timestampMs: 1737017365000,
|
|
298
|
+
// machineId: 1,
|
|
299
|
+
// sequence: 1
|
|
300
|
+
// }
|
|
301
|
+
|
|
302
|
+
console.log(JSON.stringify(json));
|
|
303
|
+
// '{"id":"136941813297545217","timestamp":"2024-01-16T09:09:25.000Z","timestampMs":1737017365000,"machineId":1,"sequence":1}'
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
#### `getTimestamp(id, epoch?): Date`
|
|
309
|
+
|
|
310
|
+
Extracts the Date object from a Snowflake ID.
|
|
311
|
+
|
|
312
|
+
| Parameter | Type | Required | Default | Description |
|
|
313
|
+
|-----------|------|----------|---------|-------------|
|
|
314
|
+
| `id` | `bigint` \| `string` | Yes | - | The Snowflake ID |
|
|
315
|
+
| `epoch` | `number` | No | `1704067200000` | Custom epoch |
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
import { getTimestamp } from '@toolkit-f/snowflake-id';
|
|
319
|
+
|
|
320
|
+
console.log(getTimestamp('136941813297545217'));
|
|
321
|
+
// 2024-01-16T09:09:25.000Z
|
|
322
|
+
|
|
323
|
+
console.log(getTimestamp(136941813297545217n));
|
|
324
|
+
// 2024-01-16T09:09:25.000Z
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
#### `getMachineId(id): number`
|
|
330
|
+
|
|
331
|
+
Extracts the machine ID from a Snowflake ID.
|
|
332
|
+
|
|
333
|
+
| Parameter | Type | Required | Description |
|
|
334
|
+
|-----------|------|----------|-------------|
|
|
335
|
+
| `id` | `bigint` \| `string` | Yes | The Snowflake ID |
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
import { getMachineId } from '@toolkit-f/snowflake-id';
|
|
339
|
+
|
|
340
|
+
console.log(getMachineId('136941813297545217'));
|
|
341
|
+
// 1
|
|
342
|
+
|
|
343
|
+
console.log(getMachineId(136941813297545217n));
|
|
344
|
+
// 1
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
#### `getSequence(id): number`
|
|
350
|
+
|
|
351
|
+
Extracts the sequence number from a Snowflake ID.
|
|
352
|
+
|
|
353
|
+
| Parameter | Type | Required | Description |
|
|
354
|
+
|-----------|------|----------|-------------|
|
|
355
|
+
| `id` | `bigint` \| `string` | Yes | The Snowflake ID |
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
import { getSequence } from '@toolkit-f/snowflake-id';
|
|
359
|
+
|
|
360
|
+
console.log(getSequence('136941813297545217'));
|
|
361
|
+
// 1
|
|
362
|
+
|
|
363
|
+
console.log(getSequence(136941813297545217n));
|
|
364
|
+
// 1
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
#### `isValidSnowflake(id, epoch?, relaxed?): boolean`
|
|
370
|
+
|
|
371
|
+
Validates if a value is a valid Snowflake ID.
|
|
372
|
+
|
|
373
|
+
| Parameter | Type | Required | Default | Description |
|
|
374
|
+
|-----------|------|----------|---------|-------------|
|
|
375
|
+
| `id` | `unknown` | Yes | - | Value to validate |
|
|
376
|
+
| `epoch` | `number` | No | `1704067200000` | Custom epoch |
|
|
377
|
+
| `relaxed` | `boolean` | No | `false` | Skip timestamp range check |
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
import { isValidSnowflake } from '@toolkit-f/snowflake-id';
|
|
381
|
+
|
|
382
|
+
console.log(isValidSnowflake('136941813297545217'));
|
|
383
|
+
// true
|
|
384
|
+
|
|
385
|
+
console.log(isValidSnowflake(136941813297545217n));
|
|
386
|
+
// true
|
|
387
|
+
|
|
388
|
+
console.log(isValidSnowflake('invalid'));
|
|
389
|
+
// false
|
|
390
|
+
|
|
391
|
+
console.log(isValidSnowflake('abc123'));
|
|
392
|
+
// false
|
|
393
|
+
|
|
394
|
+
console.log(isValidSnowflake(-1n));
|
|
395
|
+
// false
|
|
396
|
+
|
|
397
|
+
// Relaxed mode (skip timestamp validation)
|
|
398
|
+
console.log(isValidSnowflake('999999999999999999999', undefined, true));
|
|
399
|
+
// true
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
#### `snowflakeToString(id): string`
|
|
405
|
+
|
|
406
|
+
Converts a bigint Snowflake ID to string.
|
|
407
|
+
|
|
408
|
+
| Parameter | Type | Required | Description |
|
|
409
|
+
|-----------|------|----------|-------------|
|
|
410
|
+
| `id` | `bigint` | Yes | The Snowflake ID |
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
import { snowflakeToString } from '@toolkit-f/snowflake-id';
|
|
414
|
+
|
|
415
|
+
console.log(snowflakeToString(136941813297545217n));
|
|
416
|
+
// "136941813297545217"
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
#### `stringToSnowflake(str): bigint`
|
|
422
|
+
|
|
423
|
+
Converts a string Snowflake ID to bigint.
|
|
424
|
+
|
|
425
|
+
| Parameter | Type | Required | Description |
|
|
426
|
+
|-----------|------|----------|-------------|
|
|
427
|
+
| `str` | `string` | Yes | The Snowflake ID string |
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
import { stringToSnowflake } from '@toolkit-f/snowflake-id';
|
|
431
|
+
|
|
432
|
+
console.log(stringToSnowflake('136941813297545217'));
|
|
433
|
+
// 136941813297545217n
|
|
434
|
+
|
|
435
|
+
// Throws error for invalid input
|
|
436
|
+
stringToSnowflake('invalid');
|
|
437
|
+
// Error: Invalid Snowflake ID string: "invalid"
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
#### `compareSnowflakes(a, b): -1 | 0 | 1`
|
|
443
|
+
|
|
444
|
+
Compares two Snowflake IDs. Useful for sorting.
|
|
445
|
+
|
|
446
|
+
| Parameter | Type | Required | Description |
|
|
447
|
+
|-----------|------|----------|-------------|
|
|
448
|
+
| `a` | `bigint` \| `string` | Yes | First Snowflake ID |
|
|
449
|
+
| `b` | `bigint` \| `string` | Yes | Second Snowflake ID |
|
|
450
|
+
|
|
451
|
+
**Returns:** `-1` if a < b, `0` if a === b, `1` if a > b
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
import { compareSnowflakes } from '@toolkit-f/snowflake-id';
|
|
455
|
+
|
|
456
|
+
console.log(compareSnowflakes('136941813297545216', '136941813297545217'));
|
|
457
|
+
// -1
|
|
458
|
+
|
|
459
|
+
console.log(compareSnowflakes('136941813297545217', '136941813297545217'));
|
|
460
|
+
// 0
|
|
461
|
+
|
|
462
|
+
console.log(compareSnowflakes('136941813297545218', '136941813297545217'));
|
|
463
|
+
// 1
|
|
464
|
+
|
|
465
|
+
// Sorting example
|
|
466
|
+
const ids = ['136941813297545218', '136941813297545216', '136941813297545217'];
|
|
467
|
+
ids.sort(compareSnowflakes);
|
|
468
|
+
console.log(ids);
|
|
469
|
+
// ['136941813297545216', '136941813297545217', '136941813297545218']
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
#### `snowflakeFromTimestamp(date, machineId?, sequence?, epoch?): bigint`
|
|
475
|
+
|
|
476
|
+
Creates a Snowflake ID from a specific timestamp. Useful for database range queries.
|
|
477
|
+
|
|
478
|
+
| Parameter | Type | Required | Default | Description |
|
|
479
|
+
|-----------|------|----------|---------|-------------|
|
|
480
|
+
| `date` | `Date` \| `number` | Yes | - | Timestamp to create ID from |
|
|
481
|
+
| `machineId` | `number` | No | `0` | Machine ID (0-1023) |
|
|
482
|
+
| `sequence` | `number` | No | `0` | Sequence number (0-4095) |
|
|
483
|
+
| `epoch` | `number` | No | `1704067200000` | Custom epoch |
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
import { snowflakeFromTimestamp } from '@toolkit-f/snowflake-id';
|
|
487
|
+
|
|
488
|
+
// From Date object
|
|
489
|
+
const id1 = snowflakeFromTimestamp(new Date('2024-06-15T12:00:00.000Z'));
|
|
490
|
+
console.log(id1);
|
|
491
|
+
// 59918327808000000n
|
|
492
|
+
|
|
493
|
+
// From timestamp number
|
|
494
|
+
const id2 = snowflakeFromTimestamp(1718452800000);
|
|
495
|
+
console.log(id2);
|
|
496
|
+
// 59918327808000000n
|
|
497
|
+
|
|
498
|
+
// With machine ID and sequence
|
|
499
|
+
const id3 = snowflakeFromTimestamp(new Date('2024-06-15T12:00:00.000Z'), 5, 10);
|
|
500
|
+
console.log(id3);
|
|
501
|
+
// 59918327808020490n
|
|
502
|
+
|
|
503
|
+
// Database range query example
|
|
504
|
+
const startOfDay = snowflakeFromTimestamp(new Date('2024-06-15T00:00:00.000Z'));
|
|
505
|
+
const endOfDay = snowflakeFromTimestamp(new Date('2024-06-15T23:59:59.999Z'));
|
|
506
|
+
console.log(`SELECT * FROM items WHERE id >= ${startOfDay} AND id <= ${endOfDay}`);
|
|
507
|
+
// SELECT * FROM items WHERE id >= 59914215014400000 AND id <= 60010106326016000
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
### Exported Constants
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
import {
|
|
516
|
+
DEFAULT_EPOCH,
|
|
517
|
+
MAX_MACHINE_ID,
|
|
518
|
+
MAX_SEQUENCE,
|
|
519
|
+
MACHINE_ID_SHIFT,
|
|
520
|
+
TIMESTAMP_SHIFT
|
|
521
|
+
} from '@toolkit-f/snowflake-id';
|
|
522
|
+
|
|
523
|
+
console.log(DEFAULT_EPOCH);
|
|
524
|
+
// 1704067200000 (Jan 1, 2024 00:00:00 UTC)
|
|
525
|
+
|
|
526
|
+
console.log(MAX_MACHINE_ID);
|
|
527
|
+
// 1023
|
|
528
|
+
|
|
529
|
+
console.log(MAX_SEQUENCE);
|
|
530
|
+
// 4095n
|
|
531
|
+
|
|
532
|
+
console.log(MACHINE_ID_SHIFT);
|
|
533
|
+
// 12n
|
|
534
|
+
|
|
535
|
+
console.log(TIMESTAMP_SHIFT);
|
|
536
|
+
// 22n
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
### TypeScript Types
|
|
542
|
+
|
|
543
|
+
```typescript
|
|
544
|
+
import type {
|
|
545
|
+
SnowflakeConfig,
|
|
546
|
+
SnowflakeParts,
|
|
547
|
+
SnowflakePartsJSON
|
|
548
|
+
} from '@toolkit-f/snowflake-id';
|
|
549
|
+
|
|
550
|
+
// SnowflakeConfig
|
|
551
|
+
interface SnowflakeConfig {
|
|
552
|
+
machineId: number; // 0-1023
|
|
553
|
+
epoch?: number; // Custom epoch (ms)
|
|
554
|
+
clockMoveBackAction?: 'throw' | 'wait';
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// SnowflakeParts
|
|
558
|
+
interface SnowflakeParts {
|
|
559
|
+
id: bigint;
|
|
560
|
+
timestamp: Date;
|
|
561
|
+
timestampMs: number;
|
|
562
|
+
machineId: number;
|
|
563
|
+
sequence: number;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// SnowflakePartsJSON
|
|
567
|
+
interface SnowflakePartsJSON {
|
|
568
|
+
id: string;
|
|
569
|
+
timestamp: string;
|
|
570
|
+
timestampMs: number;
|
|
571
|
+
machineId: number;
|
|
572
|
+
sequence: number;
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## Error Handling
|
|
579
|
+
|
|
580
|
+
```typescript
|
|
581
|
+
import { SnowflakeGenerator, stringToSnowflake, parseSnowflake } from '@toolkit-f/snowflake-id';
|
|
582
|
+
|
|
583
|
+
// Invalid machine ID
|
|
584
|
+
try {
|
|
585
|
+
new SnowflakeGenerator({ machineId: 2000 });
|
|
586
|
+
} catch (e) {
|
|
587
|
+
console.log(e.message);
|
|
588
|
+
// "machineId must be integer 0-1023, got 2000"
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// Future epoch
|
|
592
|
+
try {
|
|
593
|
+
new SnowflakeGenerator({ machineId: 1, epoch: Date.now() + 100000 });
|
|
594
|
+
} catch (e) {
|
|
595
|
+
console.log(e.message);
|
|
596
|
+
// "epoch cannot be in the future"
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// Invalid string ID
|
|
600
|
+
try {
|
|
601
|
+
stringToSnowflake('not-a-number');
|
|
602
|
+
} catch (e) {
|
|
603
|
+
console.log(e.message);
|
|
604
|
+
// 'Invalid Snowflake ID string: "not-a-number"'
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// Invalid parse input
|
|
608
|
+
try {
|
|
609
|
+
parseSnowflake('abc123');
|
|
610
|
+
} catch (e) {
|
|
611
|
+
console.log(e.message);
|
|
612
|
+
// 'Invalid Snowflake ID: "abc123"'
|
|
613
|
+
}
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
## 🤝 Contributing
|
|
619
|
+
|
|
620
|
+
Contributions are welcome! Please feel free to submit a [Pull Request](https://github.com/maulik-mk/Snowflake-Id/pulls).
|
|
621
|
+
|
|
622
|
+
1. Fork the repository
|
|
623
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
624
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
625
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
626
|
+
5. Open a Pull Request
|
|
627
|
+
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
## 🪪 License
|
|
631
|
+
|
|
632
|
+
[MIT](https://github.com/maulik-mk/Snowflake-Id/blob/main/LICENSE) © [Maulik M. K.](https://github.com/maulik-mk)
|