@sodiumlabs/snowflake 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +74 -0
- package/dist/index.d.mts +205 -0
- package/dist/index.d.ts +205 -0
- package/dist/index.js +219 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +190 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sodiumlabs
|
|
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,74 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>@sodiumlabs/snowflake</h1>
|
|
3
|
+
<p>
|
|
4
|
+
<a href="https://discord.gg/8PDXWSHH7k"><img src="https://img.shields.io/badge/join_us-on_discord-5865F2?logo=discord&logoColor=white" alt="Discord server" /></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/@sodiumlabs/snowflake"><img src="https://img.shields.io/npm/v/@sodiumlabs/snowflake.svg?maxAge=3600" alt="npm version" /></a>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@sodiumlabs/snowflake"><img src="https://img.shields.io/npm/dt/@sodiumlabs/snowflake.svg?maxAge=3600" alt="npm downloads" /></a>
|
|
7
|
+
<a href="https://github.com/sodium-labs/utilities/commits/main/packages/snowflake"><img alt="Last commit" src="https://img.shields.io/github/last-commit/sodium-labs/utilities?logo=github&logoColor=ffffff&path=packages%2Fsnowflake" /></a>
|
|
8
|
+
</p>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
## About
|
|
12
|
+
|
|
13
|
+
Utility package to generate and deconstruct snowflakes. Snowflakes are unique IDs sortable by time and containing their creation timestamp within themselves. Read more about snowflakes on [Wikipedia](https://en.wikipedia.org/wiki/Snowflake_ID).
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
Node.js 18 or newer is required.
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm install @sodiumlabs/snowflake
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Using snowflakes
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { Snowflake } from "@sodiumlabs/snowflake";
|
|
29
|
+
|
|
30
|
+
const epoch = new Date("2020-01-01T00:00:00.000Z");
|
|
31
|
+
|
|
32
|
+
// Create an instance of Snowflake
|
|
33
|
+
const snowflake = new Snowflake(epoch);
|
|
34
|
+
|
|
35
|
+
// Generate a snowflake with the given epoch
|
|
36
|
+
const uniqueId = snowflake.generate();
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Snowflakes with Discord
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { discordSnowflake } from "@sodiumlabs/snowflake";
|
|
43
|
+
|
|
44
|
+
// Extract only the timestamp from a snowflake
|
|
45
|
+
const timestamp = discordSnowflake.timestampFrom("716068012414730320");
|
|
46
|
+
// 1590794318060
|
|
47
|
+
|
|
48
|
+
// Deconstruct the snowflake
|
|
49
|
+
const data = discordSnowflake.deconstruct("716068012414730320");
|
|
50
|
+
// {
|
|
51
|
+
// id: 716068012414730320n,
|
|
52
|
+
// timestamp: 1590794318060n,
|
|
53
|
+
// workerId: 0n,
|
|
54
|
+
// processId: 0n,
|
|
55
|
+
// increment: 80n,
|
|
56
|
+
// epoch: 1420070400000n
|
|
57
|
+
// }
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Links
|
|
61
|
+
|
|
62
|
+
- [Documentation](https://docs.sodiumlabs.xyz/docs/packages/snowflake/stable)
|
|
63
|
+
- [Discord server](https://discord.gg/8PDXWSHH7k)
|
|
64
|
+
- [GitHub](https://github.com/sodium-labs/utilities/tree/main/packages/snowflake)
|
|
65
|
+
- [npm](https://npmjs.com/package/@sodiumlabs/snowflake)
|
|
66
|
+
- [Sodium Labs](https://sodiumlabs.xyz)
|
|
67
|
+
|
|
68
|
+
## Help
|
|
69
|
+
|
|
70
|
+
Need help with the module? Ask on our [support server!](https://discord.gg/8PDXWSHH7k)
|
|
71
|
+
|
|
72
|
+
# Credits
|
|
73
|
+
|
|
74
|
+
This project also partially contains code derived or copied from [@sapphire/snowflake](https://github.com/sapphiredev/utilities/tree/main/packages/snowflake).
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
declare const IncrementSymbol: unique symbol;
|
|
2
|
+
declare const EpochSymbol: unique symbol;
|
|
3
|
+
declare const EpochNumberSymbol: unique symbol;
|
|
4
|
+
declare const ProcessIdSymbol: unique symbol;
|
|
5
|
+
declare const WorkerIdSymbol: unique symbol;
|
|
6
|
+
/**
|
|
7
|
+
* The maximum value the `workerId` field accepts in snowflakes.
|
|
8
|
+
*/
|
|
9
|
+
declare const MaximumWorkerId = 31n;
|
|
10
|
+
/**
|
|
11
|
+
* The maximum value the `processId` field accepts in snowflakes.
|
|
12
|
+
*/
|
|
13
|
+
declare const MaximumProcessId = 31n;
|
|
14
|
+
/**
|
|
15
|
+
* The maximum value the `increment` field accepts in snowflakes.
|
|
16
|
+
*/
|
|
17
|
+
declare const MaximumIncrement = 4095n;
|
|
18
|
+
/**
|
|
19
|
+
* A class for generating and deconstructing snowflakes.
|
|
20
|
+
*
|
|
21
|
+
* A {@link https://en.wikipedia.org/wiki/Snowflake_ID | snowflake}
|
|
22
|
+
* is a 64-bit unsigned integer with 4 fields that have a fixed epoch value.
|
|
23
|
+
*
|
|
24
|
+
* If we have a snowflake `266241948824764416` we can represent it as binary:
|
|
25
|
+
* ```
|
|
26
|
+
* 64 22 17 12 0
|
|
27
|
+
* 000000111011000111100001101001000101000000 00001 00000 000000000000
|
|
28
|
+
* number of ms since epoch worker pid increment
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
declare class Snowflake {
|
|
32
|
+
/**
|
|
33
|
+
* Internal reference of the epoch passed in the constructor.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
private readonly [EpochSymbol];
|
|
37
|
+
/**
|
|
38
|
+
* Internal reference of the epoch passed in the constructor as a number.
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
private readonly [EpochNumberSymbol];
|
|
42
|
+
/**
|
|
43
|
+
* Internal incrementor for generating snowflakes.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
private [IncrementSymbol];
|
|
47
|
+
/**
|
|
48
|
+
* The process ID that will be used by default in the generate method.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
private [ProcessIdSymbol];
|
|
52
|
+
/**
|
|
53
|
+
* The worker ID that will be used by default in the generate method.
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
private [WorkerIdSymbol];
|
|
57
|
+
/**
|
|
58
|
+
* @param epoch - The epoch to use.
|
|
59
|
+
*/
|
|
60
|
+
constructor(epoch: number | bigint | Date);
|
|
61
|
+
/**
|
|
62
|
+
* The epoch for this snowflake, as a bigint.
|
|
63
|
+
*/
|
|
64
|
+
get epoch(): bigint;
|
|
65
|
+
/**
|
|
66
|
+
* The epoch for this snowflake, as a number.
|
|
67
|
+
*/
|
|
68
|
+
get epochNumber(): number;
|
|
69
|
+
/**
|
|
70
|
+
* Gets or sets the configured process ID.
|
|
71
|
+
*/
|
|
72
|
+
get processId(): bigint;
|
|
73
|
+
set processId(value: number | bigint);
|
|
74
|
+
/**
|
|
75
|
+
* Gets or sets the configured worker ID.
|
|
76
|
+
*/
|
|
77
|
+
get workerId(): bigint;
|
|
78
|
+
set workerId(value: number | bigint);
|
|
79
|
+
/**
|
|
80
|
+
* Generates a snowflake given an epoch and optionally a timestamp.
|
|
81
|
+
*
|
|
82
|
+
* **Note:** when `increment` is not provided it defaults to the private `increment` of the instance.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const epoch = new Date('2000-01-01T00:00:00.000Z');
|
|
87
|
+
* const snowflake = new Snowflake(epoch).generate();
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @param options - Options to pass into the generator, see {@link SnowflakeGenerateOptions}.
|
|
91
|
+
* @returns A unique snowflake.
|
|
92
|
+
*/
|
|
93
|
+
generate({ increment, timestamp, workerId, processId, }?: SnowflakeGenerateOptions): bigint;
|
|
94
|
+
/**
|
|
95
|
+
* Deconstructs a snowflake.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* const epoch = new Date('2000-01-01T00:00:00.000Z');
|
|
100
|
+
* const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @param id - The snowflake to deconstruct.
|
|
104
|
+
* @returns A deconstructed snowflake.
|
|
105
|
+
*/
|
|
106
|
+
deconstruct(id: string | bigint): DeconstructedSnowflake;
|
|
107
|
+
/**
|
|
108
|
+
* Retrieves the timestamp field's value from a snowflake.
|
|
109
|
+
*
|
|
110
|
+
* @param id - The snowflake to get the timestamp value from.
|
|
111
|
+
* @returns The UNIX timestamp that is stored in `id`.
|
|
112
|
+
*/
|
|
113
|
+
timestampFrom(id: string | bigint): number;
|
|
114
|
+
/**
|
|
115
|
+
* Returns a number indicating whether a reference snowflake comes before,
|
|
116
|
+
* or after, or is same as the given snowflake in sort order.
|
|
117
|
+
*
|
|
118
|
+
* @example Sort snowflakes in ascending order
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];
|
|
121
|
+
* console.log(ids.sort((a, b) => Snowflake.compare(a, b)));
|
|
122
|
+
* // → ['254360814063058944', '737141877803057244', '1056191128120082432'];
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @example Sort snowflakes in descending order
|
|
126
|
+
* ```typescript
|
|
127
|
+
* const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];
|
|
128
|
+
* console.log(ids.sort((a, b) => -Snowflake.compare(a, b)));
|
|
129
|
+
* // → ['1056191128120082432', '737141877803057244', '254360814063058944'];
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @param a - The first snowflake to compare.
|
|
133
|
+
* @param b - The second snowflake to compare.
|
|
134
|
+
* @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.
|
|
135
|
+
*/
|
|
136
|
+
static compare(a: string | bigint, b: string | bigint): -1 | 0 | 1;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Options for `Snowflake#generate`.
|
|
140
|
+
*/
|
|
141
|
+
interface SnowflakeGenerateOptions {
|
|
142
|
+
/**
|
|
143
|
+
* Timestamp or date of the snowflake to generate.
|
|
144
|
+
*
|
|
145
|
+
* @defaultValue Date.now()
|
|
146
|
+
*/
|
|
147
|
+
timestamp?: number | bigint | Date;
|
|
148
|
+
/**
|
|
149
|
+
* The increment to use.
|
|
150
|
+
*
|
|
151
|
+
* @defaultValue 0n
|
|
152
|
+
* @remarks keep in mind that this bigint is auto-incremented between generate calls.
|
|
153
|
+
*/
|
|
154
|
+
increment?: bigint;
|
|
155
|
+
/**
|
|
156
|
+
* The worker ID to use, will be truncated to 5 bits (0-31).
|
|
157
|
+
*
|
|
158
|
+
* @defaultValue 0n
|
|
159
|
+
*/
|
|
160
|
+
workerId?: bigint;
|
|
161
|
+
/**
|
|
162
|
+
* The process ID to use, will be truncated to 5 bits (0-31).
|
|
163
|
+
*
|
|
164
|
+
* @defaultValue 1n
|
|
165
|
+
*/
|
|
166
|
+
processId?: bigint;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Object returned by `Snowflake#deconstruct`.
|
|
170
|
+
*/
|
|
171
|
+
interface DeconstructedSnowflake {
|
|
172
|
+
/**
|
|
173
|
+
* The id in BigInt form.
|
|
174
|
+
*/
|
|
175
|
+
id: bigint;
|
|
176
|
+
/**
|
|
177
|
+
* The timestamp stored in the snowflake.
|
|
178
|
+
*/
|
|
179
|
+
timestamp: bigint;
|
|
180
|
+
/**
|
|
181
|
+
* The worker id stored in the snowflake.
|
|
182
|
+
*/
|
|
183
|
+
workerId: bigint;
|
|
184
|
+
/**
|
|
185
|
+
* The process id stored in the snowflake.
|
|
186
|
+
*/
|
|
187
|
+
processId: bigint;
|
|
188
|
+
/**
|
|
189
|
+
* The increment stored in the snowflake.
|
|
190
|
+
*/
|
|
191
|
+
increment: bigint;
|
|
192
|
+
/**
|
|
193
|
+
* The epoch to use in the snowflake.
|
|
194
|
+
*/
|
|
195
|
+
epoch: bigint;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* A class for parsing snowflake ids using Discord's snowflake epoch.
|
|
200
|
+
*
|
|
201
|
+
* The Discord epoch is `1420070400000` (`2015-01-01T00:00:00.000Z`), see {@link https://discord.com/developers/docs/reference#snowflakes}.
|
|
202
|
+
*/
|
|
203
|
+
declare const discordSnowflake: Snowflake;
|
|
204
|
+
|
|
205
|
+
export { type DeconstructedSnowflake, MaximumIncrement, MaximumProcessId, MaximumWorkerId, Snowflake, type SnowflakeGenerateOptions, discordSnowflake };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
declare const IncrementSymbol: unique symbol;
|
|
2
|
+
declare const EpochSymbol: unique symbol;
|
|
3
|
+
declare const EpochNumberSymbol: unique symbol;
|
|
4
|
+
declare const ProcessIdSymbol: unique symbol;
|
|
5
|
+
declare const WorkerIdSymbol: unique symbol;
|
|
6
|
+
/**
|
|
7
|
+
* The maximum value the `workerId` field accepts in snowflakes.
|
|
8
|
+
*/
|
|
9
|
+
declare const MaximumWorkerId = 31n;
|
|
10
|
+
/**
|
|
11
|
+
* The maximum value the `processId` field accepts in snowflakes.
|
|
12
|
+
*/
|
|
13
|
+
declare const MaximumProcessId = 31n;
|
|
14
|
+
/**
|
|
15
|
+
* The maximum value the `increment` field accepts in snowflakes.
|
|
16
|
+
*/
|
|
17
|
+
declare const MaximumIncrement = 4095n;
|
|
18
|
+
/**
|
|
19
|
+
* A class for generating and deconstructing snowflakes.
|
|
20
|
+
*
|
|
21
|
+
* A {@link https://en.wikipedia.org/wiki/Snowflake_ID | snowflake}
|
|
22
|
+
* is a 64-bit unsigned integer with 4 fields that have a fixed epoch value.
|
|
23
|
+
*
|
|
24
|
+
* If we have a snowflake `266241948824764416` we can represent it as binary:
|
|
25
|
+
* ```
|
|
26
|
+
* 64 22 17 12 0
|
|
27
|
+
* 000000111011000111100001101001000101000000 00001 00000 000000000000
|
|
28
|
+
* number of ms since epoch worker pid increment
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
declare class Snowflake {
|
|
32
|
+
/**
|
|
33
|
+
* Internal reference of the epoch passed in the constructor.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
private readonly [EpochSymbol];
|
|
37
|
+
/**
|
|
38
|
+
* Internal reference of the epoch passed in the constructor as a number.
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
private readonly [EpochNumberSymbol];
|
|
42
|
+
/**
|
|
43
|
+
* Internal incrementor for generating snowflakes.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
private [IncrementSymbol];
|
|
47
|
+
/**
|
|
48
|
+
* The process ID that will be used by default in the generate method.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
private [ProcessIdSymbol];
|
|
52
|
+
/**
|
|
53
|
+
* The worker ID that will be used by default in the generate method.
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
private [WorkerIdSymbol];
|
|
57
|
+
/**
|
|
58
|
+
* @param epoch - The epoch to use.
|
|
59
|
+
*/
|
|
60
|
+
constructor(epoch: number | bigint | Date);
|
|
61
|
+
/**
|
|
62
|
+
* The epoch for this snowflake, as a bigint.
|
|
63
|
+
*/
|
|
64
|
+
get epoch(): bigint;
|
|
65
|
+
/**
|
|
66
|
+
* The epoch for this snowflake, as a number.
|
|
67
|
+
*/
|
|
68
|
+
get epochNumber(): number;
|
|
69
|
+
/**
|
|
70
|
+
* Gets or sets the configured process ID.
|
|
71
|
+
*/
|
|
72
|
+
get processId(): bigint;
|
|
73
|
+
set processId(value: number | bigint);
|
|
74
|
+
/**
|
|
75
|
+
* Gets or sets the configured worker ID.
|
|
76
|
+
*/
|
|
77
|
+
get workerId(): bigint;
|
|
78
|
+
set workerId(value: number | bigint);
|
|
79
|
+
/**
|
|
80
|
+
* Generates a snowflake given an epoch and optionally a timestamp.
|
|
81
|
+
*
|
|
82
|
+
* **Note:** when `increment` is not provided it defaults to the private `increment` of the instance.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const epoch = new Date('2000-01-01T00:00:00.000Z');
|
|
87
|
+
* const snowflake = new Snowflake(epoch).generate();
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @param options - Options to pass into the generator, see {@link SnowflakeGenerateOptions}.
|
|
91
|
+
* @returns A unique snowflake.
|
|
92
|
+
*/
|
|
93
|
+
generate({ increment, timestamp, workerId, processId, }?: SnowflakeGenerateOptions): bigint;
|
|
94
|
+
/**
|
|
95
|
+
* Deconstructs a snowflake.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* const epoch = new Date('2000-01-01T00:00:00.000Z');
|
|
100
|
+
* const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @param id - The snowflake to deconstruct.
|
|
104
|
+
* @returns A deconstructed snowflake.
|
|
105
|
+
*/
|
|
106
|
+
deconstruct(id: string | bigint): DeconstructedSnowflake;
|
|
107
|
+
/**
|
|
108
|
+
* Retrieves the timestamp field's value from a snowflake.
|
|
109
|
+
*
|
|
110
|
+
* @param id - The snowflake to get the timestamp value from.
|
|
111
|
+
* @returns The UNIX timestamp that is stored in `id`.
|
|
112
|
+
*/
|
|
113
|
+
timestampFrom(id: string | bigint): number;
|
|
114
|
+
/**
|
|
115
|
+
* Returns a number indicating whether a reference snowflake comes before,
|
|
116
|
+
* or after, or is same as the given snowflake in sort order.
|
|
117
|
+
*
|
|
118
|
+
* @example Sort snowflakes in ascending order
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];
|
|
121
|
+
* console.log(ids.sort((a, b) => Snowflake.compare(a, b)));
|
|
122
|
+
* // → ['254360814063058944', '737141877803057244', '1056191128120082432'];
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @example Sort snowflakes in descending order
|
|
126
|
+
* ```typescript
|
|
127
|
+
* const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];
|
|
128
|
+
* console.log(ids.sort((a, b) => -Snowflake.compare(a, b)));
|
|
129
|
+
* // → ['1056191128120082432', '737141877803057244', '254360814063058944'];
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @param a - The first snowflake to compare.
|
|
133
|
+
* @param b - The second snowflake to compare.
|
|
134
|
+
* @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.
|
|
135
|
+
*/
|
|
136
|
+
static compare(a: string | bigint, b: string | bigint): -1 | 0 | 1;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Options for `Snowflake#generate`.
|
|
140
|
+
*/
|
|
141
|
+
interface SnowflakeGenerateOptions {
|
|
142
|
+
/**
|
|
143
|
+
* Timestamp or date of the snowflake to generate.
|
|
144
|
+
*
|
|
145
|
+
* @defaultValue Date.now()
|
|
146
|
+
*/
|
|
147
|
+
timestamp?: number | bigint | Date;
|
|
148
|
+
/**
|
|
149
|
+
* The increment to use.
|
|
150
|
+
*
|
|
151
|
+
* @defaultValue 0n
|
|
152
|
+
* @remarks keep in mind that this bigint is auto-incremented between generate calls.
|
|
153
|
+
*/
|
|
154
|
+
increment?: bigint;
|
|
155
|
+
/**
|
|
156
|
+
* The worker ID to use, will be truncated to 5 bits (0-31).
|
|
157
|
+
*
|
|
158
|
+
* @defaultValue 0n
|
|
159
|
+
*/
|
|
160
|
+
workerId?: bigint;
|
|
161
|
+
/**
|
|
162
|
+
* The process ID to use, will be truncated to 5 bits (0-31).
|
|
163
|
+
*
|
|
164
|
+
* @defaultValue 1n
|
|
165
|
+
*/
|
|
166
|
+
processId?: bigint;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Object returned by `Snowflake#deconstruct`.
|
|
170
|
+
*/
|
|
171
|
+
interface DeconstructedSnowflake {
|
|
172
|
+
/**
|
|
173
|
+
* The id in BigInt form.
|
|
174
|
+
*/
|
|
175
|
+
id: bigint;
|
|
176
|
+
/**
|
|
177
|
+
* The timestamp stored in the snowflake.
|
|
178
|
+
*/
|
|
179
|
+
timestamp: bigint;
|
|
180
|
+
/**
|
|
181
|
+
* The worker id stored in the snowflake.
|
|
182
|
+
*/
|
|
183
|
+
workerId: bigint;
|
|
184
|
+
/**
|
|
185
|
+
* The process id stored in the snowflake.
|
|
186
|
+
*/
|
|
187
|
+
processId: bigint;
|
|
188
|
+
/**
|
|
189
|
+
* The increment stored in the snowflake.
|
|
190
|
+
*/
|
|
191
|
+
increment: bigint;
|
|
192
|
+
/**
|
|
193
|
+
* The epoch to use in the snowflake.
|
|
194
|
+
*/
|
|
195
|
+
epoch: bigint;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* A class for parsing snowflake ids using Discord's snowflake epoch.
|
|
200
|
+
*
|
|
201
|
+
* The Discord epoch is `1420070400000` (`2015-01-01T00:00:00.000Z`), see {@link https://discord.com/developers/docs/reference#snowflakes}.
|
|
202
|
+
*/
|
|
203
|
+
declare const discordSnowflake: Snowflake;
|
|
204
|
+
|
|
205
|
+
export { type DeconstructedSnowflake, MaximumIncrement, MaximumProcessId, MaximumWorkerId, Snowflake, type SnowflakeGenerateOptions, discordSnowflake };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/index.ts
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
MaximumIncrement: () => MaximumIncrement,
|
|
25
|
+
MaximumProcessId: () => MaximumProcessId,
|
|
26
|
+
MaximumWorkerId: () => MaximumWorkerId,
|
|
27
|
+
Snowflake: () => Snowflake,
|
|
28
|
+
discordSnowflake: () => discordSnowflake
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
|
|
32
|
+
// src/snowflake.ts
|
|
33
|
+
var IncrementSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.increment");
|
|
34
|
+
var EpochSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.epoch");
|
|
35
|
+
var EpochNumberSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.epoch.number");
|
|
36
|
+
var ProcessIdSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.processId");
|
|
37
|
+
var WorkerIdSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.workerId");
|
|
38
|
+
var MaximumWorkerId = 0b11111n;
|
|
39
|
+
var MaximumProcessId = 0b11111n;
|
|
40
|
+
var MaximumIncrement = 0b111111111111n;
|
|
41
|
+
var Snowflake = class {
|
|
42
|
+
static {
|
|
43
|
+
__name(this, "Snowflake");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Internal reference of the epoch passed in the constructor.
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
[EpochSymbol];
|
|
50
|
+
/**
|
|
51
|
+
* Internal reference of the epoch passed in the constructor as a number.
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
[EpochNumberSymbol];
|
|
55
|
+
/**
|
|
56
|
+
* Internal incrementor for generating snowflakes.
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
[IncrementSymbol] = 0n;
|
|
60
|
+
/**
|
|
61
|
+
* The process ID that will be used by default in the generate method.
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
[ProcessIdSymbol] = 1n;
|
|
65
|
+
/**
|
|
66
|
+
* The worker ID that will be used by default in the generate method.
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
[WorkerIdSymbol] = 0n;
|
|
70
|
+
/**
|
|
71
|
+
* @param epoch - The epoch to use.
|
|
72
|
+
*/
|
|
73
|
+
constructor(epoch) {
|
|
74
|
+
this[EpochSymbol] = BigInt(epoch instanceof Date ? epoch.getTime() : epoch);
|
|
75
|
+
this[EpochNumberSymbol] = Number(this[EpochSymbol]);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The epoch for this snowflake, as a bigint.
|
|
79
|
+
*/
|
|
80
|
+
get epoch() {
|
|
81
|
+
return this[EpochSymbol];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The epoch for this snowflake, as a number.
|
|
85
|
+
*/
|
|
86
|
+
get epochNumber() {
|
|
87
|
+
return this[EpochNumberSymbol];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Gets or sets the configured process ID.
|
|
91
|
+
*/
|
|
92
|
+
get processId() {
|
|
93
|
+
return this[ProcessIdSymbol];
|
|
94
|
+
}
|
|
95
|
+
set processId(value) {
|
|
96
|
+
this[ProcessIdSymbol] = BigInt(value) & MaximumProcessId;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Gets or sets the configured worker ID.
|
|
100
|
+
*/
|
|
101
|
+
get workerId() {
|
|
102
|
+
return this[WorkerIdSymbol];
|
|
103
|
+
}
|
|
104
|
+
set workerId(value) {
|
|
105
|
+
this[WorkerIdSymbol] = BigInt(value) & MaximumWorkerId;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Generates a snowflake given an epoch and optionally a timestamp.
|
|
109
|
+
*
|
|
110
|
+
* **Note:** when `increment` is not provided it defaults to the private `increment` of the instance.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const epoch = new Date('2000-01-01T00:00:00.000Z');
|
|
115
|
+
* const snowflake = new Snowflake(epoch).generate();
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* @param options - Options to pass into the generator, see {@link SnowflakeGenerateOptions}.
|
|
119
|
+
* @returns A unique snowflake.
|
|
120
|
+
*/
|
|
121
|
+
generate({
|
|
122
|
+
increment,
|
|
123
|
+
timestamp = Date.now(),
|
|
124
|
+
workerId = this[WorkerIdSymbol],
|
|
125
|
+
processId = this[ProcessIdSymbol]
|
|
126
|
+
} = {}) {
|
|
127
|
+
if (timestamp instanceof Date) timestamp = BigInt(timestamp.getTime());
|
|
128
|
+
else if (typeof timestamp === "number") timestamp = BigInt(timestamp);
|
|
129
|
+
else if (typeof timestamp !== "bigint") {
|
|
130
|
+
throw new TypeError(
|
|
131
|
+
`"timestamp" argument must be a number, bigint, or Date (received ${typeof timestamp})`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
if (typeof increment !== "bigint") {
|
|
135
|
+
increment = this[IncrementSymbol];
|
|
136
|
+
this[IncrementSymbol] = increment + 1n & MaximumIncrement;
|
|
137
|
+
}
|
|
138
|
+
return timestamp - this[EpochSymbol] << 22n | (workerId & MaximumWorkerId) << 17n | (processId & MaximumProcessId) << 12n | increment & MaximumIncrement;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Deconstructs a snowflake.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* const epoch = new Date('2000-01-01T00:00:00.000Z');
|
|
146
|
+
* const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* @param id - The snowflake to deconstruct.
|
|
150
|
+
* @returns A deconstructed snowflake.
|
|
151
|
+
*/
|
|
152
|
+
deconstruct(id) {
|
|
153
|
+
const bigIntId = BigInt(id);
|
|
154
|
+
const epoch = this[EpochSymbol];
|
|
155
|
+
return {
|
|
156
|
+
id: bigIntId,
|
|
157
|
+
timestamp: (bigIntId >> 22n) + epoch,
|
|
158
|
+
workerId: bigIntId >> 17n & MaximumWorkerId,
|
|
159
|
+
processId: bigIntId >> 12n & MaximumProcessId,
|
|
160
|
+
increment: bigIntId & MaximumIncrement,
|
|
161
|
+
epoch
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Retrieves the timestamp field's value from a snowflake.
|
|
166
|
+
*
|
|
167
|
+
* @param id - The snowflake to get the timestamp value from.
|
|
168
|
+
* @returns The UNIX timestamp that is stored in `id`.
|
|
169
|
+
*/
|
|
170
|
+
timestampFrom(id) {
|
|
171
|
+
return Number((BigInt(id) >> 22n) + this.epoch);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Returns a number indicating whether a reference snowflake comes before,
|
|
175
|
+
* or after, or is same as the given snowflake in sort order.
|
|
176
|
+
*
|
|
177
|
+
* @example Sort snowflakes in ascending order
|
|
178
|
+
* ```typescript
|
|
179
|
+
* const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];
|
|
180
|
+
* console.log(ids.sort((a, b) => Snowflake.compare(a, b)));
|
|
181
|
+
* // → ['254360814063058944', '737141877803057244', '1056191128120082432'];
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* @example Sort snowflakes in descending order
|
|
185
|
+
* ```typescript
|
|
186
|
+
* const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];
|
|
187
|
+
* console.log(ids.sort((a, b) => -Snowflake.compare(a, b)));
|
|
188
|
+
* // → ['1056191128120082432', '737141877803057244', '254360814063058944'];
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
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
|
+
const typeA = typeof a;
|
|
197
|
+
return typeA === typeof b ? typeA === "string" ? cmpString(a, b) : cmpBigInt(a, b) : cmpBigInt(BigInt(a), BigInt(b));
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
function cmpBigInt(a, b) {
|
|
201
|
+
return a === b ? 0 : a < b ? -1 : 1;
|
|
202
|
+
}
|
|
203
|
+
__name(cmpBigInt, "cmpBigInt");
|
|
204
|
+
function cmpString(a, b) {
|
|
205
|
+
return a === b ? 0 : a.length < b.length ? -1 : a.length > b.length ? 1 : a < b ? -1 : 1;
|
|
206
|
+
}
|
|
207
|
+
__name(cmpString, "cmpString");
|
|
208
|
+
|
|
209
|
+
// src/discord-snowflake.ts
|
|
210
|
+
var discordSnowflake = new Snowflake(1420070400000n);
|
|
211
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
212
|
+
0 && (module.exports = {
|
|
213
|
+
MaximumIncrement,
|
|
214
|
+
MaximumProcessId,
|
|
215
|
+
MaximumWorkerId,
|
|
216
|
+
Snowflake,
|
|
217
|
+
discordSnowflake
|
|
218
|
+
});
|
|
219
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/snowflake.ts","../src/discord-snowflake.ts"],"sourcesContent":["export * from \"./snowflake\";\nexport * from \"./discord-snowflake\";\n","const IncrementSymbol = Symbol(\"@sodiumlabs/snowflake.increment\");\nconst EpochSymbol = Symbol(\"@sodiumlabs/snowflake.epoch\");\nconst EpochNumberSymbol = Symbol(\"@sodiumlabs/snowflake.epoch.number\");\nconst ProcessIdSymbol = Symbol(\"@sodiumlabs/snowflake.processId\");\nconst WorkerIdSymbol = Symbol(\"@sodiumlabs/snowflake.workerId\");\n\n/**\n * The maximum value the `workerId` field accepts in snowflakes.\n */\nexport const MaximumWorkerId = 0b11111n;\n\n/**\n * The maximum value the `processId` field accepts in snowflakes.\n */\nexport const MaximumProcessId = 0b11111n;\n\n/**\n * The maximum value the `increment` field accepts in snowflakes.\n */\nexport const MaximumIncrement = 0b111111111111n;\n\n/**\n * A class for generating and deconstructing snowflakes.\n *\n * A {@link https://en.wikipedia.org/wiki/Snowflake_ID | 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 */\nexport class Snowflake {\n /**\n * Internal reference of the epoch passed in the constructor.\n * @internal\n */\n private readonly [EpochSymbol]: bigint;\n\n /**\n * Internal reference of the epoch passed in the constructor as a number.\n * @internal\n */\n private readonly [EpochNumberSymbol]: number;\n\n /**\n * Internal incrementor for generating snowflakes.\n * @internal\n */\n private [IncrementSymbol] = 0n;\n\n /**\n * The process ID that will be used by default in the generate method.\n * @internal\n */\n private [ProcessIdSymbol] = 1n;\n\n /**\n * The worker ID that will be used by default in the generate method.\n * @internal\n */\n private [WorkerIdSymbol] = 0n;\n\n /**\n * @param epoch - The epoch to use.\n */\n public constructor(epoch: number | bigint | Date) {\n this[EpochSymbol] = BigInt(epoch instanceof Date ? epoch.getTime() : epoch);\n this[EpochNumberSymbol] = Number(this[EpochSymbol]);\n }\n\n /**\n * The epoch for this snowflake, as a bigint.\n */\n public get epoch(): bigint {\n return this[EpochSymbol];\n }\n\n /**\n * The epoch for this snowflake, as a number.\n */\n public get epochNumber(): number {\n return this[EpochNumberSymbol];\n }\n\n /**\n * Gets or sets the configured process ID.\n */\n public get processId(): bigint {\n return this[ProcessIdSymbol];\n }\n\n public set processId(value: number | bigint) {\n this[ProcessIdSymbol] = BigInt(value) & MaximumProcessId;\n }\n\n /**\n * Gets or sets the configured worker ID.\n */\n public get workerId(): bigint {\n return this[WorkerIdSymbol];\n }\n\n public set workerId(value: number | bigint) {\n this[WorkerIdSymbol] = BigInt(value) & MaximumWorkerId;\n }\n\n /**\n * Generates a snowflake given an epoch and optionally a timestamp.\n *\n * **Note:** when `increment` is not provided it defaults to the private `increment` of the instance.\n *\n * @example\n * ```typescript\n * const epoch = new Date('2000-01-01T00:00:00.000Z');\n * const snowflake = new Snowflake(epoch).generate();\n * ```\n *\n * @param options - Options to pass into the generator, see {@link SnowflakeGenerateOptions}.\n * @returns A unique snowflake.\n */\n public generate({\n increment,\n timestamp = Date.now(),\n workerId = this[WorkerIdSymbol],\n processId = this[ProcessIdSymbol],\n }: SnowflakeGenerateOptions = {}) {\n if (timestamp instanceof Date) timestamp = BigInt(timestamp.getTime());\n else if (typeof timestamp === \"number\") timestamp = BigInt(timestamp);\n else if (typeof timestamp !== \"bigint\") {\n throw new TypeError(\n `\"timestamp\" argument must be a number, bigint, or Date (received ${typeof timestamp})`,\n );\n }\n\n if (typeof increment !== \"bigint\") {\n increment = this[IncrementSymbol];\n this[IncrementSymbol] = (increment + 1n) & MaximumIncrement;\n }\n\n // timestamp, workerId, processId, increment\n return (\n ((timestamp - this[EpochSymbol]) << 22n) |\n ((workerId & MaximumWorkerId) << 17n) |\n ((processId & MaximumProcessId) << 12n) |\n (increment & MaximumIncrement)\n );\n }\n\n /**\n * Deconstructs a snowflake.\n *\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 * @param id - The snowflake to deconstruct.\n * @returns A deconstructed snowflake.\n */\n public deconstruct(id: string | bigint): DeconstructedSnowflake {\n const bigIntId = BigInt(id);\n const epoch = this[EpochSymbol];\n return {\n id: bigIntId,\n timestamp: (bigIntId >> 22n) + epoch,\n workerId: (bigIntId >> 17n) & MaximumWorkerId,\n processId: (bigIntId >> 12n) & MaximumProcessId,\n increment: bigIntId & MaximumIncrement,\n epoch,\n };\n }\n\n /**\n * Retrieves the timestamp field's value from a snowflake.\n *\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): number {\n return Number((BigInt(id) >> 22n) + this.epoch);\n }\n\n /**\n * Returns a number indicating whether a reference snowflake comes before,\n * or after, or is same as the given snowflake in sort order.\n *\n * @example Sort snowflakes in ascending order\n * ```typescript\n * const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];\n * console.log(ids.sort((a, b) => Snowflake.compare(a, b)));\n * // → ['254360814063058944', '737141877803057244', '1056191128120082432'];\n * ```\n *\n * @example Sort snowflakes in descending order\n * ```typescript\n * const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];\n * console.log(ids.sort((a, b) => -Snowflake.compare(a, b)));\n * // → ['1056191128120082432', '737141877803057244', '254360814063058944'];\n * ```\n *\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(a: string | bigint, b: string | bigint): -1 | 0 | 1 {\n const typeA = typeof a;\n return typeA === typeof b\n ? typeA === \"string\"\n ? cmpString(a as string, b as string)\n : cmpBigInt(a as bigint, b as bigint)\n : cmpBigInt(BigInt(a), BigInt(b));\n }\n}\n\n/** @internal */\nfunction cmpBigInt(a: bigint, b: bigint) {\n return a === b ? 0 : a < b ? -1 : 1;\n}\n\n/** @internal */\nfunction cmpString(a: string, b: string) {\n return a === b ? 0 : a.length < b.length ? -1 : a.length > b.length ? 1 : a < b ? -1 : 1;\n}\n\n/**\n * Options for `Snowflake#generate`.\n */\nexport interface SnowflakeGenerateOptions {\n /**\n * Timestamp or date of the snowflake to generate.\n *\n * @defaultValue Date.now()\n */\n timestamp?: number | bigint | Date;\n /**\n * The increment to use.\n *\n * @defaultValue 0n\n * @remarks keep in mind that this bigint is auto-incremented between generate calls.\n */\n increment?: bigint;\n /**\n * The worker ID to use, will be truncated to 5 bits (0-31).\n *\n * @defaultValue 0n\n */\n workerId?: bigint;\n /**\n * The process ID to use, will be truncated to 5 bits (0-31).\n *\n * @defaultValue 1n\n */\n processId?: bigint;\n}\n\n/**\n * Object returned by `Snowflake#deconstruct`.\n */\nexport interface DeconstructedSnowflake {\n /**\n * The id in BigInt form.\n */\n id: bigint;\n /**\n * The timestamp stored in the snowflake.\n */\n timestamp: bigint;\n /**\n * The worker id stored in the snowflake.\n */\n workerId: bigint;\n /**\n * The process id stored in the snowflake.\n */\n processId: bigint;\n /**\n * The increment stored in the snowflake.\n */\n increment: bigint;\n /**\n * The epoch to use in the snowflake.\n */\n epoch: bigint;\n}\n","import { Snowflake } from \"./snowflake\";\n\n/**\n * A class for parsing snowflake ids using Discord's snowflake epoch.\n *\n * The Discord epoch is `1420070400000` (`2015-01-01T00:00:00.000Z`), see {@link https://discord.com/developers/docs/reference#snowflakes}.\n */\nexport const discordSnowflake = new Snowflake(1420070400000n);\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
|
|
4
|
+
// src/snowflake.ts
|
|
5
|
+
var IncrementSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.increment");
|
|
6
|
+
var EpochSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.epoch");
|
|
7
|
+
var EpochNumberSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.epoch.number");
|
|
8
|
+
var ProcessIdSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.processId");
|
|
9
|
+
var WorkerIdSymbol = /* @__PURE__ */ Symbol("@sodiumlabs/snowflake.workerId");
|
|
10
|
+
var MaximumWorkerId = 0b11111n;
|
|
11
|
+
var MaximumProcessId = 0b11111n;
|
|
12
|
+
var MaximumIncrement = 0b111111111111n;
|
|
13
|
+
var Snowflake = class {
|
|
14
|
+
static {
|
|
15
|
+
__name(this, "Snowflake");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Internal reference of the epoch passed in the constructor.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
[EpochSymbol];
|
|
22
|
+
/**
|
|
23
|
+
* Internal reference of the epoch passed in the constructor as a number.
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
[EpochNumberSymbol];
|
|
27
|
+
/**
|
|
28
|
+
* Internal incrementor for generating snowflakes.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
[IncrementSymbol] = 0n;
|
|
32
|
+
/**
|
|
33
|
+
* The process ID that will be used by default in the generate method.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
[ProcessIdSymbol] = 1n;
|
|
37
|
+
/**
|
|
38
|
+
* The worker ID that will be used by default in the generate method.
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
[WorkerIdSymbol] = 0n;
|
|
42
|
+
/**
|
|
43
|
+
* @param epoch - The epoch to use.
|
|
44
|
+
*/
|
|
45
|
+
constructor(epoch) {
|
|
46
|
+
this[EpochSymbol] = BigInt(epoch instanceof Date ? epoch.getTime() : epoch);
|
|
47
|
+
this[EpochNumberSymbol] = Number(this[EpochSymbol]);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The epoch for this snowflake, as a bigint.
|
|
51
|
+
*/
|
|
52
|
+
get epoch() {
|
|
53
|
+
return this[EpochSymbol];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The epoch for this snowflake, as a number.
|
|
57
|
+
*/
|
|
58
|
+
get epochNumber() {
|
|
59
|
+
return this[EpochNumberSymbol];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Gets or sets the configured process ID.
|
|
63
|
+
*/
|
|
64
|
+
get processId() {
|
|
65
|
+
return this[ProcessIdSymbol];
|
|
66
|
+
}
|
|
67
|
+
set processId(value) {
|
|
68
|
+
this[ProcessIdSymbol] = BigInt(value) & MaximumProcessId;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Gets or sets the configured worker ID.
|
|
72
|
+
*/
|
|
73
|
+
get workerId() {
|
|
74
|
+
return this[WorkerIdSymbol];
|
|
75
|
+
}
|
|
76
|
+
set workerId(value) {
|
|
77
|
+
this[WorkerIdSymbol] = BigInt(value) & MaximumWorkerId;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Generates a snowflake given an epoch and optionally a timestamp.
|
|
81
|
+
*
|
|
82
|
+
* **Note:** when `increment` is not provided it defaults to the private `increment` of the instance.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const epoch = new Date('2000-01-01T00:00:00.000Z');
|
|
87
|
+
* const snowflake = new Snowflake(epoch).generate();
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @param options - Options to pass into the generator, see {@link SnowflakeGenerateOptions}.
|
|
91
|
+
* @returns A unique snowflake.
|
|
92
|
+
*/
|
|
93
|
+
generate({
|
|
94
|
+
increment,
|
|
95
|
+
timestamp = Date.now(),
|
|
96
|
+
workerId = this[WorkerIdSymbol],
|
|
97
|
+
processId = this[ProcessIdSymbol]
|
|
98
|
+
} = {}) {
|
|
99
|
+
if (timestamp instanceof Date) timestamp = BigInt(timestamp.getTime());
|
|
100
|
+
else if (typeof timestamp === "number") timestamp = BigInt(timestamp);
|
|
101
|
+
else if (typeof timestamp !== "bigint") {
|
|
102
|
+
throw new TypeError(
|
|
103
|
+
`"timestamp" argument must be a number, bigint, or Date (received ${typeof timestamp})`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
if (typeof increment !== "bigint") {
|
|
107
|
+
increment = this[IncrementSymbol];
|
|
108
|
+
this[IncrementSymbol] = increment + 1n & MaximumIncrement;
|
|
109
|
+
}
|
|
110
|
+
return timestamp - this[EpochSymbol] << 22n | (workerId & MaximumWorkerId) << 17n | (processId & MaximumProcessId) << 12n | increment & MaximumIncrement;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Deconstructs a snowflake.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const epoch = new Date('2000-01-01T00:00:00.000Z');
|
|
118
|
+
* const snowflake = new Snowflake(epoch).deconstruct('3971046231244935168');
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @param id - The snowflake to deconstruct.
|
|
122
|
+
* @returns A deconstructed snowflake.
|
|
123
|
+
*/
|
|
124
|
+
deconstruct(id) {
|
|
125
|
+
const bigIntId = BigInt(id);
|
|
126
|
+
const epoch = this[EpochSymbol];
|
|
127
|
+
return {
|
|
128
|
+
id: bigIntId,
|
|
129
|
+
timestamp: (bigIntId >> 22n) + epoch,
|
|
130
|
+
workerId: bigIntId >> 17n & MaximumWorkerId,
|
|
131
|
+
processId: bigIntId >> 12n & MaximumProcessId,
|
|
132
|
+
increment: bigIntId & MaximumIncrement,
|
|
133
|
+
epoch
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Retrieves the timestamp field's value from a snowflake.
|
|
138
|
+
*
|
|
139
|
+
* @param id - The snowflake to get the timestamp value from.
|
|
140
|
+
* @returns The UNIX timestamp that is stored in `id`.
|
|
141
|
+
*/
|
|
142
|
+
timestampFrom(id) {
|
|
143
|
+
return Number((BigInt(id) >> 22n) + this.epoch);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Returns a number indicating whether a reference snowflake comes before,
|
|
147
|
+
* or after, or is same as the given snowflake in sort order.
|
|
148
|
+
*
|
|
149
|
+
* @example Sort snowflakes in ascending order
|
|
150
|
+
* ```typescript
|
|
151
|
+
* const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];
|
|
152
|
+
* console.log(ids.sort((a, b) => Snowflake.compare(a, b)));
|
|
153
|
+
* // → ['254360814063058944', '737141877803057244', '1056191128120082432'];
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @example Sort snowflakes in descending order
|
|
157
|
+
* ```typescript
|
|
158
|
+
* const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];
|
|
159
|
+
* console.log(ids.sort((a, b) => -Snowflake.compare(a, b)));
|
|
160
|
+
* // → ['1056191128120082432', '737141877803057244', '254360814063058944'];
|
|
161
|
+
* ```
|
|
162
|
+
*
|
|
163
|
+
* @param a - The first snowflake to compare.
|
|
164
|
+
* @param b - The second snowflake to compare.
|
|
165
|
+
* @returns `-1` if `a` is older than `b`, `0` if `a` and `b` are equals, `1` if `a` is newer than `b`.
|
|
166
|
+
*/
|
|
167
|
+
static compare(a, b) {
|
|
168
|
+
const typeA = typeof a;
|
|
169
|
+
return typeA === typeof b ? typeA === "string" ? cmpString(a, b) : cmpBigInt(a, b) : cmpBigInt(BigInt(a), BigInt(b));
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
function cmpBigInt(a, b) {
|
|
173
|
+
return a === b ? 0 : a < b ? -1 : 1;
|
|
174
|
+
}
|
|
175
|
+
__name(cmpBigInt, "cmpBigInt");
|
|
176
|
+
function cmpString(a, b) {
|
|
177
|
+
return a === b ? 0 : a.length < b.length ? -1 : a.length > b.length ? 1 : a < b ? -1 : 1;
|
|
178
|
+
}
|
|
179
|
+
__name(cmpString, "cmpString");
|
|
180
|
+
|
|
181
|
+
// src/discord-snowflake.ts
|
|
182
|
+
var discordSnowflake = new Snowflake(1420070400000n);
|
|
183
|
+
export {
|
|
184
|
+
MaximumIncrement,
|
|
185
|
+
MaximumProcessId,
|
|
186
|
+
MaximumWorkerId,
|
|
187
|
+
Snowflake,
|
|
188
|
+
discordSnowflake
|
|
189
|
+
};
|
|
190
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/snowflake.ts","../src/discord-snowflake.ts"],"sourcesContent":["const IncrementSymbol = Symbol(\"@sodiumlabs/snowflake.increment\");\nconst EpochSymbol = Symbol(\"@sodiumlabs/snowflake.epoch\");\nconst EpochNumberSymbol = Symbol(\"@sodiumlabs/snowflake.epoch.number\");\nconst ProcessIdSymbol = Symbol(\"@sodiumlabs/snowflake.processId\");\nconst WorkerIdSymbol = Symbol(\"@sodiumlabs/snowflake.workerId\");\n\n/**\n * The maximum value the `workerId` field accepts in snowflakes.\n */\nexport const MaximumWorkerId = 0b11111n;\n\n/**\n * The maximum value the `processId` field accepts in snowflakes.\n */\nexport const MaximumProcessId = 0b11111n;\n\n/**\n * The maximum value the `increment` field accepts in snowflakes.\n */\nexport const MaximumIncrement = 0b111111111111n;\n\n/**\n * A class for generating and deconstructing snowflakes.\n *\n * A {@link https://en.wikipedia.org/wiki/Snowflake_ID | 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 */\nexport class Snowflake {\n /**\n * Internal reference of the epoch passed in the constructor.\n * @internal\n */\n private readonly [EpochSymbol]: bigint;\n\n /**\n * Internal reference of the epoch passed in the constructor as a number.\n * @internal\n */\n private readonly [EpochNumberSymbol]: number;\n\n /**\n * Internal incrementor for generating snowflakes.\n * @internal\n */\n private [IncrementSymbol] = 0n;\n\n /**\n * The process ID that will be used by default in the generate method.\n * @internal\n */\n private [ProcessIdSymbol] = 1n;\n\n /**\n * The worker ID that will be used by default in the generate method.\n * @internal\n */\n private [WorkerIdSymbol] = 0n;\n\n /**\n * @param epoch - The epoch to use.\n */\n public constructor(epoch: number | bigint | Date) {\n this[EpochSymbol] = BigInt(epoch instanceof Date ? epoch.getTime() : epoch);\n this[EpochNumberSymbol] = Number(this[EpochSymbol]);\n }\n\n /**\n * The epoch for this snowflake, as a bigint.\n */\n public get epoch(): bigint {\n return this[EpochSymbol];\n }\n\n /**\n * The epoch for this snowflake, as a number.\n */\n public get epochNumber(): number {\n return this[EpochNumberSymbol];\n }\n\n /**\n * Gets or sets the configured process ID.\n */\n public get processId(): bigint {\n return this[ProcessIdSymbol];\n }\n\n public set processId(value: number | bigint) {\n this[ProcessIdSymbol] = BigInt(value) & MaximumProcessId;\n }\n\n /**\n * Gets or sets the configured worker ID.\n */\n public get workerId(): bigint {\n return this[WorkerIdSymbol];\n }\n\n public set workerId(value: number | bigint) {\n this[WorkerIdSymbol] = BigInt(value) & MaximumWorkerId;\n }\n\n /**\n * Generates a snowflake given an epoch and optionally a timestamp.\n *\n * **Note:** when `increment` is not provided it defaults to the private `increment` of the instance.\n *\n * @example\n * ```typescript\n * const epoch = new Date('2000-01-01T00:00:00.000Z');\n * const snowflake = new Snowflake(epoch).generate();\n * ```\n *\n * @param options - Options to pass into the generator, see {@link SnowflakeGenerateOptions}.\n * @returns A unique snowflake.\n */\n public generate({\n increment,\n timestamp = Date.now(),\n workerId = this[WorkerIdSymbol],\n processId = this[ProcessIdSymbol],\n }: SnowflakeGenerateOptions = {}) {\n if (timestamp instanceof Date) timestamp = BigInt(timestamp.getTime());\n else if (typeof timestamp === \"number\") timestamp = BigInt(timestamp);\n else if (typeof timestamp !== \"bigint\") {\n throw new TypeError(\n `\"timestamp\" argument must be a number, bigint, or Date (received ${typeof timestamp})`,\n );\n }\n\n if (typeof increment !== \"bigint\") {\n increment = this[IncrementSymbol];\n this[IncrementSymbol] = (increment + 1n) & MaximumIncrement;\n }\n\n // timestamp, workerId, processId, increment\n return (\n ((timestamp - this[EpochSymbol]) << 22n) |\n ((workerId & MaximumWorkerId) << 17n) |\n ((processId & MaximumProcessId) << 12n) |\n (increment & MaximumIncrement)\n );\n }\n\n /**\n * Deconstructs a snowflake.\n *\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 * @param id - The snowflake to deconstruct.\n * @returns A deconstructed snowflake.\n */\n public deconstruct(id: string | bigint): DeconstructedSnowflake {\n const bigIntId = BigInt(id);\n const epoch = this[EpochSymbol];\n return {\n id: bigIntId,\n timestamp: (bigIntId >> 22n) + epoch,\n workerId: (bigIntId >> 17n) & MaximumWorkerId,\n processId: (bigIntId >> 12n) & MaximumProcessId,\n increment: bigIntId & MaximumIncrement,\n epoch,\n };\n }\n\n /**\n * Retrieves the timestamp field's value from a snowflake.\n *\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): number {\n return Number((BigInt(id) >> 22n) + this.epoch);\n }\n\n /**\n * Returns a number indicating whether a reference snowflake comes before,\n * or after, or is same as the given snowflake in sort order.\n *\n * @example Sort snowflakes in ascending order\n * ```typescript\n * const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];\n * console.log(ids.sort((a, b) => Snowflake.compare(a, b)));\n * // → ['254360814063058944', '737141877803057244', '1056191128120082432'];\n * ```\n *\n * @example Sort snowflakes in descending order\n * ```typescript\n * const ids = ['737141877803057244', '1056191128120082432', '254360814063058944'];\n * console.log(ids.sort((a, b) => -Snowflake.compare(a, b)));\n * // → ['1056191128120082432', '737141877803057244', '254360814063058944'];\n * ```\n *\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(a: string | bigint, b: string | bigint): -1 | 0 | 1 {\n const typeA = typeof a;\n return typeA === typeof b\n ? typeA === \"string\"\n ? cmpString(a as string, b as string)\n : cmpBigInt(a as bigint, b as bigint)\n : cmpBigInt(BigInt(a), BigInt(b));\n }\n}\n\n/** @internal */\nfunction cmpBigInt(a: bigint, b: bigint) {\n return a === b ? 0 : a < b ? -1 : 1;\n}\n\n/** @internal */\nfunction cmpString(a: string, b: string) {\n return a === b ? 0 : a.length < b.length ? -1 : a.length > b.length ? 1 : a < b ? -1 : 1;\n}\n\n/**\n * Options for `Snowflake#generate`.\n */\nexport interface SnowflakeGenerateOptions {\n /**\n * Timestamp or date of the snowflake to generate.\n *\n * @defaultValue Date.now()\n */\n timestamp?: number | bigint | Date;\n /**\n * The increment to use.\n *\n * @defaultValue 0n\n * @remarks keep in mind that this bigint is auto-incremented between generate calls.\n */\n increment?: bigint;\n /**\n * The worker ID to use, will be truncated to 5 bits (0-31).\n *\n * @defaultValue 0n\n */\n workerId?: bigint;\n /**\n * The process ID to use, will be truncated to 5 bits (0-31).\n *\n * @defaultValue 1n\n */\n processId?: bigint;\n}\n\n/**\n * Object returned by `Snowflake#deconstruct`.\n */\nexport interface DeconstructedSnowflake {\n /**\n * The id in BigInt form.\n */\n id: bigint;\n /**\n * The timestamp stored in the snowflake.\n */\n timestamp: bigint;\n /**\n * The worker id stored in the snowflake.\n */\n workerId: bigint;\n /**\n * The process id stored in the snowflake.\n */\n processId: bigint;\n /**\n * The increment stored in the snowflake.\n */\n increment: bigint;\n /**\n * The epoch to use in the snowflake.\n */\n epoch: bigint;\n}\n","import { Snowflake } from \"./snowflake\";\n\n/**\n * A class for parsing snowflake ids using Discord's snowflake epoch.\n *\n * The Discord epoch is `1420070400000` (`2015-01-01T00:00:00.000Z`), see {@link https://discord.com/developers/docs/reference#snowflakes}.\n */\nexport const discordSnowflake = new Snowflake(1420070400000n);\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
+
"name": "@sodiumlabs/snowflake",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Snowflake utility package",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"id",
|
|
8
|
+
"snowflake",
|
|
9
|
+
"sodium",
|
|
10
|
+
"sodiumlabs",
|
|
11
|
+
"typescript",
|
|
12
|
+
"utility"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/sodium-labs/utilities/tree/main/packages/snowflake",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/sodium-labs/utilities/issues"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "sodiumlabs",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/sodium-labs/utilities.git",
|
|
23
|
+
"directory": "packages/snowflake"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"module": "./dist/index.mjs",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"require": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"import": {
|
|
38
|
+
"types": "./dist/index.d.mts",
|
|
39
|
+
"default": "./dist/index.mjs"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsup",
|
|
45
|
+
"build:docs": "tsc -p tsconfig.docs.json",
|
|
46
|
+
"lint": "tsc --noEmit && oxlint && oxfmt --check",
|
|
47
|
+
"fmt": "oxfmt",
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"docs": "npm run build:docs && api-extractor run --local"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@microsoft/api-extractor": "^7.55.2",
|
|
53
|
+
"tsup": "^8.5.1",
|
|
54
|
+
"typescript": "^5.9.3"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=18"
|
|
58
|
+
}
|
|
59
|
+
}
|