albedo-node 0.5.89 → 0.5.91

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 CHANGED
@@ -136,6 +136,27 @@ export declare class Bucket {
136
136
  * ```
137
137
  */
138
138
  list<T>(query?: object | Query): Generator<T>;
139
+ /**
140
+ * Collect all documents matching the optional query into an array.
141
+ * @param query - filter or `Query` object
142
+ * @returns array of all matching documents
143
+ * @example
144
+ * ```ts
145
+ * const docs = bucket.all<{ name: string }>(where('name', { $exists: true }));
146
+ * ```
147
+ */
148
+ all<T>(query?: object | Query): Array<T>;
149
+ /**
150
+ * Return the first document matching the optional query, or `null`
151
+ * when no document matches.
152
+ * @param query - filter or `Query` object
153
+ * @returns first matching document or `null`
154
+ * @example
155
+ * ```ts
156
+ * const doc = bucket.one<{ _id: number }>(where('_id', { $eq: 1 }));
157
+ * ```
158
+ */
159
+ one<T>(query?: object | Query): T | null;
139
160
  /**
140
161
  * Normalize a query argument to a plain object, unpacking
141
162
  * `Query` instances.
package/dist/index.js CHANGED
@@ -183,6 +183,34 @@ class Bucket {
183
183
  exports.albedo.listClose(cursor);
184
184
  }
185
185
  }
186
+ /**
187
+ * Collect all documents matching the optional query into an array.
188
+ * @param query - filter or `Query` object
189
+ * @returns array of all matching documents
190
+ * @example
191
+ * ```ts
192
+ * const docs = bucket.all<{ name: string }>(where('name', { $exists: true }));
193
+ * ```
194
+ */
195
+ all(query) {
196
+ return Array.from(this.list(query));
197
+ }
198
+ /**
199
+ * Return the first document matching the optional query, or `null`
200
+ * when no document matches.
201
+ * @param query - filter or `Query` object
202
+ * @returns first matching document or `null`
203
+ * @example
204
+ * ```ts
205
+ * const doc = bucket.one<{ _id: number }>(where('_id', { $eq: 1 }));
206
+ * ```
207
+ */
208
+ one(query) {
209
+ for (const doc of this.list(query)) {
210
+ return doc;
211
+ }
212
+ return null;
213
+ }
186
214
  /**
187
215
  * Normalize a query argument to a plain object, unpacking
188
216
  * `Query` instances.
@@ -0,0 +1,10 @@
1
+ FROM oven/bun:1-alpine
2
+
3
+ WORKDIR /app
4
+
5
+ COPY package.json ./
6
+ RUN bun install
7
+
8
+ COPY . .
9
+
10
+ CMD ["bun", "run", "index.js"]
package/example/bun.lock CHANGED
@@ -5,8 +5,7 @@
5
5
  "": {
6
6
  "name": "example",
7
7
  "dependencies": {
8
- "albedo-node": "../",
9
- "better-sqlite3": "^12.6.2",
8
+ "albedo-node": "0.5.90",
10
9
  },
11
10
  "devDependencies": {
12
11
  "@types/bun": "latest",
@@ -21,88 +20,12 @@
21
20
 
22
21
  "@types/node": ["@types/node@24.10.13", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg=="],
23
22
 
24
- "albedo-node": ["albedo-node@file:..", { "devDependencies": { "@types/node": "^24.0.0", "typescript": "^5.9.3" } }],
25
-
26
- "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
27
-
28
- "better-sqlite3": ["better-sqlite3@12.6.2", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA=="],
29
-
30
- "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
31
-
32
- "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
33
-
34
- "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
23
+ "albedo-node": ["albedo-node@0.5.90", "", {}, "sha512-YoKDQ/tJSv+YF4zaEby2pqHrRQjKPXDXkAVwt2kX00d/dTz2ZigPLvJcBt3yVNu207+k4woxAWSe3ofLiRedXA=="],
35
24
 
36
25
  "bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
37
26
 
38
- "chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
39
-
40
- "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
41
-
42
- "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
43
-
44
- "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
45
-
46
- "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
47
-
48
- "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
49
-
50
- "file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
51
-
52
- "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
53
-
54
- "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="],
55
-
56
- "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
57
-
58
- "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
59
-
60
- "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
61
-
62
- "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
63
-
64
- "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
65
-
66
- "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
67
-
68
- "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="],
69
-
70
- "node-abi": ["node-abi@3.87.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ=="],
71
-
72
- "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
73
-
74
- "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="],
75
-
76
- "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
77
-
78
- "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
79
-
80
- "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
81
-
82
- "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
83
-
84
- "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
85
-
86
- "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
87
-
88
- "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="],
89
-
90
- "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
91
-
92
- "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
93
-
94
- "tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="],
95
-
96
- "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
97
-
98
- "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
99
-
100
27
  "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
101
28
 
102
29
  "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
103
-
104
- "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
105
-
106
- "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
107
30
  }
108
31
  }
package/example/index.js CHANGED
@@ -2,55 +2,55 @@ import { BSON, Bucket, where } from "albedo-node";
2
2
  import Database from "bun:sqlite";
3
3
  import { unlinkSync } from "fs";
4
4
 
5
- const docNum = 100000;
5
+ const docNum = 1000;
6
6
 
7
- const sqliteDb = new Database("db.sqlite");
8
- sqliteDb
9
- .prepare(
10
- `
11
- CREATE TABLE IF NOT EXISTS documents (
12
- _id INTEGER PRIMARY KEY,
13
- doc JSON
14
- );
15
- `,
16
- )
17
- .run();
7
+ // const sqliteDb = new Database("db.sqlite");
8
+ // sqliteDb
9
+ // .prepare(
10
+ // `
11
+ // CREATE TABLE IF NOT EXISTS documents (
12
+ // _id INTEGER PRIMARY KEY,
13
+ // doc JSON
14
+ // );
15
+ // `,
16
+ // )
17
+ // .run();
18
18
 
19
- sqliteDb.prepare("drop index IF EXISTS idx_doc_id;").run();
20
- sqliteDb.prepare("create unique index idx_doc_id on documents(json_extract(doc, '$._id'));").run();
19
+ // sqliteDb.prepare("drop index IF EXISTS idx_doc_id;").run();
20
+ // sqliteDb.prepare("create unique index idx_doc_id on documents(json_extract(doc, '$._id'));").run();
21
21
 
22
- console.time("Insert 100000 documents into SQLite");
23
- const insertStmt = sqliteDb.prepare("INSERT INTO documents (doc) VALUES (json(?))");
24
- for (let i = 0; i < docNum; i++) {
25
- insertStmt.run(JSON.stringify({
26
- _id: i,
27
- name: `Name ${i}`,
28
- age: i,
29
- }));
30
- }
31
- console.timeEnd("Insert 100000 documents into SQLite");
22
+ // console.time("Insert 100000 documents into SQLite");
23
+ // const insertStmt = sqliteDb.prepare("INSERT INTO documents (doc) VALUES (json(?))");
24
+ // for (let i = 0; i < docNum; i++) {
25
+ // insertStmt.run(JSON.stringify({
26
+ // _id: i,
27
+ // name: `Name ${i}`,
28
+ // age: i,
29
+ // }));
30
+ // }
31
+ // console.timeEnd("Insert 100000 documents into SQLite");
32
32
 
33
- console.time("Query scan x 100 in SQLite");
34
- for (let i = 0; i < 100; i++) {
35
- const row = sqliteDb
36
- .prepare("SELECT doc FROM documents WHERE json_extract(doc, '$.age') = ? LIMIT 100")
37
- .get(Math.floor(Math.random() * docNum));
38
- if (row) JSON.parse(row.doc);
39
- }
40
- console.timeEnd("Query scan x 100 in SQLite");
33
+ // console.time("Query scan x 100 in SQLite");
34
+ // for (let i = 0; i < 100; i++) {
35
+ // const row = sqliteDb
36
+ // .prepare("SELECT doc FROM documents WHERE json_extract(doc, '$.age') = ? LIMIT 100")
37
+ // .get(Math.floor(Math.random() * docNum));
38
+ // if (row) JSON.parse(row.doc);
39
+ // }
40
+ // console.timeEnd("Query scan x 100 in SQLite");
41
41
 
42
- console.time("Query index x 100 in SQLite");
43
- for (let i = 0; i < 100; i++) {
44
- const row = sqliteDb
45
- .prepare(
46
- "SELECT doc FROM documents WHERE json_extract(doc, '$._id') = ? LIMIT 100",
47
- )
48
- .get(Math.floor(Math.random() * docNum));
49
- if (row) JSON.parse(row.doc);
50
- }
51
- console.timeEnd("Query index x 100 in SQLite");
42
+ // console.time("Query index x 100 in SQLite");
43
+ // for (let i = 0; i < 100; i++) {
44
+ // const row = sqliteDb
45
+ // .prepare(
46
+ // "SELECT doc FROM documents WHERE json_extract(doc, '$._id') = ? LIMIT 100",
47
+ // )
48
+ // .get(Math.floor(Math.random() * docNum));
49
+ // if (row) JSON.parse(row.doc);
50
+ // }
51
+ // console.timeEnd("Query index x 100 in SQLite");
52
52
 
53
- sqliteDb.close();
53
+ // sqliteDb.close();
54
54
 
55
55
  const bucket = Bucket.open("db.bucket");
56
56
 
@@ -79,14 +79,15 @@ console.timeEnd("Query scan x 100");
79
79
 
80
80
  console.time("Query index x 100");
81
81
  for (let i = 0; i < 100; i++) {
82
-
83
82
  bucket
84
- .list(where("_id", { $eq: Math.floor(Math.random() * docNum) }).sector(0, 100))
83
+ .list(
84
+ where("_id", { $eq: Math.floor(Math.random() * docNum) }).sector(0, 100),
85
+ )
85
86
  .next();
86
87
  }
87
88
  console.timeEnd("Query index x 100");
88
89
 
89
90
  bucket.close();
90
91
 
91
- unlinkSync("db.sqlite");
92
- unlinkSync("db.bucket");
92
+ // unlinkSync("db.sqlite");
93
+ unlinkSync("db.bucket");
@@ -10,7 +10,6 @@
10
10
  "typescript": "^5"
11
11
  },
12
12
  "dependencies": {
13
- "albedo-node": "../",
14
- "better-sqlite3": "^12.6.2"
13
+ "albedo-node": "0.5.90"
15
14
  }
16
15
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "albedo-node",
3
- "version": "0.5.89",
3
+ "version": "0.5.91",
4
4
  "description": "High-performance embedded database for Node.js with native bindings, BSON support, indexing, and replication",
5
5
  "keywords": [
6
6
  "albedo",
@@ -31,5 +31,8 @@
31
31
  "devDependencies": {
32
32
  "@types/node": "^24.0.0",
33
33
  "typescript": "^5.9.3"
34
+ },
35
+ "dependencies": {
36
+ "detect-libc": "^2.1.2"
34
37
  }
35
38
  }