simpleflakes 4.1.0 → 4.1.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 CHANGED
@@ -7,16 +7,16 @@
7
7
  [![Bundle Size](https://img.shields.io/bundlephobia/minzip/simpleflakes?style=flat)](https://bundlephobia.com/package/simpleflakes)
8
8
  [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
9
9
  [![Node.js](https://img.shields.io/badge/node-%3E%3D16.0.0-brightgreen.svg?style=flat)](https://nodejs.org/)
10
- [![Performance](https://img.shields.io/badge/performance-8.8M%20ops%2Fsec-brightgreen?style=flat&logo=javascript)](https://github.com/leodutra/simpleflakes/actions/workflows/ci.yml)
10
+ [![Performance](https://img.shields.io/badge/performance-11.5M%20ops%2Fsec-brightgreen?style=flat&logo=javascript)](https://github.com/leodutra/simpleflakes/actions/workflows/ci.yml)
11
11
  [![Last Commit](https://img.shields.io/github/last-commit/leodutra/simpleflakes.svg?style=flat)](https://github.com/leodutra/simpleflakes)
12
12
  [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fleodutra%2Fsimpleflakes.svg?type=shield&issueType=license)](https://app.fossa.io/projects/git%2Bgithub.com%2Fleodutra%2Fsimpleflakes?ref=badge_shield&issueType=license)
13
13
 
14
14
  > **Fast, lightweight, and reliable distributed 64-bit ID generation for Node.js and the web**
15
- > Zero dependencies • TypeScript-ready • 8.8M+ ops/sec performance
15
+ > Zero dependencies • TypeScript-ready • 10M+ ops/sec performance
16
16
 
17
17
  ## Features
18
18
 
19
- - ⚡ **8.8M+ ops/sec** - Ultra-fast performance
19
+ - ⚡ **10M+ ops/sec** - Ultra-fast performance
20
20
  - 🔢 **Time-oriented 64-bit IDs** - Globally unique, sortable by creation time
21
21
  - 0️⃣ **Zero dependencies** - Pure JavaScript, lightweight bundle
22
22
  - 🏷️ **TypeScript-ready** - Full type safety and universal module support
@@ -157,13 +157,29 @@ This gives you:
157
157
 
158
158
  This library is optimized for speed:
159
159
 
160
- ```javascript
161
- // Benchmark results (operations per second)
162
- simpleflake() // ~8.8M+ ops/sec
163
- parseSimpleflake() // ~3.9M+ ops/sec
164
- binary() // ~26M+ ops/sec
160
+ | Operation | Ops/sec | Time/op |
161
+ |-----------|---------|---------|
162
+ | `simpleflake()` | 11,468,350 | 87.20 ns |
163
+ | `simpleflake(timestamp, randomBits, epoch)` | 14,557,764 | 68.69 ns |
164
+ | `binary()` | 22,794,523 | 43.87 ns |
165
+ | `BigInt()` | 15,933,159 | 62.76 ns |
166
+ | `parseSimpleflake()` | 6,722,882 | 148.75 ns |
167
+
168
+ Benchmark command:
169
+
170
+ ```bash
171
+ npm run benchmark
165
172
  ```
166
173
 
174
+ Benchmark environment:
175
+
176
+ - Node.js v24.14.1
177
+ - Linux 6.6.87.2-microsoft-standard-WSL2 (WSL2)
178
+ - AMD Ryzen 7 5800X3D 8-Core Processor
179
+ - 8 cores / 16 threads
180
+
181
+ Results will vary across CPUs, Node.js versions, power profiles, and native Linux vs. WSL2 environments.
182
+
167
183
  Perfect for high-throughput applications requiring millions of IDs per second.
168
184
 
169
185
  ## Architecture
@@ -1 +1 @@
1
- {"version":3,"file":"simpleflakes.d.ts","sourceRoot":"","sources":["../src/simpleflakes.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,iBAAiB,gBAAgB,CAAC;AA4DxC;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,EAAE,GAAE,MAAM,GAAG,MAAmB,EAChC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAC5B,KAAK,GAAE,MAAM,GAAG,MAA0B,GACzC,MAAM,CAOR;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAC/B,OAAO,GAAE,OAAc,GACtB,MAAM,CAKR;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAC9B,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,MAAM,EAAE,MAAM,GAAG,MAAM,GACtB,MAAM,CAKR;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAOlD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAC9B,iBAAiB,CAWnB;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAC;;;;;;;;;AAG7B,wBAOE"}
1
+ {"version":3,"file":"simpleflakes.d.ts","sourceRoot":"","sources":["../src/simpleflakes.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,iBAAiB,gBAAgB,CAAC;AA2DxC;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,EAAE,GAAE,MAAM,GAAG,MAAmB,EAChC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAC5B,KAAK,GAAE,MAAM,GAAG,MAA0B,GACzC,MAAM,CAOR;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAC/B,OAAO,GAAE,OAAc,GACtB,MAAM,CAKR;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAC9B,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,MAAM,EAAE,MAAM,GAAG,MAAM,GACtB,MAAM,CAKR;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,SAAwB,SAAS,EAAE,MAAM,CAAC;IAC1C,SAAwB,UAAU,EAAE,MAAM,CAAC;gBAE/B,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAOlD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAC9B,iBAAiB,CAWnB;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAC;;;;;;;;;AAG7B,wBAOE"}
@@ -1,3 +1,3 @@
1
- "use strict";function _define_property(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}Object.defineProperty(exports,"__esModule",{value:!0}),function(e,t){for(var r in t)Object.defineProperty(e,r,{enumerable:!0,get:Object.getOwnPropertyDescriptor(t,r).get})}(exports,{get SIMPLEFLAKE_EPOCH(){return SIMPLEFLAKE_EPOCH},get SimpleflakeStruct(){return SimpleflakeStruct},get binary(){return binary},get default(){return _default},get extractBits(){return extractBits},get parseSimpleflake(){return parseSimpleflake},get simpleflake(){return simpleflake}});const SIMPLEFLAKE_EPOCH=946684800000n;let randomBuffer=new Uint32Array(1024),randomBufferIndex=1024;function toBigInt(e){return"bigint"==typeof e?e:BigInt(e)}function getRandomSource(){let e=globalThis.crypto;if(e)return e;if("function"==typeof require){let{webcrypto:e}=require("node:crypto");if(e)return e}throw Error("Cryptographically secure random values are unavailable in this environment.")}function refillRandomBuffer(){getRandomSource().getRandomValues(randomBuffer),randomBufferIndex=0}function random23(){return randomBufferIndex>=1024&&refillRandomBuffer(),BigInt(8388607&randomBuffer[randomBufferIndex++])}function simpleflake(e=Date.now(),t,r=SIMPLEFLAKE_EPOCH){return toBigInt(e)-toBigInt(r)<<23n|(null==t?random23():toBigInt(t))}function binary(e,t=!0){let r=toBigInt(e).toString(2);return t&&r.length<64?"0000000000000000000000000000000000000000000000000000000000000000".substr(0,64-r.length)+r:r}function extractBits(e,t,r){let n=toBigInt(t),i=toBigInt(r);return toBigInt(e)>>n&(1n<<i)-1n}class SimpleflakeStruct{constructor(e,t){if(_define_property(this,"timestamp",void 0),_define_property(this,"randomBits",void 0),null==e||null==t)throw Error("Missing argument for SimpleflakeStruct.");this.timestamp=e,this.randomBits=t}}function parseSimpleflake(e){return new SimpleflakeStruct(extractBits(e,23n,41n)+SIMPLEFLAKE_EPOCH,extractBits(e,0n,23n))}const _default={binary,extractBits,parseSimpleflake,SIMPLEFLAKE_EPOCH,simpleflake,SimpleflakeStruct};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),function(e,t){for(var r in t)Object.defineProperty(e,r,{enumerable:!0,get:Object.getOwnPropertyDescriptor(t,r).get})}(exports,{get SIMPLEFLAKE_EPOCH(){return SIMPLEFLAKE_EPOCH},get SimpleflakeStruct(){return SimpleflakeStruct},get binary(){return binary},get default(){return _default},get extractBits(){return extractBits},get parseSimpleflake(){return parseSimpleflake},get simpleflake(){return simpleflake}});const SIMPLEFLAKE_EPOCH=946684800000n;let randomBuffer=new Uint32Array(1024),randomBufferIndex=1024;function toBigInt(e){return"bigint"==typeof e?e:BigInt(e)}function getRandomSource(){let e=globalThis.crypto;if(e)return e;try{return require("node:crypto").webcrypto}catch{throw Error("Cryptographically secure random values are unavailable in this environment.")}}function refillRandomBuffer(){getRandomSource().getRandomValues(randomBuffer),randomBufferIndex=0}function random23(){randomBufferIndex>=1024&&refillRandomBuffer();let e=randomBuffer[randomBufferIndex];return randomBufferIndex+=1,BigInt(8388607&e)}function simpleflake(e=Date.now(),t,r=SIMPLEFLAKE_EPOCH){return toBigInt(e)-toBigInt(r)<<23n|(null==t?random23():toBigInt(t))}function binary(e,t=!0){let r=toBigInt(e).toString(2);return t&&r.length<64?"0000000000000000000000000000000000000000000000000000000000000000".substr(0,64-r.length)+r:r}function extractBits(e,t,r){let n=toBigInt(t),i=toBigInt(r);return toBigInt(e)>>n&(1n<<i)-1n}class SimpleflakeStruct{constructor(e,t){if(null==e||null==t)throw Error("Missing argument for SimpleflakeStruct.");this.timestamp=e,this.randomBits=t}}function parseSimpleflake(e){return new SimpleflakeStruct(extractBits(e,23n,41n)+SIMPLEFLAKE_EPOCH,extractBits(e,0n,23n))}const _default={binary,extractBits,parseSimpleflake,SIMPLEFLAKE_EPOCH,simpleflake,SimpleflakeStruct};
2
2
 
3
3
  //# sourceMappingURL=simpleflakes.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/simpleflakes.ts"],"names":["SIMPLEFLAKE_EPOCH","SimpleflakeStruct","binary","extractBits","parseSimpleflake","simpleflake","randomBuffer","Uint32Array","randomBufferIndex","toBigInt","value","BigInt","getRandomSource","globalCrypto","globalThis","crypto","require","webcrypto","Error","refillRandomBuffer","getRandomValues","random23","ts","Date","now","randomBits","epoch","padding","binValue","toString","length","CACHE_64_BIT_ZEROS","substr","data","shift","shiftN","lengthN","timestamp","flake"],"mappings":"8UAuJSA,2BAAAA,uBAlCIC,2BAAAA,uBA/BGC,gBAAAA,YAoEhB,iBAAA,cAnDgBC,qBAAAA,iBAgCAC,0BAAAA,sBApEAC,qBAAAA,eAnEhB,MAAML,kBAAoB,YAAA,AAAa,CAAA,CAmBvC,IAAIM,aAAe,IAAIC,YAjBI,MAkBvBC,kBAlBuB,KAoB3B,SAASC,SAASC,CAA+B,EAC/C,MAAO,AAAiB,UAAjB,OAAOA,EAAqBA,EAAQC,OAAOD,EACpD,CAEA,SAASE,kBACP,IAAMC,EAAe,AAACC,WAEnBC,MAAM,CACT,GAAIF,EACF,OAAOA,EAGT,GAAI,AAAmB,YAAnB,OAAOG,QAAwB,CACjC,GAAM,CAAEC,UAAAA,CAAS,CAAE,CAAGD,QAAQ,eAG9B,GAAIC,EACF,OAAOA,CAEX,CAEA,MAAM,AAAIC,MACR,8EAEJ,CAEA,SAASC,qBACPP,kBAAkBQ,eAAe,CAACd,cAClCE,kBAAoB,CACtB,CAEA,SAASa,WAIP,OAHIb,mBApDqB,MAqDvBW,qBAEKR,OAxDkB,AAwDXL,QAAAA,YAAY,CAACE,oBAAoB,CACjD,CASO,SAASH,YACdiB,EAAsBC,KAAKC,GAAG,EAAE,CAChCC,CAA4B,CAC5BC,EAAyB1B,iBAAiB,EAI1C,OACE,AAAES,SAASa,GAAMb,SAASiB,IAnEM,EAAA,AAAG,CAAA,CAoElCD,CAAAA,AAAc,MAAdA,EAAqBJ,WAAaZ,SAASgB,EAAU,CAE1D,CAQO,SAASvB,OACdQ,CAA+B,CAC/BiB,EAAmB,CAAA,CAAI,EAEvB,IAAMC,EAAWnB,SAASC,GAAOmB,QAAQ,CAAC,GAC1C,OAAOF,GAAWC,EAASE,MAAM,CAAG,GAhFpC,AAiFIC,mEAAmBC,MAAM,CAAC,EAAG,GAAKJ,EAASE,MAAM,EAAIF,EACrDA,CACN,CASO,SAASzB,YACd8B,CAA8B,CAC9BC,CAAsB,CACtBJ,CAAuB,EAEvB,IAAMK,EAAS1B,SAASyB,GAClBE,EAAU3B,SAASqB,GAEzB,OAAO,AAACrB,SAASwB,IAASE,EAAW,AAAC,CAAA,CAAA,AAAE,CAAA,EAAIC,CAAM,EAAK,CAAA,AAAE,CAAA,AAC3D,CAKO,MAAMnC,kBAIX,YAAYoC,CAAiB,CAAEZ,CAAkB,CAAE,CACjD,GAJF,sBAAgBY,YAAhB,KAAA,GACA,sBAAgBZ,aAAhB,KAAA,GAGMY,AAAa,MAAbA,GAAqBZ,AAAc,MAAdA,EACvB,MAAM,AAAIP,MAAM,0CAElB,CAAA,IAAI,CAACmB,SAAS,CAAGA,EACjB,IAAI,CAACZ,UAAU,CAAGA,CACpB,CACF,CAOO,SAASrB,iBACdkC,CAA+B,EAE/B,OAAO,IAAIrC,kBAETE,YACEmC,EArI8B,EAAA,AAAG,CAAA,CAJF,EAAA,AAAG,CAAA,EA4IhCtC,kBAEJG,YAAYmC,EA3IiB,CAAA,AAAE,CAAA,CAFD,EAAA,AAAG,CAAA,EA+IrC,OAMA,SAAe,CACbpC,OACAC,YACAC,iBACAJ,kBACAK,YACAJ,iBACF","file":"simpleflakes.js","sourcesContent":["const SIMPLEFLAKE_EPOCH = 946684800000n; // Date.UTC(2000, 0, 1) == epoch ms, since 1 Jan 2000 00:00\nconst UNSIGNED_23BIT_MAX = 8388607; // (Math.pow(2, 23) - 1) >> 0\nconst RANDOM_BUFFER_SIZE = 1024;\n\nconst SIMPLEFLAKE_TIMESTAMP_LENGTH = 41n;\nconst SIMPLEFLAKE_RANDOM_LENGTH = 23n;\n\nconst SIMPLEFLAKE_RANDOM_SHIFT = 0n;\nconst SIMPLEFLAKE_TIMESTAMP_SHIFT = 23n;\n\nconst CACHE_64_BIT_ZEROS =\n \"0000000000000000000000000000000000000000000000000000000000000000\";\n\ninterface RandomSource {\n getRandomValues<T extends ArrayBufferView>(array: T): T;\n}\n\ndeclare const require: ((moduleName: string) => unknown) | undefined;\n\nlet randomBuffer = new Uint32Array(RANDOM_BUFFER_SIZE);\nlet randomBufferIndex = RANDOM_BUFFER_SIZE;\n\nfunction toBigInt(value: bigint | number | string): bigint {\n return typeof value === \"bigint\" ? value : BigInt(value);\n}\n\nfunction getRandomSource(): RandomSource {\n const globalCrypto = (globalThis as typeof globalThis & {\n crypto?: RandomSource;\n }).crypto;\n if (globalCrypto) {\n return globalCrypto;\n }\n\n if (typeof require === \"function\") {\n const { webcrypto } = require([\"node\", \"crypto\"].join(\":\")) as {\n webcrypto?: RandomSource;\n };\n if (webcrypto) {\n return webcrypto;\n }\n }\n\n throw new Error(\n \"Cryptographically secure random values are unavailable in this environment.\"\n );\n}\n\nfunction refillRandomBuffer(): void {\n getRandomSource().getRandomValues(randomBuffer);\n randomBufferIndex = 0;\n}\n\nfunction random23(): bigint {\n if (randomBufferIndex >= RANDOM_BUFFER_SIZE) {\n refillRandomBuffer();\n }\n return BigInt(randomBuffer[randomBufferIndex++] & UNSIGNED_23BIT_MAX);\n}\n\n/**\n * Generates a simpleflake ID\n * @param ts - Timestamp in milliseconds (defaults to current time)\n * @param randomBits - Random bits for the ID (defaults to a cryptographically secure random value)\n * @param epoch - Epoch timestamp in milliseconds (defaults to SIMPLEFLAKE_EPOCH)\n * @returns Generated simpleflake as a BigInt\n */\nexport function simpleflake(\n ts: number | bigint = Date.now(),\n randomBits?: number | bigint,\n epoch: number | bigint = SIMPLEFLAKE_EPOCH\n): bigint {\n // Use bitwise OR instead of addition since bit ranges don't overlap\n\n return (\n ((toBigInt(ts) - toBigInt(epoch)) << SIMPLEFLAKE_TIMESTAMP_SHIFT) |\n (randomBits == null ? random23() : toBigInt(randomBits))\n );\n}\n\n/**\n * Converts a value to binary representation\n * @param value - The value to convert to binary\n * @param padding - Whether to pad to 64 bits (defaults to true)\n * @returns Binary string representation\n */\nexport function binary(\n value: bigint | number | string,\n padding: boolean = true\n): string {\n const binValue = toBigInt(value).toString(2);\n return padding && binValue.length < 64\n ? CACHE_64_BIT_ZEROS.substr(0, 64 - binValue.length) + binValue\n : binValue;\n}\n\n/**\n * Extracts bits from a data value\n * @param data - The data to extract bits from\n * @param shift - Number of bits to shift\n * @param length - Number of bits to extract\n * @returns Extracted bits as a BigInt\n */\nexport function extractBits(\n data: bigint | number | string,\n shift: bigint | number,\n length: bigint | number\n): bigint {\n const shiftN = toBigInt(shift);\n const lengthN = toBigInt(length);\n // Optimize: shift right first, then mask (avoids creating large bitmask)\n return (toBigInt(data) >> shiftN) & ((1n << lengthN) - 1n);\n}\n\n/**\n * Structure representing a parsed simpleflake\n */\nexport class SimpleflakeStruct {\n public readonly timestamp: bigint;\n public readonly randomBits: bigint;\n\n constructor(timestamp: bigint, randomBits: bigint) {\n if (timestamp == null || randomBits == null) {\n throw new Error(\"Missing argument for SimpleflakeStruct.\");\n }\n this.timestamp = timestamp;\n this.randomBits = randomBits;\n }\n}\n\n/**\n * Parses a simpleflake into its components\n * @param flake - The simpleflake to parse\n * @returns SimpleflakeStruct containing timestamp and random bits\n */\nexport function parseSimpleflake(\n flake: bigint | number | string\n): SimpleflakeStruct {\n return new SimpleflakeStruct(\n // timestamp\n extractBits(\n flake,\n SIMPLEFLAKE_TIMESTAMP_SHIFT,\n SIMPLEFLAKE_TIMESTAMP_LENGTH\n ) + SIMPLEFLAKE_EPOCH,\n // random bits\n extractBits(flake, SIMPLEFLAKE_RANDOM_SHIFT, SIMPLEFLAKE_RANDOM_LENGTH)\n );\n}\n\n// Export constants\nexport { SIMPLEFLAKE_EPOCH };\n\n// Default export for CommonJS compatibility\nexport default {\n binary,\n extractBits,\n parseSimpleflake,\n SIMPLEFLAKE_EPOCH,\n simpleflake,\n SimpleflakeStruct,\n};\n"]}
1
+ {"version":3,"sources":["../src/simpleflakes.ts"],"names":["SIMPLEFLAKE_EPOCH","SimpleflakeStruct","binary","extractBits","parseSimpleflake","simpleflake","randomBuffer","Uint32Array","randomBufferIndex","toBigInt","value","BigInt","getRandomSource","globalCrypto","globalThis","crypto","require","webcrypto","Error","refillRandomBuffer","getRandomValues","random23","ts","Date","now","randomBits","epoch","padding","binValue","toString","length","CACHE_64_BIT_ZEROS","substr","data","shift","shiftN","lengthN","timestamp","flake"],"mappings":"uMAsJSA,2BAAAA,uBAlCIC,2BAAAA,uBA/BGC,gBAAAA,YAoEhB,iBAAA,cAnDgBC,qBAAAA,iBAgCAC,0BAAAA,sBApEAC,qBAAAA,eAlEhB,MAAML,kBAAoB,YAAA,AAAa,CAAA,CAmBvC,IAAIM,aAAe,IAAIC,YAjBI,MAkBvBC,kBAlBuB,KAoB3B,SAASC,SAASC,CAA+B,EAC/C,MAAO,AAAiB,UAAjB,OAAOA,EAAqBA,EAAQC,OAAOD,EACpD,CAEA,SAASE,kBACP,IAAMC,EAAe,AAACC,WAEnBC,MAAM,CAET,GAAIF,EAAc,OAAOA,EAEzB,GAAI,CACF,OAAO,AAACG,QACN,eACAC,SAAS,AACb,CAAE,KAAM,CACN,MAAM,AAAIC,MACR,8EAEJ,CACF,CAEA,SAASC,qBACPP,kBAAkBQ,eAAe,CAACd,cAClCE,kBAAoB,CACtB,CAEA,SAASa,WACHb,mBAhDqB,MAiDvBW,qBAEF,IAAMT,EAAQJ,YAAY,CAACE,kBAAkB,CAG7C,OADAA,mBAAqB,EACdG,OAvDkB,AAuDXD,QAAAA,EAChB,CASO,SAASL,YACdiB,EAAsBC,KAAKC,GAAG,EAAE,CAChCC,CAA4B,CAC5BC,EAAyB1B,iBAAiB,EAI1C,OACE,AAAES,SAASa,GAAMb,SAASiB,IAlEM,EAAA,AAAG,CAAA,CAmElCD,CAAAA,AAAc,MAAdA,EAAqBJ,WAAaZ,SAASgB,EAAU,CAE1D,CAQO,SAASvB,OACdQ,CAA+B,CAC/BiB,EAAmB,CAAA,CAAI,EAEvB,IAAMC,EAAWnB,SAASC,GAAOmB,QAAQ,CAAC,GAC1C,OAAOF,GAAWC,EAASE,MAAM,CAAG,GA/EpC,AAgFIC,mEAAmBC,MAAM,CAAC,EAAG,GAAKJ,EAASE,MAAM,EAAIF,EACrDA,CACN,CASO,SAASzB,YACd8B,CAA8B,CAC9BC,CAAsB,CACtBJ,CAAuB,EAEvB,IAAMK,EAAS1B,SAASyB,GAClBE,EAAU3B,SAASqB,GAEzB,OAAO,AAACrB,SAASwB,IAASE,EAAW,AAAC,CAAA,CAAA,AAAE,CAAA,EAAIC,CAAM,EAAK,CAAA,AAAE,CAAA,AAC3D,CAKO,MAAMnC,kBAIX,YAAYoC,CAAiB,CAAEZ,CAAkB,CAAE,CACjD,GAAIY,AAAa,MAAbA,GAAqBZ,AAAc,MAAdA,EACvB,MAAM,AAAIP,MAAM,0CAElB,CAAA,IAAI,CAACmB,SAAS,CAAGA,EACjB,IAAI,CAACZ,UAAU,CAAGA,CACpB,CACF,CAOO,SAASrB,iBACdkC,CAA+B,EAE/B,OAAO,IAAIrC,kBAETE,YACEmC,EApI8B,EAAA,AAAG,CAAA,CAJF,EAAA,AAAG,CAAA,EA2IhCtC,kBAEJG,YAAYmC,EA1IiB,CAAA,AAAE,CAAA,CAFD,EAAA,AAAG,CAAA,EA8IrC,OAMA,SAAe,CACbpC,OACAC,YACAC,iBACAJ,kBACAK,YACAJ,iBACF","file":"simpleflakes.js","sourcesContent":["const SIMPLEFLAKE_EPOCH = 946684800000n; // Date.UTC(2000, 0, 1) == epoch ms, since 1 Jan 2000 00:00\nconst UNSIGNED_23BIT_MAX = 8388607; // (Math.pow(2, 23) - 1) >> 0\nconst RANDOM_BUFFER_SIZE = 1024;\n\nconst SIMPLEFLAKE_TIMESTAMP_LENGTH = 41n;\nconst SIMPLEFLAKE_RANDOM_LENGTH = 23n;\n\nconst SIMPLEFLAKE_RANDOM_SHIFT = 0n;\nconst SIMPLEFLAKE_TIMESTAMP_SHIFT = 23n;\n\nconst CACHE_64_BIT_ZEROS =\n \"0000000000000000000000000000000000000000000000000000000000000000\";\n\ninterface RandomSource {\n getRandomValues<T extends ArrayBufferView>(array: T): T;\n}\n\ndeclare const require: ((moduleName: string) => unknown) | undefined;\n\nlet randomBuffer = new Uint32Array(RANDOM_BUFFER_SIZE);\nlet randomBufferIndex = RANDOM_BUFFER_SIZE;\n\nfunction toBigInt(value: bigint | number | string): bigint {\n return typeof value === \"bigint\" ? value : BigInt(value);\n}\n\nfunction getRandomSource(): RandomSource {\n const globalCrypto = (globalThis as typeof globalThis & {\n crypto?: RandomSource;\n }).crypto;\n\n if (globalCrypto) return globalCrypto;\n\n try {\n return (require as (moduleName: string) => { webcrypto: RandomSource })(\n [\"node\", \"crypto\"].join(\":\")\n ).webcrypto;\n } catch {\n throw new Error(\n \"Cryptographically secure random values are unavailable in this environment.\"\n );\n }\n}\n\nfunction refillRandomBuffer(): void {\n getRandomSource().getRandomValues(randomBuffer);\n randomBufferIndex = 0;\n}\n\nfunction random23(): bigint {\n if (randomBufferIndex >= RANDOM_BUFFER_SIZE) {\n refillRandomBuffer();\n }\n const value = randomBuffer[randomBufferIndex]!;\n\n randomBufferIndex += 1;\n return BigInt(value & UNSIGNED_23BIT_MAX);\n}\n\n/**\n * Generates a simpleflake ID\n * @param ts - Timestamp in milliseconds (defaults to current time)\n * @param randomBits - Random bits for the ID (defaults to a cryptographically secure random value)\n * @param epoch - Epoch timestamp in milliseconds (defaults to SIMPLEFLAKE_EPOCH)\n * @returns Generated simpleflake as a BigInt\n */\nexport function simpleflake(\n ts: number | bigint = Date.now(),\n randomBits?: number | bigint,\n epoch: number | bigint = SIMPLEFLAKE_EPOCH\n): bigint {\n // Use bitwise OR instead of addition since bit ranges don't overlap\n\n return (\n ((toBigInt(ts) - toBigInt(epoch)) << SIMPLEFLAKE_TIMESTAMP_SHIFT) |\n (randomBits == null ? random23() : toBigInt(randomBits))\n );\n}\n\n/**\n * Converts a value to binary representation\n * @param value - The value to convert to binary\n * @param padding - Whether to pad to 64 bits (defaults to true)\n * @returns Binary string representation\n */\nexport function binary(\n value: bigint | number | string,\n padding: boolean = true\n): string {\n const binValue = toBigInt(value).toString(2);\n return padding && binValue.length < 64\n ? CACHE_64_BIT_ZEROS.substr(0, 64 - binValue.length) + binValue\n : binValue;\n}\n\n/**\n * Extracts bits from a data value\n * @param data - The data to extract bits from\n * @param shift - Number of bits to shift\n * @param length - Number of bits to extract\n * @returns Extracted bits as a BigInt\n */\nexport function extractBits(\n data: bigint | number | string,\n shift: bigint | number,\n length: bigint | number\n): bigint {\n const shiftN = toBigInt(shift);\n const lengthN = toBigInt(length);\n // Optimize: shift right first, then mask (avoids creating large bitmask)\n return (toBigInt(data) >> shiftN) & ((1n << lengthN) - 1n);\n}\n\n/**\n * Structure representing a parsed simpleflake\n */\nexport class SimpleflakeStruct {\n public declare readonly timestamp: bigint;\n public declare readonly randomBits: bigint;\n\n constructor(timestamp: bigint, randomBits: bigint) {\n if (timestamp == null || randomBits == null) {\n throw new Error(\"Missing argument for SimpleflakeStruct.\");\n }\n this.timestamp = timestamp;\n this.randomBits = randomBits;\n }\n}\n\n/**\n * Parses a simpleflake into its components\n * @param flake - The simpleflake to parse\n * @returns SimpleflakeStruct containing timestamp and random bits\n */\nexport function parseSimpleflake(\n flake: bigint | number | string\n): SimpleflakeStruct {\n return new SimpleflakeStruct(\n // timestamp\n extractBits(\n flake,\n SIMPLEFLAKE_TIMESTAMP_SHIFT,\n SIMPLEFLAKE_TIMESTAMP_LENGTH\n ) + SIMPLEFLAKE_EPOCH,\n // random bits\n extractBits(flake, SIMPLEFLAKE_RANDOM_SHIFT, SIMPLEFLAKE_RANDOM_LENGTH)\n );\n}\n\n// Export constants\nexport { SIMPLEFLAKE_EPOCH };\n\n// Default export for CommonJS compatibility\nexport default {\n binary,\n extractBits,\n parseSimpleflake,\n SIMPLEFLAKE_EPOCH,\n simpleflake,\n SimpleflakeStruct,\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simpleflakes",
3
- "version": "4.1.0",
3
+ "version": "4.1.1",
4
4
  "description": "Fast, lightweight, and reliable distributed 64-bit ID generation with zero dependencies for Node.js and the web.",
5
5
  "main": "dist/simpleflakes.js",
6
6
  "types": "dist/simpleflakes.d.ts",
@@ -33,19 +33,24 @@
33
33
  "keywords": [
34
34
  "simpleflake",
35
35
  "snowflake",
36
- "flake",
37
- "id",
36
+ "snowflake-id",
37
+ "id-generator",
38
+ "unique-id",
39
+ "sortable-id",
40
+ "time-ordered",
41
+ "64-bit",
42
+ "bigint",
43
+ "distributed-id",
44
+ "database-id",
38
45
  "uuid",
39
- "sequential",
40
- "monotonic",
41
- "ksuid",
42
- "nanoid",
43
46
  "uuidv7",
44
- "database",
45
- "distributed",
46
- "bigint",
47
- "time-ordered",
48
- "typescript"
47
+ "nanoid",
48
+ "ksuid",
49
+ "webcrypto",
50
+ "zero-dependency",
51
+ "typescript",
52
+ "nodejs",
53
+ "browser"
49
54
  ],
50
55
  "author": {
51
56
  "name": "Leonardo Dutra",