tigerbeetle-node 0.16.52 → 0.16.53

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
@@ -65,7 +65,8 @@ ID and replica addresses are both chosen by the system that
65
65
  starts the TigerBeetle cluster.
66
66
 
67
67
  Clients are thread-safe and a single instance should be shared
68
- between multiple concurrent tasks.
68
+ between multiple concurrent tasks. This allows events to be
69
+ [automatically batched](https://docs.tigerbeetle.com/coding/requests/#batching-events).
69
70
 
70
71
  Multiple clients are useful when connecting to more than
71
72
  one TigerBeetle cluster.
Binary file
Binary file
Binary file
package/dist/index.js CHANGED
@@ -94,7 +94,8 @@ function createClient(args) {
94
94
  }
95
95
  exports.createClient = createClient;
96
96
  let idLastTimestamp = 0;
97
- let idLastBuffer = new DataView(new ArrayBuffer(16));
97
+ const idLastBuffer = new DataView(new ArrayBuffer(16));
98
+ const idLastBufferArray = new Uint8Array(idLastBuffer.buffer, idLastBuffer.byteOffset, idLastBuffer.byteLength);
98
99
  function id() {
99
100
  let timestamp = Date.now();
100
101
  if (timestamp <= idLastTimestamp) {
@@ -102,7 +103,7 @@ function id() {
102
103
  }
103
104
  else {
104
105
  idLastTimestamp = timestamp;
105
- (0, node_crypto_1.randomFillSync)(idLastBuffer);
106
+ (0, node_crypto_1.randomFillSync)(idLastBufferArray);
106
107
  }
107
108
  const littleEndian = true;
108
109
  const randomLo32 = idLastBuffer.getUint32(0, littleEndian) + 1;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export * from './bindings'\nimport {\n Account,\n Transfer,\n CreateAccountsError,\n CreateTransfersError,\n Operation,\n AccountFilter,\n AccountBalance,\n QueryFilter,\n} from './bindings'\nimport { randomFillSync } from 'node:crypto'\n\nconst binding: Binding = (() => {\n const { arch, platform } = process\n\n const archMap = {\n \"arm64\": \"aarch64\",\n \"x64\": \"x86_64\"\n }\n\n const platformMap = {\n \"linux\": \"linux\",\n \"darwin\": \"macos\",\n \"win32\" : \"windows\",\n }\n\n if (! (arch in archMap)) {\n throw new Error(`Unsupported arch: ${arch}`)\n }\n\n if (! (platform in platformMap)) {\n throw new Error(`Unsupported platform: ${platform}`)\n }\n\n let extra = ''\n\n /**\n * We need to detect during runtime which libc we're running on to load the correct NAPI.\n * binary.\n *\n * Rationale: The /proc/self/map_files/ subdirectory contains entries corresponding to\n * memory-mapped files loaded by Node.\n * https://man7.org/linux/man-pages/man5/proc.5.html: We detect a musl-based distro by\n * checking if any library contains the name \"musl\".\n *\n * Prior art: https://github.com/xerial/sqlite-jdbc/issues/623\n */\n\n const fs = require('fs')\n const path = require('path')\n\n if (platform === 'linux') {\n extra = '-gnu'\n\n for (const file of fs.readdirSync(\"/proc/self/map_files/\")) {\n const realPath = fs.readlinkSync(path.join(\"/proc/self/map_files/\", file))\n if (realPath.includes('musl')) {\n extra = '-musl'\n break\n }\n }\n }\n\n const filename = `./bin/${archMap[arch]}-${platformMap[platform]}${extra}/client.node`\n return require(filename)\n})()\n\nexport type Context = object // tb_client\nexport type AccountID = bigint // u128\nexport type TransferID = bigint // u128\nexport type Event = Account | Transfer | AccountID | TransferID | AccountFilter | QueryFilter\nexport type Result = CreateAccountsError | CreateTransfersError | Account | Transfer | AccountBalance\nexport type ResultCallback = (error: Error | null, results: Result[] | null) => void\n\nexport const amount_max: bigint = (2n ** 128n) - 1n\n\ninterface BindingInitArgs {\n cluster_id: bigint, // u128\n replica_addresses: Buffer,\n}\n\ninterface Binding {\n init: (args: BindingInitArgs) => Context\n submit: (context: Context, operation: Operation, batch: Event[], callback: ResultCallback) => void\n deinit: (context: Context) => void,\n}\n\nexport interface ClientInitArgs {\n cluster_id: bigint, // u128\n replica_addresses: Array<string | number>,\n}\n\nexport interface Client {\n createAccounts: (batch: Account[]) => Promise<CreateAccountsError[]>\n createTransfers: (batch: Transfer[]) => Promise<CreateTransfersError[]>\n lookupAccounts: (batch: AccountID[]) => Promise<Account[]>\n lookupTransfers: (batch: TransferID[]) => Promise<Transfer[]>\n getAccountTransfers: (filter: AccountFilter) => Promise<Transfer[]>\n getAccountBalances: (filter: AccountFilter) => Promise<AccountBalance[]>\n queryAccounts: (filter: QueryFilter) => Promise<Account[]>\n queryTransfers: (filter: QueryFilter) => Promise<Transfer[]>\n destroy: () => void\n}\n\nexport function createClient (args: ClientInitArgs): Client {\n // Context becomes null when `destroy` is called. After that point, further `request` Promises\n // throw a shutdown Error. This prevents tb_client calls from happening after tb_client_deinit().\n let context: Context | null = binding.init({\n cluster_id: args.cluster_id,\n replica_addresses: Buffer.from(args.replica_addresses.join(',')),\n })\n\n const destroy = () => {\n if (context) binding.deinit(context)\n context = null;\n }\n\n const request = <T extends Result>(operation: Operation, batch: Event[]): Promise<T[]> => {\n return new Promise((resolve, reject) => {\n try {\n if (!context) throw new Error('Client was shutdown.');\n binding.submit(context, operation, batch, (error, result) => {\n if (error) {\n reject(error)\n } else if (result) {\n resolve(result as T[])\n } else {\n throw new Error(\"UB: Binding invoked callback without error or result\")\n }\n })\n } catch (err) {\n reject(err)\n }\n })\n }\n\n return {\n createAccounts(batch) { return request(Operation.create_accounts, batch) },\n createTransfers(batch) { return request(Operation.create_transfers, batch) },\n lookupAccounts(batch) { return request(Operation.lookup_accounts, batch) },\n lookupTransfers(batch) { return request(Operation.lookup_transfers, batch) },\n getAccountTransfers(filter) { return request(Operation.get_account_transfers, [filter]) },\n getAccountBalances(filter) { return request(Operation.get_account_balances, [filter]) },\n queryAccounts(filter) { return request(Operation.query_accounts, [filter]) },\n queryTransfers(filter) { return request(Operation.query_transfers, [filter]) },\n destroy,\n }\n}\n\nlet idLastTimestamp = 0;\nlet idLastBuffer = new DataView(new ArrayBuffer(16));\n\n/**\n * Generates a Universally Unique and Sortable Identifier as a u128 bigint.\n *\n * @remarks\n * Based on {@link https://github.com/ulid/spec}, IDs returned are guaranteed to be monotonically\n * increasing.\n */\nexport function id(): bigint {\n // Ensure timestamp monotonically increases and generate a new random on each new timestamp.\n let timestamp = Date.now()\n if (timestamp <= idLastTimestamp) {\n timestamp = idLastTimestamp\n } else {\n idLastTimestamp = timestamp\n randomFillSync(idLastBuffer)\n }\n\n // Increment the u80 in idLastBuffer using carry arithmetic on u32s (as JS doesn't have fast u64).\n const littleEndian = true\n const randomLo32 = idLastBuffer.getUint32(0, littleEndian) + 1\n const randomHi32 = idLastBuffer.getUint32(4, littleEndian) + (randomLo32 > 0xFFFFFFFF ? 1 : 0)\n const randomHi16 = idLastBuffer.getUint16(8, littleEndian) + (randomHi32 > 0xFFFFFFFF ? 1 : 0)\n if (randomHi16 > 0xFFFF) {\n throw new Error('random bits overflow on monotonic increment')\n }\n\n // Store the incremented random monotonic and the timestamp into the buffer.\n idLastBuffer.setUint32(0, randomLo32 & 0xFFFFFFFF, littleEndian)\n idLastBuffer.setUint32(4, randomHi32 & 0xFFFFFFFF, littleEndian)\n idLastBuffer.setUint16(8, randomHi16, littleEndian) // No need to mask since checked above.\n idLastBuffer.setUint16(10, timestamp & 0xFFFF, littleEndian) // timestamp lo.\n idLastBuffer.setUint32(12, (timestamp >>> 16) & 0xFFFFFFFF, littleEndian) // timestamp hi.\n\n // Then return the buffer's contents as a little-endian u128 bigint.\n const lo = idLastBuffer.getBigUint64(0, littleEndian)\n const hi = idLastBuffer.getBigUint64(8, littleEndian)\n return (hi << 64n) | lo\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,6CAA0B;AAC1B,yCASmB;AACnB,6CAA4C;AAE5C,MAAM,OAAO,GAAY,CAAC,GAAG,EAAE;IAC7B,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IAElC,MAAM,OAAO,GAAG;QACd,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,QAAQ;KAChB,CAAA;IAED,MAAM,WAAW,GAAG;QAClB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAG,SAAS;KACpB,CAAA;IAED,IAAI,CAAE,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE;QACvB,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAA;KAC7C;IAED,IAAI,CAAE,CAAC,QAAQ,IAAI,WAAW,CAAC,EAAE;QAC/B,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAA;KACrD;IAED,IAAI,KAAK,GAAG,EAAE,CAAA;IAcd,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAE5B,IAAI,QAAQ,KAAK,OAAO,EAAE;QACxB,KAAK,GAAG,MAAM,CAAA;QAEd,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,WAAW,CAAC,uBAAuB,CAAC,EAAE;YAC1D,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC,CAAA;YAC1E,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBAC7B,KAAK,GAAG,OAAO,CAAA;gBACf,MAAK;aACN;SACF;KACF;IAED,MAAM,QAAQ,GAAG,SAAS,OAAO,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,KAAK,cAAc,CAAA;IACtF,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAA;AAC1B,CAAC,CAAC,EAAE,CAAA;AASS,QAAA,UAAU,GAAW,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAA;AA8BnD,SAAgB,YAAY,CAAE,IAAoB;IAGhD,IAAI,OAAO,GAAmB,OAAO,CAAC,IAAI,CAAC;QACzC,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;KACjE,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,IAAI,OAAO;YAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACpC,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC,CAAA;IAED,MAAM,OAAO,GAAG,CAAmB,SAAoB,EAAE,KAAc,EAAgB,EAAE;QACvF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI;gBACF,IAAI,CAAC,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;gBACtD,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;oBAC1D,IAAI,KAAK,EAAE;wBACT,MAAM,CAAC,KAAK,CAAC,CAAA;qBACd;yBAAM,IAAI,MAAM,EAAE;wBACjB,OAAO,CAAC,MAAa,CAAC,CAAA;qBACvB;yBAAM;wBACL,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;qBACxE;gBACH,CAAC,CAAC,CAAA;aACH;YAAC,OAAO,GAAG,EAAE;gBACZ,MAAM,CAAC,GAAG,CAAC,CAAA;aACZ;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,OAAO;QACL,cAAc,CAAC,KAAK,IAAI,OAAO,OAAO,CAAC,oBAAS,CAAC,eAAe,EAAE,KAAK,CAAC,CAAA,CAAC,CAAC;QAC1E,eAAe,CAAC,KAAK,IAAI,OAAO,OAAO,CAAC,oBAAS,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAA,CAAC,CAAC;QAC5E,cAAc,CAAC,KAAK,IAAI,OAAO,OAAO,CAAC,oBAAS,CAAC,eAAe,EAAE,KAAK,CAAC,CAAA,CAAC,CAAC;QAC1E,eAAe,CAAC,KAAK,IAAI,OAAO,OAAO,CAAC,oBAAS,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAA,CAAC,CAAC;QAC5E,mBAAmB,CAAC,MAAM,IAAI,OAAO,OAAO,CAAC,oBAAS,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA,CAAC,CAAC;QACzF,kBAAkB,CAAC,MAAM,IAAI,OAAO,OAAO,CAAC,oBAAS,CAAC,oBAAoB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA,CAAC,CAAC;QACvF,aAAa,CAAC,MAAM,IAAI,OAAO,OAAO,CAAC,oBAAS,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA,CAAC,CAAC;QAC5E,cAAc,CAAC,MAAM,IAAI,OAAO,OAAO,CAAC,oBAAS,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA,CAAC,CAAC;QAC9E,OAAO;KACR,CAAA;AACH,CAAC;AA3CD,oCA2CC;AAED,IAAI,eAAe,GAAG,CAAC,CAAC;AAKxB,MAAM,YAAY,GAAG,IAAI,QAAQ,CAAC,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;AACvD,MAAM,iBAAiB,GAAG,IAAI,UAAU,CACpC,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC,UAAU,EAAE,YAAY,CAAC,UAAU,CACxE,CAAC;AASF,SAAgB,EAAE;IAEhB,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAC1B,IAAI,SAAS,IAAI,eAAe,EAAE;QAChC,SAAS,GAAG,eAAe,CAAA;KAC5B;SAAM;QACL,eAAe,GAAG,SAAS,CAAA;QAC3B,IAAA,4BAAc,EAAC,iBAAiB,CAAC,CAAA;KAClC;IAGD,MAAM,YAAY,GAAG,IAAI,CAAA;IACzB,MAAM,UAAU,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,CAAA;IAC9D,MAAM,UAAU,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9F,MAAM,UAAU,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9F,IAAI,UAAU,GAAG,MAAM,EAAE;QACvB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;KAC/D;IAGD,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,YAAY,CAAC,CAAA;IAChE,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,YAAY,CAAC,CAAA;IAChE,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,CAAA;IACnD,YAAY,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,EAAE,YAAY,CAAC,CAAA;IAC5D,YAAY,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,SAAS,KAAK,EAAE,CAAC,GAAG,UAAU,EAAE,YAAY,CAAC,CAAA;IAGzE,MAAM,EAAE,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC,EAAE,YAAY,CAAC,CAAA;IACrD,MAAM,EAAE,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC,EAAE,YAAY,CAAC,CAAA;IACrD,OAAO,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,EAAE,CAAA;AACzB,CAAC;AA9BD,gBA8BC","sourcesContent":["export * from './bindings'\nimport {\n Account,\n Transfer,\n CreateAccountsError,\n CreateTransfersError,\n Operation,\n AccountFilter,\n AccountBalance,\n QueryFilter,\n} from './bindings'\nimport { randomFillSync } from 'node:crypto'\n\nconst binding: Binding = (() => {\n const { arch, platform } = process\n\n const archMap = {\n \"arm64\": \"aarch64\",\n \"x64\": \"x86_64\"\n }\n\n const platformMap = {\n \"linux\": \"linux\",\n \"darwin\": \"macos\",\n \"win32\" : \"windows\",\n }\n\n if (! (arch in archMap)) {\n throw new Error(`Unsupported arch: ${arch}`)\n }\n\n if (! (platform in platformMap)) {\n throw new Error(`Unsupported platform: ${platform}`)\n }\n\n let extra = ''\n\n /**\n * We need to detect during runtime which libc we're running on to load the correct NAPI.\n * binary.\n *\n * Rationale: The /proc/self/map_files/ subdirectory contains entries corresponding to\n * memory-mapped files loaded by Node.\n * https://man7.org/linux/man-pages/man5/proc.5.html: We detect a musl-based distro by\n * checking if any library contains the name \"musl\".\n *\n * Prior art: https://github.com/xerial/sqlite-jdbc/issues/623\n */\n\n const fs = require('fs')\n const path = require('path')\n\n if (platform === 'linux') {\n extra = '-gnu'\n\n for (const file of fs.readdirSync(\"/proc/self/map_files/\")) {\n const realPath = fs.readlinkSync(path.join(\"/proc/self/map_files/\", file))\n if (realPath.includes('musl')) {\n extra = '-musl'\n break\n }\n }\n }\n\n const filename = `./bin/${archMap[arch]}-${platformMap[platform]}${extra}/client.node`\n return require(filename)\n})()\n\nexport type Context = object // tb_client\nexport type AccountID = bigint // u128\nexport type TransferID = bigint // u128\nexport type Event = Account | Transfer | AccountID | TransferID | AccountFilter | QueryFilter\nexport type Result = CreateAccountsError | CreateTransfersError | Account | Transfer | AccountBalance\nexport type ResultCallback = (error: Error | null, results: Result[] | null) => void\n\nexport const amount_max: bigint = (2n ** 128n) - 1n\n\ninterface BindingInitArgs {\n cluster_id: bigint, // u128\n replica_addresses: Buffer,\n}\n\ninterface Binding {\n init: (args: BindingInitArgs) => Context\n submit: (context: Context, operation: Operation, batch: Event[], callback: ResultCallback) => void\n deinit: (context: Context) => void,\n}\n\nexport interface ClientInitArgs {\n cluster_id: bigint, // u128\n replica_addresses: Array<string | number>,\n}\n\nexport interface Client {\n createAccounts: (batch: Account[]) => Promise<CreateAccountsError[]>\n createTransfers: (batch: Transfer[]) => Promise<CreateTransfersError[]>\n lookupAccounts: (batch: AccountID[]) => Promise<Account[]>\n lookupTransfers: (batch: TransferID[]) => Promise<Transfer[]>\n getAccountTransfers: (filter: AccountFilter) => Promise<Transfer[]>\n getAccountBalances: (filter: AccountFilter) => Promise<AccountBalance[]>\n queryAccounts: (filter: QueryFilter) => Promise<Account[]>\n queryTransfers: (filter: QueryFilter) => Promise<Transfer[]>\n destroy: () => void\n}\n\nexport function createClient (args: ClientInitArgs): Client {\n // Context becomes null when `destroy` is called. After that point, further `request` Promises\n // throw a shutdown Error. This prevents tb_client calls from happening after tb_client_deinit().\n let context: Context | null = binding.init({\n cluster_id: args.cluster_id,\n replica_addresses: Buffer.from(args.replica_addresses.join(',')),\n })\n\n const destroy = () => {\n if (context) binding.deinit(context)\n context = null;\n }\n\n const request = <T extends Result>(operation: Operation, batch: Event[]): Promise<T[]> => {\n return new Promise((resolve, reject) => {\n try {\n if (!context) throw new Error('Client was shutdown.');\n binding.submit(context, operation, batch, (error, result) => {\n if (error) {\n reject(error)\n } else if (result) {\n resolve(result as T[])\n } else {\n throw new Error(\"UB: Binding invoked callback without error or result\")\n }\n })\n } catch (err) {\n reject(err)\n }\n })\n }\n\n return {\n createAccounts(batch) { return request(Operation.create_accounts, batch) },\n createTransfers(batch) { return request(Operation.create_transfers, batch) },\n lookupAccounts(batch) { return request(Operation.lookup_accounts, batch) },\n lookupTransfers(batch) { return request(Operation.lookup_transfers, batch) },\n getAccountTransfers(filter) { return request(Operation.get_account_transfers, [filter]) },\n getAccountBalances(filter) { return request(Operation.get_account_balances, [filter]) },\n queryAccounts(filter) { return request(Operation.query_accounts, [filter]) },\n queryTransfers(filter) { return request(Operation.query_transfers, [filter]) },\n destroy,\n }\n}\n\nlet idLastTimestamp = 0;\n\n// These are two references to the same buffer.\n// We only need the `Uint8Array` because in Node 24, but not earlier, `crypto.randomFillSync`\n// rejects `DataView` typed arguments.\nconst idLastBuffer = new DataView(new ArrayBuffer(16));\nconst idLastBufferArray = new Uint8Array(\n idLastBuffer.buffer, idLastBuffer.byteOffset, idLastBuffer.byteLength\n);\n\n/**\n * Generates a Universally Unique and Sortable Identifier as a u128 bigint.\n *\n * @remarks\n * Based on {@link https://github.com/ulid/spec}, IDs returned are guaranteed to be monotonically\n * increasing.\n */\nexport function id(): bigint {\n // Ensure timestamp monotonically increases and generate a new random on each new timestamp.\n let timestamp = Date.now()\n if (timestamp <= idLastTimestamp) {\n timestamp = idLastTimestamp\n } else {\n idLastTimestamp = timestamp\n randomFillSync(idLastBufferArray)\n }\n\n // Increment the u80 in idLastBuffer using carry arithmetic on u32s (as JS doesn't have fast u64).\n const littleEndian = true\n const randomLo32 = idLastBuffer.getUint32(0, littleEndian) + 1\n const randomHi32 = idLastBuffer.getUint32(4, littleEndian) + (randomLo32 > 0xFFFFFFFF ? 1 : 0)\n const randomHi16 = idLastBuffer.getUint16(8, littleEndian) + (randomHi32 > 0xFFFFFFFF ? 1 : 0)\n if (randomHi16 > 0xFFFF) {\n throw new Error('random bits overflow on monotonic increment')\n }\n\n // Store the incremented random monotonic and the timestamp into the buffer.\n idLastBuffer.setUint32(0, randomLo32 & 0xFFFFFFFF, littleEndian)\n idLastBuffer.setUint32(4, randomHi32 & 0xFFFFFFFF, littleEndian)\n idLastBuffer.setUint16(8, randomHi16, littleEndian) // No need to mask since checked above.\n idLastBuffer.setUint16(10, timestamp & 0xFFFF, littleEndian) // timestamp lo.\n idLastBuffer.setUint32(12, (timestamp >>> 16) & 0xFFFFFFFF, littleEndian) // timestamp hi.\n\n // Then return the buffer's contents as a little-endian u128 bigint.\n const lo = idLastBuffer.getBigUint64(0, littleEndian)\n const hi = idLastBuffer.getBigUint64(8, littleEndian)\n return (hi << 64n) | lo\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tigerbeetle-node",
3
- "version": "0.16.52",
3
+ "version": "0.16.53",
4
4
  "description": "TigerBeetle Node.js client",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
package/src/index.ts CHANGED
@@ -149,7 +149,14 @@ export function createClient (args: ClientInitArgs): Client {
149
149
  }
150
150
 
151
151
  let idLastTimestamp = 0;
152
- let idLastBuffer = new DataView(new ArrayBuffer(16));
152
+
153
+ // These are two references to the same buffer.
154
+ // We only need the `Uint8Array` because in Node 24, but not earlier, `crypto.randomFillSync`
155
+ // rejects `DataView` typed arguments.
156
+ const idLastBuffer = new DataView(new ArrayBuffer(16));
157
+ const idLastBufferArray = new Uint8Array(
158
+ idLastBuffer.buffer, idLastBuffer.byteOffset, idLastBuffer.byteLength
159
+ );
153
160
 
154
161
  /**
155
162
  * Generates a Universally Unique and Sortable Identifier as a u128 bigint.
@@ -165,7 +172,7 @@ export function id(): bigint {
165
172
  timestamp = idLastTimestamp
166
173
  } else {
167
174
  idLastTimestamp = timestamp
168
- randomFillSync(idLastBuffer)
175
+ randomFillSync(idLastBufferArray)
169
176
  }
170
177
 
171
178
  // Increment the u80 in idLastBuffer using carry arithmetic on u32s (as JS doesn't have fast u64).