ruggy 0.1.0 → 0.2.0

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/CHANGELOG.md CHANGED
@@ -5,6 +5,37 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.0] - 2026-01-12
9
+
10
+ ### Added
11
+ - Advanced search with query operators (`LIKE`, `starts_with`, `ends_with`, `contains`)
12
+ - `RuggyCollection.findWithOperator()` method for advanced queries
13
+ - `RuggyCollection.updateField(id, field, value)` method for editing specific document fields
14
+ - `RuggyCollection.delete(id)` method for removing documents by ID
15
+ - Updated TypeScript definitions for all new methods
16
+
17
+ ### Changed
18
+ - **Refactored Rust backend architecture** (`db`, `collection`, `ffi` modules) for better maintainability.
19
+ - Improved `persist()` logic to handle file truncation reliably on Windows.
20
+ - Switched FFI return types to `i32` for better cross-platform consistency.
21
+
22
+ ### Fixed
23
+ - Fixed "Access Denied" errors when updating/deleting files on Windows.
24
+ - Fixed inconsistent boolean return values across the FFI boundary.
25
+
26
+ ### Platform Support
27
+ - Windows x64 - Pre-built binaries included
28
+ - Linux - Not supported at this time
29
+ - macOS - Not supported at this time
30
+
31
+ ### Known Limitations
32
+ - Single-platform binary distribution (Windows only)
33
+ - No indexes (linear scan)
34
+ - No transactions
35
+ - No schema validation
36
+
37
+ ---
38
+
8
39
  ## [0.1.0] - 2026-01-04
9
40
 
10
41
  ### Added
@@ -15,51 +46,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
46
  - Configuration loader with automatic file discovery
16
47
  - `Database.fromConfig()` and `Pool.fromConfig()` factory methods
17
48
  - Full TypeScript type definitions
18
- - Comprehensive README with examples
19
49
  - Support for Node.js 14+
20
50
  - Windows x64 pre-built binaries
21
51
 
22
52
  ### Features
23
53
  - Native Rust backend with FFI bindings
24
54
  - Embedded database (no external server required)
25
- - Simple and intuitive API
26
55
  - Persistent storage with append-only files
27
56
  - Flexible YAML configuration
28
- - TypeScript support with complete definitions
29
-
30
- ### Platform Support
31
- - Windows x64 - Pre-built binaries included
32
- - Linux - Not supported at this time
33
- - macOS - Not supported at this time
34
-
35
- ### Known Limitations
36
- - Single-platform binary distribution (Windows only)
37
- - No query operators (only exact match)
38
- - No indexes (linear scan)
39
- - No transactions
40
- - No schema validation
41
-
42
- ### Dependencies
43
- - koffi ^2.8.0 - FFI bindings
44
- - js-yaml ^4.1.0 - YAML configuration parsing
45
57
 
46
58
  ---
47
59
 
48
60
  ## [Unreleased]
49
61
 
50
- ### Planned for 0.2.0
62
+ ### Planned
51
63
  - Linux and macOS pre-built binaries
52
64
  - Configurable limits (maxCollectionSize, maxDocumentSize)
53
65
  - Logging configuration
54
66
  - Performance tuning options
55
67
 
56
68
  ### Future Enhancements
57
- - Backup automation
69
+ - Basic indexing (B-Tree/Hash)
70
+ - Write-Ahead Logging (WAL) for faster updates
71
+ - $AND / $OR logical operators
58
72
  - Compression support
59
- - Query operators (range, comparison)
60
- - Basic indexing
61
73
  - Encryption at rest
62
74
 
63
75
  ---
64
76
 
77
+ [0.2.0]: https://github.com/Mub1522/ruggy/releases/tag/v0.2.0
65
78
  [0.1.0]: https://github.com/Mub1522/ruggy/releases/tag/v0.1.0
package/README.md CHANGED
@@ -161,6 +161,35 @@ Finds documents where field matches value.
161
161
  const adults = collection.find('age', '30');
162
162
  ```
163
163
 
164
+ **`findWithOperator(field: string, value: any, operator: string): Array<Object>`**
165
+
166
+ Finds documents using advanced operators.
167
+
168
+ - **`=`**, **`==`**, **`eq`**: Exact match.
169
+ - **`like`**, **`LIKE`**, **`contains`**: Partial match (case-sensitive).
170
+ - **`starts_with`**: Matches the beginning of the string.
171
+ - **`ends_with`**: Matches the end of the string.
172
+
173
+ ```javascript
174
+ const results = collection.findWithOperator('name', 'App', 'like');
175
+ ```
176
+
177
+ **`updateField(id: string, field: string, value: any): boolean`**
178
+
179
+ Edits a specific field of a document identified by its `_id`.
180
+
181
+ ```javascript
182
+ const success = collection.updateField('some-uuid-here', 'role', 'superadmin');
183
+ ```
184
+
185
+ **`delete(id: string): boolean`**
186
+
187
+ Deletes a document identified by its `_id`.
188
+
189
+ ```javascript
190
+ const deleted = collection.delete('some-uuid-here');
191
+ ```
192
+
164
193
  **`close(): void`**
165
194
 
166
195
  Closes the collection and releases resources.
@@ -258,6 +287,25 @@ const electronics = products.find('category', 'electronics');
258
287
  db.close();
259
288
  ```
260
289
 
290
+ ### Advanced Searching
291
+
292
+ ```javascript
293
+ const { RuggyDatabase } = require('ruggy');
294
+ const db = new RuggyDatabase('./data');
295
+ const products = db.collection('products');
296
+
297
+ // Partial search (LIKE)
298
+ const electronics = products.findWithOperator('category', 'elect', 'like');
299
+
300
+ // Prefix search
301
+ const startsWithA = products.findWithOperator('name', 'A', 'starts_with');
302
+
303
+ // Suffix search
304
+ const endsWithS = products.findWithOperator('name', 's', 'ends_with');
305
+
306
+ db.close();
307
+ ```
308
+
261
309
  ### Using Connection Pool
262
310
 
263
311
  ```javascript
package/index.d.ts CHANGED
@@ -70,13 +70,32 @@ export class RuggyCollection {
70
70
  */
71
71
  findAll(): Array<Record<string, any>>;
72
72
 
73
+ find(field: string, value: any): Array<Record<string, any>>;
74
+
73
75
  /**
74
- * Finds documents matching a field-value pair
76
+ * Finds documents using advanced operators
75
77
  * @param field - Field name to search
76
78
  * @param value - Value to match
79
+ * @param operator - Operator to use (=, ==, eq, like, LIKE, contains, starts_with, ends_with)
77
80
  * @returns Array of matching documents
78
81
  */
79
- find(field: string, value: any): Array<Record<string, any>>;
82
+ findWithOperator(field: string, value: any, operator: string): Array<Record<string, any>>;
83
+
84
+ /**
85
+ * Updates a specific field of a document found by its _id
86
+ * @param id - The _id of the document to update
87
+ * @param field - The field name to update
88
+ * @param value - The new value for the field
89
+ * @returns True if updated, false if not found or error
90
+ */
91
+ updateField(id: string, field: string, value: any): boolean;
92
+
93
+ /**
94
+ * Deletes a document by its _id
95
+ * @param id - The _id of the document to delete
96
+ * @returns True if deleted, false if not found or error
97
+ */
98
+ delete(id: string): boolean;
80
99
 
81
100
  /**
82
101
  * Closes the collection and frees native resources
package/lib/ruggy.dll CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruggy",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A simple, fast embedded database for Node.js backed by Rust",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
package/src/Collection.js CHANGED
@@ -2,6 +2,9 @@ const {
2
2
  ruggy_insert,
3
3
  ruggy_find_all,
4
4
  ruggy_find,
5
+ ruggy_find_op,
6
+ ruggy_update_field,
7
+ ruggy_delete,
5
8
  ruggy_col_free,
6
9
  ruggy_str_free
7
10
  } = require('./bindings');
@@ -136,6 +139,91 @@ class RuggyCollection {
136
139
  }
137
140
  }
138
141
 
142
+ /**
143
+ * Finds documents using a specific operator
144
+ * @param {string} field - Field name to search
145
+ * @param {*} value - Value to match (converted to string)
146
+ * @param {string} operator - Operator to use (e.g., '=', 'like', 'starts_with', 'ends_with')
147
+ * @returns {Array<Object>} - Array of matching documents
148
+ * @throws {Error} If collection is closed
149
+ */
150
+ findWithOperator(field, value, operator) {
151
+ this.#ensureOpen();
152
+
153
+ if (typeof field !== 'string' || !field) {
154
+ throw new Error('Field must be a non-empty string');
155
+ }
156
+
157
+ if (typeof operator !== 'string' || !operator) {
158
+ throw new Error('Operator must be a non-empty string');
159
+ }
160
+
161
+ const fieldBuf = toCString(field);
162
+ const valueBuf = toCString(String(value));
163
+ const opBuf = toCString(operator);
164
+
165
+ const resPtr = ruggy_find_op(this.#colPtr, fieldBuf, valueBuf, opBuf);
166
+ if (!isValidPointer(resPtr)) {
167
+ return [];
168
+ }
169
+
170
+ const json = readCString(resPtr);
171
+ ruggy_str_free(resPtr);
172
+
173
+ try {
174
+ return JSON.parse(json);
175
+ } catch (error) {
176
+ console.error('Failed to parse JSON from Rust:', error);
177
+ return [];
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Updates a specific field of a document found by its _id
183
+ * @param {string} id - The _id of the document to update
184
+ * @param {string} field - The field name to update
185
+ * @param {*} value - The new value for the field (will be JSON stringified)
186
+ * @returns {boolean} - True if updated, false if not found or error
187
+ * @throws {Error} If collection is closed or parameters are invalid
188
+ */
189
+ updateField(id, field, value) {
190
+ this.#ensureOpen();
191
+
192
+ if (typeof id !== 'string' || !id) {
193
+ throw new Error('ID must be a non-empty string');
194
+ }
195
+
196
+ if (typeof field !== 'string' || !field) {
197
+ throw new Error('Field must be a non-empty string');
198
+ }
199
+
200
+ const idBuf = toCString(id);
201
+ const fieldBuf = toCString(field);
202
+ const valueJson = JSON.stringify(value);
203
+ const valBuf = toCString(valueJson);
204
+
205
+ const result = ruggy_update_field(this.#colPtr, idBuf, fieldBuf, valBuf);
206
+ return result === 1;
207
+ }
208
+
209
+ /**
210
+ * Deletes a document by its _id
211
+ * @param {string} id - The _id of the document to delete
212
+ * @returns {boolean} - True if deleted, false if not found or error
213
+ * @throws {Error} If collection is closed or ID is invalid
214
+ */
215
+ delete(id) {
216
+ this.#ensureOpen();
217
+
218
+ if (typeof id !== 'string' || !id) {
219
+ throw new Error('ID must be a non-empty string');
220
+ }
221
+
222
+ const idBuf = toCString(id);
223
+ const result = ruggy_delete(this.#colPtr, idBuf);
224
+ return result === 1;
225
+ }
226
+
139
227
  /**
140
228
  * Closes the collection and frees native resources
141
229
  * Safe to call multiple times
package/src/bindings.js CHANGED
@@ -17,6 +17,9 @@ const ruggy_col_free = lib.func('ruggy_col_free', 'void', ['void *']);
17
17
  const ruggy_insert = lib.func('ruggy_insert', 'void *', ['void *', 'string']);
18
18
  const ruggy_find_all = lib.func('ruggy_find_all', 'void *', ['void *']);
19
19
  const ruggy_find = lib.func('ruggy_find', 'void *', ['void *', 'string', 'string']);
20
+ const ruggy_find_op = lib.func('ruggy_find_op', 'void *', ['void *', 'string', 'string', 'string']);
21
+ const ruggy_update_field = lib.func('ruggy_update_field', 'int', ['void *', 'string', 'string', 'string']);
22
+ const ruggy_delete = lib.func('ruggy_delete', 'int', ['void *', 'string']);
20
23
 
21
24
  // Memory management
22
25
  const ruggy_str_free = lib.func('ruggy_str_free', 'void', ['void *']);
@@ -30,5 +33,8 @@ module.exports = {
30
33
  ruggy_insert,
31
34
  ruggy_find_all,
32
35
  ruggy_find,
36
+ ruggy_find_op,
37
+ ruggy_update_field,
38
+ ruggy_delete,
33
39
  ruggy_str_free
34
40
  };