diff --git a/packages/core/__benches__/objectid.bench.ts b/packages/core/__benches__/objectid.bench.ts
new file mode 100644
index 000000000..749958c0b
--- /dev/null
+++ b/packages/core/__benches__/objectid.bench.ts
@@ -0,0 +1,37 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { bench, describe } from "vitest";
+import { createObjectId } from "../src/utils/object-id";
+import boid from "bson-objectid";
+import { nanoid } from "nanoid";
+
+describe("objectid", async () => {
+ bench("custom", () => {
+ createObjectId();
+ });
+
+ bench("bson-objectid", () => {
+ boid().toHexString();
+ });
+
+ bench("nanoid", () => {
+ nanoid(32);
+ });
+});
diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json
index 191a068cc..00eb65f00 100644
--- a/packages/core/package-lock.json
+++ b/packages/core/package-lock.json
@@ -44,6 +44,7 @@
"@vitest/coverage-v8": "^0.34.1",
"abortcontroller-polyfill": "^1.7.3",
"better-sqlite3": "^8.6.0",
+ "bson-objectid": "^2.0.4",
"cross-env": "^7.0.3",
"dotenv": "^16.0.1",
"event-source-polyfill": "^1.0.31",
@@ -52,6 +53,7 @@
"isomorphic-fetch": "^3.0.0",
"jsdom": "^22.1.0",
"mockdate": "^3.0.5",
+ "nanoid": "^5.0.1",
"otplib": "^12.0.1",
"refractor": "^4.8.1",
"vitest": "^0.34.1",
@@ -2086,6 +2088,12 @@
"concat-map": "0.0.1"
}
},
+ "node_modules/bson-objectid": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/bson-objectid/-/bson-objectid-2.0.4.tgz",
+ "integrity": "sha512-vgnKAUzcDoa+AeyYwXCoHyF2q6u/8H46dxu5JN+4/TZeq/Dlinn0K6GvxsCLb3LHUJl0m/TLiEK31kUwtgocMQ==",
+ "dev": true
+ },
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
@@ -3150,7 +3158,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.6",
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.5.tgz",
+ "integrity": "sha512-/Veqm+QKsyMY3kqi4faWplnY1u+VuKO3dD2binyPIybP31DRO29bPF+1mszgLnrR2KqSLceFLBNw0zmvDzN1QQ==",
"dev": true,
"funding": [
{
@@ -3158,12 +3168,11 @@
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"bin": {
- "nanoid": "bin/nanoid.cjs"
+ "nanoid": "bin/nanoid.js"
},
"engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ "node": "^18 || >=20"
}
},
"node_modules/napi-build-utils": {
@@ -3394,6 +3403,24 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/postcss/node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
"node_modules/prebuild-install": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
diff --git a/packages/core/package.json b/packages/core/package.json
index 0812d145c..583446b02 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -21,6 +21,7 @@
"@vitest/coverage-v8": "^0.34.1",
"abortcontroller-polyfill": "^1.7.3",
"better-sqlite3": "^8.6.0",
+ "bson-objectid": "^2.0.4",
"cross-env": "^7.0.3",
"dotenv": "^16.0.1",
"event-source-polyfill": "^1.0.31",
@@ -29,6 +30,7 @@
"isomorphic-fetch": "^3.0.0",
"jsdom": "^22.1.0",
"mockdate": "^3.0.5",
+ "nanoid": "^5.0.1",
"otplib": "^12.0.1",
"refractor": "^4.8.1",
"vitest": "^0.34.1",
diff --git a/packages/core/src/utils/object-id.ts b/packages/core/src/utils/object-id.ts
index a9ebe4df9..2355a602c 100644
--- a/packages/core/src/utils/object-id.ts
+++ b/packages/core/src/utils/object-id.ts
@@ -17,35 +17,16 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-import { BufferPool } from "./buffer-pool";
import { randomBytes, randomInt } from "./random";
-const PROCESS_UNIQUE = randomBytes(5);
+const PROCESS_UNIQUE = randomBytes(5).toString("hex");
let index = ~~(randomInt() * 0xffffff);
-
-const objectIdPool = new BufferPool(12);
export function createObjectId(date = Date.now()): string {
- const buffer = objectIdPool.alloc();
- index = (index + 1) % 0xffffff;
-
- const time = ~~(date / 1000);
-
- // 4-byte timestamp
- new DataView(buffer.buffer, 0, 4).setUint32(0, time);
-
- // 5-byte process unique
- buffer[4] = PROCESS_UNIQUE[0];
- buffer[5] = PROCESS_UNIQUE[1];
- buffer[6] = PROCESS_UNIQUE[2];
- buffer[7] = PROCESS_UNIQUE[3];
- buffer[8] = PROCESS_UNIQUE[4];
-
- // 3-byte counter
- buffer[11] = index & 0xff;
- buffer[10] = (index >> 8) & 0xff;
- buffer[9] = (index >> 16) & 0xff;
-
- const objectId = buffer.toString("hex");
- objectIdPool.free(buffer);
- return objectId;
+ index++;
+ const time = Math.floor(date / 1000);
+ return time.toString(16) + PROCESS_UNIQUE + swap16(index).toString(16);
+}
+
+function swap16(val: number) {
+ return ((val & 0xff) << 16) | (val & 0xff00) | ((val >> 16) & 0xff);
}
diff --git a/packages/core/src/utils/random.ts b/packages/core/src/utils/random.ts
index d87b82c05..5099af5d7 100644
--- a/packages/core/src/utils/random.ts
+++ b/packages/core/src/utils/random.ts
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-export function randomBytes(size: number) {
+export function randomBytes(size: number): Buffer {
if (!globalThis.crypto || !crypto)
throw new Error("Crypto is not supported on this platform.");
if ("randomBytes" in crypto && typeof crypto.randomBytes === "function")
@@ -34,8 +34,5 @@ export function randomBytes(size: number) {
}
export function randomInt() {
- const randomBuffer = randomBytes(1);
- const randomNumber = randomBuffer[0] / 0xff; // / (0xffffffff + 1);
-
- return Math.floor(randomNumber * 0xffffff);
+ return randomBytes(4).readInt32BE();
}