@tabsircg/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/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/package.json +33 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type SnowflakeId<T extends boolean> = T extends true ? string : bigint;
|
|
2
|
+
/**
|
|
3
|
+
* Creates a Snowflake ID generator with consistent sequence tracking.
|
|
4
|
+
*
|
|
5
|
+
* @param workerId - Unique worker identifier
|
|
6
|
+
* @param datacenterId - Unique datacenter identifier
|
|
7
|
+
* @returns Function that generates unique Snowflake IDs
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const generator = createSnowflakeGenerator(1, 1);
|
|
11
|
+
* const id = generator(); // 1234567890123456789n
|
|
12
|
+
* const stringId = generator(true); // "1234567890123456789"
|
|
13
|
+
*/
|
|
14
|
+
export declare const createSnowflakeGenerator: (workerId: number, datacenterId: number) => <T extends boolean = false>(returnAsString?: T) => SnowflakeId<T>;
|
|
15
|
+
/**
|
|
16
|
+
* Generates a Snowflake ID for a specific timestamp (used for cleanup thresholds).
|
|
17
|
+
*
|
|
18
|
+
* @param timestamp - Unix timestamp in milliseconds
|
|
19
|
+
* @param workerId - Worker ID (default: 0 for minimum possible ID)
|
|
20
|
+
* @param datacenterId - Datacenter ID (default: 0 for minimum possible ID)
|
|
21
|
+
* @param sequence - Sequence number (default: 0 for minimum possible ID)
|
|
22
|
+
* @returns Snowflake ID as BigInt
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Get threshold for deleting records older than 30 days
|
|
26
|
+
* const thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000);
|
|
27
|
+
* const threshold = generateTimestampSnowflake(thirtyDaysAgo);
|
|
28
|
+
*/
|
|
29
|
+
export declare const generateTimestampSnowflake: (timestamp: number, workerId: number, datacenterId: number, sequence: number) => bigint;
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,IAAI,CAAC,SAAS,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9E;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,wBAAwB,GACnC,UAAU,MAAM,EAChB,cAAc,MAAM,MAyBZ,CAAC,SAAS,OAAO,GAAG,KAAK,EAAE,iBAAiB,CAAC,KAAG,WAAW,CAAC,CAAC,CA+BtE,CAAC;AAEF;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,0BAA0B,GACrC,WAAW,MAAM,EACjB,UAAU,MAAM,EAChB,cAAc,MAAM,EACpB,UAAU,MAAM,WAUjB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const SNOWFLAKE_EPOCH = 1770479980106;
|
|
2
|
+
const SNOWFLAKE_BITS = {
|
|
3
|
+
SEQUENCE: 11,
|
|
4
|
+
WORKER_ID: 4,
|
|
5
|
+
DATACENTER_ID: 5,
|
|
6
|
+
};
|
|
7
|
+
const SNOWFLAKE_SHIFTS = {
|
|
8
|
+
WORKER_ID: SNOWFLAKE_BITS.SEQUENCE,
|
|
9
|
+
DATACENTER_ID: SNOWFLAKE_BITS.SEQUENCE + SNOWFLAKE_BITS.WORKER_ID,
|
|
10
|
+
TIMESTAMP: SNOWFLAKE_BITS.SEQUENCE +
|
|
11
|
+
SNOWFLAKE_BITS.WORKER_ID +
|
|
12
|
+
SNOWFLAKE_BITS.DATACENTER_ID,
|
|
13
|
+
};
|
|
14
|
+
const SNOWFLAKE_MASKS = {
|
|
15
|
+
SEQUENCE: (1 << SNOWFLAKE_BITS.SEQUENCE) - 1,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Creates a Snowflake ID generator with consistent sequence tracking.
|
|
19
|
+
*
|
|
20
|
+
* @param workerId - Unique worker identifier
|
|
21
|
+
* @param datacenterId - Unique datacenter identifier
|
|
22
|
+
* @returns Function that generates unique Snowflake IDs
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const generator = createSnowflakeGenerator(1, 1);
|
|
26
|
+
* const id = generator(); // 1234567890123456789n
|
|
27
|
+
* const stringId = generator(true); // "1234567890123456789"
|
|
28
|
+
*/
|
|
29
|
+
export const createSnowflakeGenerator = (workerId, datacenterId) => {
|
|
30
|
+
const maxWorkerId = (1 << SNOWFLAKE_BITS.WORKER_ID) - 1;
|
|
31
|
+
const maxDatacenterId = (1 << SNOWFLAKE_BITS.DATACENTER_ID) - 1;
|
|
32
|
+
if (workerId < 0 || workerId > maxWorkerId) {
|
|
33
|
+
throw new Error(`Worker ID must be between 0 and ${maxWorkerId}`);
|
|
34
|
+
}
|
|
35
|
+
if (datacenterId < 0 || datacenterId > maxDatacenterId) {
|
|
36
|
+
throw new Error(`Datacenter ID must be between 0 and ${maxDatacenterId}`);
|
|
37
|
+
}
|
|
38
|
+
let sequence = 0;
|
|
39
|
+
let lastTimestamp = -1;
|
|
40
|
+
const getCurrentTimestamp = () => Date.now();
|
|
41
|
+
const waitForNextMillis = (lastTimestamp) => {
|
|
42
|
+
let timestamp = getCurrentTimestamp();
|
|
43
|
+
while (timestamp <= lastTimestamp) {
|
|
44
|
+
timestamp = getCurrentTimestamp();
|
|
45
|
+
}
|
|
46
|
+
return timestamp;
|
|
47
|
+
};
|
|
48
|
+
return (returnAsString) => {
|
|
49
|
+
let timestamp = getCurrentTimestamp();
|
|
50
|
+
if (timestamp < lastTimestamp) {
|
|
51
|
+
throw new Error(`Clock moved backwards. Refusing to generate id for ${lastTimestamp - timestamp} milliseconds`);
|
|
52
|
+
}
|
|
53
|
+
if (timestamp === lastTimestamp) {
|
|
54
|
+
sequence = (sequence + 1) & SNOWFLAKE_MASKS.SEQUENCE;
|
|
55
|
+
if (sequence === 0) {
|
|
56
|
+
timestamp = waitForNextMillis(lastTimestamp);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
sequence = 0;
|
|
61
|
+
}
|
|
62
|
+
lastTimestamp = timestamp;
|
|
63
|
+
const id = (BigInt(timestamp - SNOWFLAKE_EPOCH) <<
|
|
64
|
+
BigInt(SNOWFLAKE_SHIFTS.TIMESTAMP)) +
|
|
65
|
+
(BigInt(datacenterId) << BigInt(SNOWFLAKE_SHIFTS.DATACENTER_ID)) +
|
|
66
|
+
(BigInt(workerId) << BigInt(SNOWFLAKE_SHIFTS.WORKER_ID)) +
|
|
67
|
+
BigInt(sequence);
|
|
68
|
+
return (returnAsString ? id.toString() : id);
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Generates a Snowflake ID for a specific timestamp (used for cleanup thresholds).
|
|
73
|
+
*
|
|
74
|
+
* @param timestamp - Unix timestamp in milliseconds
|
|
75
|
+
* @param workerId - Worker ID (default: 0 for minimum possible ID)
|
|
76
|
+
* @param datacenterId - Datacenter ID (default: 0 for minimum possible ID)
|
|
77
|
+
* @param sequence - Sequence number (default: 0 for minimum possible ID)
|
|
78
|
+
* @returns Snowflake ID as BigInt
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* // Get threshold for deleting records older than 30 days
|
|
82
|
+
* const thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000);
|
|
83
|
+
* const threshold = generateTimestampSnowflake(thirtyDaysAgo);
|
|
84
|
+
*/
|
|
85
|
+
export const generateTimestampSnowflake = (timestamp, workerId, datacenterId, sequence) => {
|
|
86
|
+
const id = (BigInt(timestamp - SNOWFLAKE_EPOCH) <<
|
|
87
|
+
BigInt(SNOWFLAKE_SHIFTS.TIMESTAMP)) +
|
|
88
|
+
(BigInt(datacenterId) << BigInt(SNOWFLAKE_SHIFTS.DATACENTER_ID)) +
|
|
89
|
+
(BigInt(workerId) << BigInt(SNOWFLAKE_SHIFTS.WORKER_ID)) +
|
|
90
|
+
BigInt(sequence);
|
|
91
|
+
return id;
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tabsircg/snowflake",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Lightweight Snowflake ID generator for Node.js",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "Tabsir CG",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"prepublishOnly": "tsc"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"snowflake",
|
|
25
|
+
"id",
|
|
26
|
+
"generator",
|
|
27
|
+
"distributed",
|
|
28
|
+
"unique-id"
|
|
29
|
+
],
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"typescript": "^5.9.3"
|
|
32
|
+
}
|
|
33
|
+
}
|