a collection of lightweight TypeScript packages for AT Protocol, the protocol powering Bluesky
atproto bluesky typescript npm
101
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(time-ms): Bun FFI support

Mary 07a3100c f41e201e

+89 -6
+5
.changeset/sparkly-animals-carry.md
··· 1 + --- 2 + '@atcute/time-ms': minor 3 + --- 4 + 5 + Bun FFI support
+63
packages/misc/time-ms/lib/index.bun.ts
··· 1 + import { dlopen, ptr } from 'bun:ffi'; 2 + 3 + const CLOCK_REALTIME = 0; 4 + 5 + // 100-nanosecond intervals between 1601-01-01 and 1970-01-01 6 + const EPOCH_OFFSET = 116444736000000000n; 7 + 8 + /** 9 + * whether the native module is available for the current runtime. 10 + */ 11 + export let hasNative = false; 12 + 13 + /** 14 + * returns the current time in microseconds since unix epoch. 15 + * @returns timestamp in microseconds 16 + */ 17 + export let now = (): number => { 18 + return Date.now() * 1_000; 19 + }; 20 + 21 + try { 22 + if (process.platform === 'win32') { 23 + const lib = dlopen('kernel32.dll', { 24 + GetSystemTimePreciseAsFileTime: { args: ['pointer'], returns: 'void' }, 25 + }); 26 + 27 + // FILETIME: { dwLowDateTime: u32, dwHighDateTime: u32 } = 8 bytes 28 + const buf = new Uint32Array(2); 29 + const bufPtr = ptr(buf); 30 + 31 + now = (): number => { 32 + lib.symbols.GetSystemTimePreciseAsFileTime(bufPtr); 33 + const low = BigInt(buf[0]); 34 + const high = BigInt(buf[1]); 35 + const filetime = (high << 32n) | low; 36 + // convert from 100-nanosecond intervals since 1601 to microseconds since 1970 37 + return Number((filetime - EPOCH_OFFSET) / 10n); 38 + }; 39 + 40 + hasNative = true; 41 + } else { 42 + const libPath = process.platform === 'darwin' ? 'libSystem.B.dylib' : 'libc.so.6'; 43 + 44 + const lib = dlopen(libPath, { 45 + clock_gettime: { args: ['i32', 'pointer'], returns: 'i32' }, 46 + }); 47 + 48 + // timespec: { tv_sec: i64, tv_nsec: i64 } = 16 bytes on 64-bit 49 + const buf = new BigInt64Array(2); 50 + const bufPtr = ptr(buf); 51 + 52 + now = (): number => { 53 + lib.symbols.clock_gettime(CLOCK_REALTIME, bufPtr); 54 + const sec = buf[0]; 55 + const nsec = buf[1]; 56 + return Number(sec * 1_000_000n + nsec / 1_000n); 57 + }; 58 + 59 + hasNative = true; 60 + } 61 + } catch { 62 + // ffi unavailable, keep fallback 63 + }
+2 -1
packages/misc/time-ms/package.json
··· 23 23 "exports": { 24 24 ".": { 25 25 "deno": "./dist/index.deno.js", 26 + "bun": "./dist/index.bun.js", 26 27 "node": "./dist/index.node.js", 27 28 "default": "./dist/index.js" 28 29 } ··· 40 41 "vitest": "^4.0.16" 41 42 }, 42 43 "dependencies": { 43 - "@types/node": "^22.19.3", 44 + "@types/bun": "^1.3.6", 44 45 "node-gyp-build": "^4.8.4" 45 46 } 46 47 }
+1 -1
packages/misc/time-ms/tsconfig.json
··· 1 1 { 2 2 "compilerOptions": { 3 - "types": ["node"], 3 + "types": ["bun"], 4 4 "outDir": "dist/", 5 5 "esModuleInterop": true, 6 6 "skipLibCheck": true,
+18 -4
pnpm-lock.yaml
··· 718 718 719 719 packages/misc/time-ms: 720 720 dependencies: 721 - '@types/node': 722 - specifier: ^22.19.3 723 - version: 22.19.3 721 + '@types/bun': 722 + specifier: ^1.3.6 723 + version: 1.3.6 724 724 node-gyp-build: 725 725 specifier: ^4.8.4 726 726 version: 4.8.4 ··· 730 730 version: 6.0.1 731 731 vitest: 732 732 specifier: ^4.0.16 733 - version: 4.0.16(@types/node@22.19.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.0) 733 + version: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.0) 734 734 735 735 packages/misc/uint8array: 736 736 devDependencies: ··· 2644 2644 '@types/bun@1.3.5': 2645 2645 resolution: {integrity: sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w==} 2646 2646 2647 + '@types/bun@1.3.6': 2648 + resolution: {integrity: sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA==} 2649 + 2647 2650 '@types/chai@5.2.3': 2648 2651 resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} 2649 2652 ··· 2885 2888 2886 2889 bun-types@1.3.5: 2887 2890 resolution: {integrity: sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw==} 2891 + 2892 + bun-types@1.3.6: 2893 + resolution: {integrity: sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ==} 2888 2894 2889 2895 bytes@3.1.2: 2890 2896 resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} ··· 6504 6510 dependencies: 6505 6511 bun-types: 1.3.5 6506 6512 6513 + '@types/bun@1.3.6': 6514 + dependencies: 6515 + bun-types: 1.3.6 6516 + 6507 6517 '@types/chai@5.2.3': 6508 6518 dependencies: 6509 6519 '@types/deep-eql': 4.0.2 ··· 6849 6859 ieee754: 1.2.1 6850 6860 6851 6861 bun-types@1.3.5: 6862 + dependencies: 6863 + '@types/node': 22.19.3 6864 + 6865 + bun-types@1.3.6: 6852 6866 dependencies: 6853 6867 '@types/node': 22.19.3 6854 6868