jexidb 2.0.3 โ†’ 2.1.1

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.
Files changed (79) hide show
  1. package/.babelrc +13 -0
  2. package/.gitattributes +2 -0
  3. package/CHANGELOG.md +132 -101
  4. package/LICENSE +21 -21
  5. package/README.md +301 -639
  6. package/babel.config.json +5 -0
  7. package/dist/Database.cjs +5204 -0
  8. package/docs/API.md +908 -241
  9. package/docs/EXAMPLES.md +701 -177
  10. package/docs/README.md +194 -184
  11. package/examples/iterate-usage-example.js +157 -0
  12. package/examples/simple-iterate-example.js +115 -0
  13. package/jest.config.js +24 -0
  14. package/package.json +63 -54
  15. package/scripts/README.md +47 -0
  16. package/scripts/benchmark-array-serialization.js +108 -0
  17. package/scripts/clean-test-files.js +75 -0
  18. package/scripts/prepare.js +31 -0
  19. package/scripts/run-tests.js +80 -0
  20. package/scripts/score-mode-demo.js +45 -0
  21. package/src/Database.mjs +5325 -0
  22. package/src/FileHandler.mjs +1140 -0
  23. package/src/OperationQueue.mjs +279 -0
  24. package/src/SchemaManager.mjs +268 -0
  25. package/src/Serializer.mjs +702 -0
  26. package/src/managers/ConcurrencyManager.mjs +257 -0
  27. package/src/managers/IndexManager.mjs +2094 -0
  28. package/src/managers/QueryManager.mjs +1490 -0
  29. package/src/managers/StatisticsManager.mjs +262 -0
  30. package/src/managers/StreamingProcessor.mjs +429 -0
  31. package/src/managers/TermManager.mjs +278 -0
  32. package/src/utils/operatorNormalizer.mjs +116 -0
  33. package/test/$not-operator-with-and.test.js +282 -0
  34. package/test/README.md +8 -0
  35. package/test/close-init-cycle.test.js +256 -0
  36. package/test/coverage-method.test.js +93 -0
  37. package/test/critical-bugs-fixes.test.js +1069 -0
  38. package/test/deserialize-corruption-fixes.test.js +296 -0
  39. package/test/exists-method.test.js +318 -0
  40. package/test/explicit-indexes-comparison.test.js +219 -0
  41. package/test/filehandler-non-adjacent-ranges-bug.test.js +175 -0
  42. package/test/index-line-number-regression.test.js +100 -0
  43. package/test/index-missing-index-data.test.js +91 -0
  44. package/test/index-persistence.test.js +491 -0
  45. package/test/index-serialization.test.js +314 -0
  46. package/test/indexed-query-mode.test.js +360 -0
  47. package/test/insert-session-auto-flush.test.js +353 -0
  48. package/test/iterate-method.test.js +272 -0
  49. package/test/legacy-operator-compat.test.js +154 -0
  50. package/test/query-operators.test.js +238 -0
  51. package/test/regex-array-fields.test.js +129 -0
  52. package/test/score-method.test.js +298 -0
  53. package/test/setup.js +17 -0
  54. package/test/term-mapping-minimal.test.js +154 -0
  55. package/test/term-mapping-simple.test.js +257 -0
  56. package/test/term-mapping.test.js +514 -0
  57. package/test/writebuffer-flush-resilience.test.js +204 -0
  58. package/dist/FileHandler.js +0 -688
  59. package/dist/IndexManager.js +0 -353
  60. package/dist/IntegrityChecker.js +0 -364
  61. package/dist/JSONLDatabase.js +0 -1333
  62. package/dist/index.js +0 -617
  63. package/docs/MIGRATION.md +0 -295
  64. package/examples/auto-save-example.js +0 -158
  65. package/examples/cjs-usage.cjs +0 -82
  66. package/examples/close-vs-delete-example.js +0 -71
  67. package/examples/esm-usage.js +0 -113
  68. package/examples/example-columns.idx.jdb +0 -0
  69. package/examples/example-columns.jdb +0 -9
  70. package/examples/example-options.idx.jdb +0 -0
  71. package/examples/example-options.jdb +0 -0
  72. package/examples/example-users.idx.jdb +0 -0
  73. package/examples/example-users.jdb +0 -5
  74. package/examples/simple-test.js +0 -55
  75. package/src/FileHandler.js +0 -674
  76. package/src/IndexManager.js +0 -363
  77. package/src/IntegrityChecker.js +0 -379
  78. package/src/JSONLDatabase.js +0 -1391
  79. package/src/index.js +0 -608
package/docs/README.md CHANGED
@@ -1,184 +1,194 @@
1
- # JexiDB - High-Performance Local JSONL Database
2
-
3
- [![Tests](https://img.shields.io/badge/tests-71%2F71%20passing-brightgreen)](https://github.com/jexidb/jexidb)
4
- [![Performance](https://img.shields.io/badge/performance-10k%20ops%2Fsec-brightgreen)](https://github.com/jexidb/jexidb)
5
- [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
6
-
7
- JexiDB is a high-performance, local JSONL database with intelligent optimizations, real compression, and comprehensive error handling. Perfect for Electron apps, Node.js applications, and any scenario requiring fast local data storage.
8
-
9
- ## โœจ Features
10
-
11
- - ๐Ÿš€ **High Performance**: 10,000+ ops/sec for bulk operations
12
- - ๐Ÿง  **Intelligent Optimizations**: Adaptive mode switching and query optimization
13
- - ๐Ÿ“ฆ **Real Compression**: LZ4 and Gzip compression with automatic fallback
14
- - ๐Ÿ›ก๏ธ **Error Recovery**: Comprehensive error handling with automatic recovery
15
- - ๐Ÿ” **Advanced Queries**: MongoDB-style query operators and nested field support
16
- - ๐Ÿ“Š **Performance Monitoring**: Built-in statistics and optimization recommendations
17
- - ๐ŸŽฏ **Zero Dependencies**: Pure JavaScript implementation
18
- - ๐Ÿ”ง **Production Ready**: 100% test coverage and comprehensive documentation
19
-
20
- ## ๐Ÿš€ Quick Start
21
-
22
- ### Installation
23
-
24
- ```bash
25
- npm install jexidb
26
- ```
27
-
28
- ### Basic Usage
29
-
30
- ```javascript
31
- const { Database } = require('jexidb');
32
-
33
- // Create database
34
- const db = new Database('./data/users.jsonl', {
35
- indexes: { id: true, email: true }
36
- });
37
-
38
- // Initialize
39
- await db.init();
40
-
41
- // Insert data
42
- await db.insert({ id: '1', name: 'John', email: 'john@example.com' });
43
-
44
- // Find data
45
- const user = await db.findOne({ id: '1' });
46
- const users = await db.find({ name: { $regex: /john/i } });
47
-
48
- // Update data
49
- await db.update({ id: '1' }, { name: 'John Updated' });
50
-
51
- // Delete data
52
- await db.delete({ id: '1' });
53
-
54
- // Save and cleanup
55
- await db.save();
56
- await db.destroy();
57
- ```
58
-
59
- ## ๐Ÿ“š Documentation
60
-
61
- - [API Reference](docs/API.md) - Complete API documentation
62
- - [Usage Examples](docs/EXAMPLES.md) - Practical examples and patterns
63
- - [Performance Guide](docs/PERFORMANCE.md) - Optimization strategies
64
- - [Migration Guide](docs/MIGRATION.md) - Migrating from other databases
65
-
66
- ## ๐Ÿ—๏ธ Architecture
67
-
68
- JexiDB is built with a modular architecture:
69
-
70
- - **Database**: Main database class with CRUD operations
71
- - **FileHandler**: Efficient file I/O with batch operations
72
- - **IndexManager**: Intelligent indexing with multiple strategies
73
- - **QueryOptimizer**: Query optimization and execution planning
74
- - **CompressionManager**: Real compression with LZ4 and Gzip
75
- - **CacheManager**: Intelligent caching with adaptive eviction
76
- - **ErrorHandler**: Comprehensive error recovery and logging
77
- - **BackgroundMaintenance**: Non-blocking maintenance operations
78
-
79
- ## ๐ŸŽฏ Performance
80
-
81
- ### Benchmarks
82
-
83
- | Operation | Throughput | Latency |
84
- |-----------|------------|---------|
85
- | Bulk Insert | 10,000 ops/sec | <1ms |
86
- | Single Insert | 1,000 ops/sec | <5ms |
87
- | Indexed Query | 5,000 ops/sec | <2ms |
88
- | Update | 1,000 ops/sec | <10ms |
89
- | Delete | 1,000 ops/sec | <10ms |
90
-
91
- ### Compression
92
-
93
- - **LZ4**: 30-50% size reduction, very fast
94
- - **Gzip**: 20-40% size reduction, good compression
95
- - **Automatic**: Age-based compression strategy
96
-
97
- ## ๐Ÿ”ง Configuration
98
-
99
- ```javascript
100
- const db = new Database('./data.jsonl', {
101
- // Indexes
102
- indexes: {
103
- id: true,
104
- email: true,
105
- 'metadata.created': true
106
- },
107
-
108
- // Behavior
109
- markDeleted: true,
110
- autoSave: true,
111
- validateOnInit: false,
112
- backgroundMaintenance: true,
113
-
114
- // Performance
115
- cache: {
116
- maxSize: 1000,
117
- ttl: 300000
118
- },
119
-
120
- // Compression
121
- compression: {
122
- hot: { type: 'none', threshold: 7 },
123
- warm: { type: 'lz4', threshold: 30 },
124
- cold: { type: 'gzip', threshold: Infinity }
125
- },
126
-
127
- // Error handling
128
- errorHandler: {
129
- logLevel: 'info',
130
- enableRecovery: true
131
- }
132
- });
133
- ```
134
-
135
- ## ๐Ÿงช Testing
136
-
137
- ```bash
138
- # Run all tests
139
- npm test
140
-
141
- # Run benchmarks
142
- npm run benchmark-performance
143
- npm run benchmark-compression
144
-
145
- # Generate test data
146
- npm run generate-test-db
147
- ```
148
-
149
- ## ๐Ÿ“Š Monitoring
150
-
151
- ```javascript
152
- // Get comprehensive statistics
153
- const stats = await db.getStats();
154
- console.log(`Records: ${stats.recordCount}`);
155
- console.log(`File size: ${stats.fileSize} bytes`);
156
- console.log(`Cache hit rate: ${stats.cacheStats.hitRate}%`);
157
-
158
- // Get optimization recommendations
159
- const recommendations = db.getOptimizationRecommendations();
160
- console.log('Optimization tips:', recommendations);
161
- ```
162
-
163
- ## ๐Ÿค Contributing
164
-
165
- 1. Fork the repository
166
- 2. Create a feature branch
167
- 3. Make your changes
168
- 4. Add tests for new functionality
169
- 5. Run the test suite
170
- 6. Submit a pull request
171
-
172
- ## ๐Ÿ“„ License
173
-
174
- MIT License - see [LICENSE](LICENSE) for details.
175
-
176
- ## ๐Ÿ™ Acknowledgments
177
-
178
- - Inspired by JexiDB but with significant improvements
179
- - Built with performance and reliability in mind
180
- - Designed for real-world production use
181
-
182
- ---
183
-
184
- **JexiDB** - Fast, reliable, and intelligent local database storage.
1
+ # JexiDB Documentation
2
+
3
+ Welcome to the JexiDB documentation! This directory contains comprehensive guides and references for using JexiDB effectively.
4
+
5
+ ## ๐Ÿ“š Documentation Structure
6
+
7
+ ### ๐Ÿš€ [API Reference](API.md)
8
+ Complete API documentation covering all methods, options, and features:
9
+ - Database constructor and configuration
10
+ - Core methods (insert, update, delete, find)
11
+ - Advanced features (term mapping, bulk operations)
12
+ - Query operators and complex queries
13
+ - Performance optimization tips
14
+
15
+ ### ๐Ÿ’ก [Examples](EXAMPLES.md)
16
+ Practical examples and real-world use cases:
17
+ - Basic usage patterns
18
+ - User management systems
19
+ - Product catalogs
20
+ - Blog systems
21
+ - Analytics dashboards
22
+ - Performance optimization techniques
23
+ - Error handling strategies
24
+
25
+ ## ๐ŸŽฏ Quick Start
26
+
27
+ If you're new to JexiDB, start with these resources:
28
+
29
+ 1. **Installation**: See the main [README.md](../README.md) for installation instructions
30
+ 2. **Basic Usage**: Check out the [Basic Usage](EXAMPLES.md#basic-usage) section in Examples
31
+ 3. **API Reference**: Browse the [API Reference](API.md) for detailed method documentation
32
+ 4. **Advanced Features**: Explore [Term Mapping](API.md#term-mapping) and [Bulk Operations](API.md#bulk-operations)
33
+
34
+ ## ๐Ÿ” What's New
35
+
36
+ ### Recent Features
37
+ - **Term Mapping**: Reduce database size by up to 77% for repetitive data
38
+ - **Bulk Operations**: High-performance `iterate()` method for large datasets
39
+ - **Advanced Querying**: Support for complex queries with logical operators
40
+ - **Indexed Query Modes**: Strict and permissive query modes for performance control
41
+
42
+ ### Performance Improvements
43
+ - Streaming operations for memory efficiency
44
+ - Automatic term cleanup
45
+ - Optimized indexing strategies
46
+ - Batch processing capabilities
47
+
48
+ ## ๐Ÿ“– Key Concepts
49
+
50
+ ### Indexes
51
+ Define which fields to keep in memory for fast queries:
52
+ ```javascript
53
+ const db = new Database('app.jdb', {
54
+ fields: { // REQUIRED - Define schema
55
+ id: 'number',
56
+ name: 'string',
57
+ email: 'string'
58
+ },
59
+ indexes: { // OPTIONAL - Only fields you query frequently
60
+ email: 'string' // โœ… Login queries
61
+ }
62
+ })
63
+ ```
64
+
65
+ ### Term Mapping
66
+ Optimize storage for repetitive string data:
67
+ ```javascript
68
+ const db = new Database('app.jdb', {
69
+ fields: { // REQUIRED - Define schema
70
+ id: 'number',
71
+ name: 'string',
72
+ tags: 'array:string',
73
+ categories: 'array:string'
74
+ }
75
+ // termMapping is now auto-enabled for array:string fields
76
+ })
77
+ ```
78
+
79
+ ### Bulk Operations
80
+ Process large datasets efficiently:
81
+ ```javascript
82
+ for await (const record of db.iterate({ status: 'pending' })) {
83
+ record.status = 'processed'
84
+ record.updatedAt = Date.now()
85
+ }
86
+ ```
87
+
88
+ ## ๐Ÿ› ๏ธ Common Patterns
89
+
90
+ ### Database Lifecycle
91
+ ```javascript
92
+ const db = new Database('my-app.jdb', options)
93
+ await db.init() // Initialize
94
+ // ... use database ...
95
+ await db.save() // Save changes
96
+ await db.destroy() // Clean up
97
+ ```
98
+
99
+ ### Error Handling
100
+ ```javascript
101
+ try {
102
+ await db.init()
103
+ await db.insert(data)
104
+ await db.save()
105
+ } catch (error) {
106
+ console.error('Database error:', error)
107
+ } finally {
108
+ await db.destroy()
109
+ }
110
+ ```
111
+
112
+ ### Query Patterns
113
+ ```javascript
114
+ // Simple queries
115
+ const users = await db.find({ status: 'active' })
116
+
117
+ // Complex queries
118
+ const results = await db.find({
119
+ age: { '>': 18, '<': 65 },
120
+ $or: [
121
+ { role: 'admin' },
122
+ { role: 'moderator' }
123
+ ]
124
+ })
125
+
126
+ // Case-insensitive search
127
+ const results = await db.find(
128
+ { name: 'john doe' },
129
+ { caseInsensitive: true }
130
+ )
131
+ ```
132
+
133
+ ## ๐Ÿ”ง Configuration Options
134
+
135
+ ### Basic Configuration
136
+ ```javascript
137
+ const db = new Database('database.jdb', {
138
+ create: true, // Create file if doesn't exist
139
+ clear: false, // Clear existing data
140
+ fields: { // REQUIRED - Define schema
141
+ id: 'number',
142
+ name: 'string'
143
+ },
144
+ indexes: { // OPTIONAL - Only fields you query frequently
145
+ name: 'string' // โœ… Search by name
146
+ },
147
+ indexedQueryMode: 'permissive' // Query mode
148
+ })
149
+ ```
150
+
151
+ ### Advanced Configuration
152
+ ```javascript
153
+ const db = new Database('database.jdb', {
154
+ fields: { // REQUIRED - Define schema
155
+ id: 'number',
156
+ name: 'string',
157
+ tags: 'array:string'
158
+ },
159
+ indexes: { // OPTIONAL - Only fields you query frequently
160
+ name: 'string', // โœ… Search by name
161
+ tags: 'array:string' // โœ… Search by tags
162
+ }
163
+ // termMapping is now auto-enabled for array:string fields
164
+ })
165
+ ```
166
+
167
+ ## ๐Ÿ“Š Performance Tips
168
+
169
+ 1. **Use indexed fields** in your queries for best performance
170
+ 2. **Enable term mapping** for datasets with repetitive strings
171
+ 3. **Use `iterate()`** for bulk operations on large datasets
172
+ 4. **Specify fewer indexes** to reduce memory usage
173
+ 5. **Use `save()`** strategically to persist changes
174
+
175
+ ## ๐Ÿ†˜ Getting Help
176
+
177
+ - **Issues**: Report bugs and request features on [GitHub Issues](https://github.com/EdenwareApps/jexidb/issues)
178
+ - **Documentation**: Browse this documentation for detailed guides
179
+ - **Examples**: Check out the [Examples](EXAMPLES.md) for practical use cases
180
+ - **API Reference**: Consult the [API Reference](API.md) for method details
181
+
182
+ ## ๐Ÿ“ Contributing
183
+
184
+ Found an issue with the documentation? Want to add an example?
185
+
186
+ 1. Fork the repository
187
+ 2. Make your changes
188
+ 3. Submit a pull request
189
+
190
+ We welcome contributions to improve the documentation!
191
+
192
+ ---
193
+
194
+ **Happy coding with JexiDB! ๐Ÿš€**
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Example usage of the new iterate() method
3
+ * Demonstrates bulk update capabilities with streaming performance
4
+ */
5
+
6
+ import { Database } from '../src/Database.mjs'
7
+
8
+ async function demonstrateIterate() {
9
+ console.log('๐Ÿš€ JexiDB iterate() Method Demo\n')
10
+
11
+ // Create database with indexing
12
+ const db = new Database('iterate-demo.jdb', {
13
+ debugMode: true,
14
+ termMapping: true,
15
+ indexedFields: ['category', 'price', 'status']
16
+ })
17
+
18
+ await db.init()
19
+
20
+ try {
21
+ // 1. Insert sample data
22
+ console.log('๐Ÿ“ Inserting sample data...')
23
+ const sampleData = [
24
+ { id: 1, name: 'Apple', category: 'fruits', price: 1.50, status: 'active' },
25
+ { id: 2, name: 'Banana', category: 'fruits', price: 0.80, status: 'active' },
26
+ { id: 3, name: 'Orange', category: 'fruits', price: 1.20, status: 'inactive' },
27
+ { id: 4, name: 'Carrot', category: 'vegetables', price: 0.60, status: 'active' },
28
+ { id: 5, name: 'Broccoli', category: 'vegetables', price: 1.80, status: 'active' },
29
+ { id: 6, name: 'Lettuce', category: 'vegetables', price: 0.90, status: 'inactive' },
30
+ { id: 7, name: 'Milk', category: 'dairy', price: 2.50, status: 'active' },
31
+ { id: 8, name: 'Cheese', category: 'dairy', price: 3.20, status: 'active' },
32
+ { id: 9, name: 'Yogurt', category: 'dairy', price: 1.80, status: 'inactive' },
33
+ { id: 10, name: 'Bread', category: 'bakery', price: 2.00, status: 'active' }
34
+ ]
35
+
36
+ for (const item of sampleData) {
37
+ await db.insert(item)
38
+ }
39
+
40
+ console.log(`โœ… Inserted ${sampleData.length} records\n`)
41
+
42
+ // 2. Basic iteration without modifications
43
+ console.log('๐Ÿ” Basic iteration - listing all fruits:')
44
+ for await (const entry of db.iterate({ category: 'fruits' })) {
45
+ console.log(` - ${entry.name}: $${entry.price} (${entry.status})`)
46
+ }
47
+ console.log()
48
+
49
+ // 3. Bulk price update with progress tracking
50
+ console.log('๐Ÿ’ฐ Bulk price update - 10% increase for all active items:')
51
+ let processedCount = 0
52
+ let modifiedCount = 0
53
+
54
+ for await (const entry of db.iterate(
55
+ { status: 'active' },
56
+ {
57
+ chunkSize: 5,
58
+ progressCallback: (progress) => {
59
+ if (progress.processed % 5 === 0) {
60
+ console.log(` ๐Ÿ“Š Progress: ${progress.processed} processed, ${progress.modified} modified`)
61
+ }
62
+ }
63
+ }
64
+ )) {
65
+ const oldPrice = entry.price
66
+ entry.price = Math.round(entry.price * 1.1 * 100) / 100 // 10% increase, rounded to 2 decimals
67
+ entry.lastUpdated = new Date().toISOString()
68
+
69
+ if (oldPrice !== entry.price) {
70
+ console.log(` ๐Ÿ’ต ${entry.name}: $${oldPrice} โ†’ $${entry.price}`)
71
+ }
72
+ }
73
+
74
+ console.log(`โœ… Price update completed: ${processedCount} processed, ${modifiedCount} modified\n`)
75
+
76
+ // 4. Bulk status change with deletions
77
+ console.log('๐Ÿ—‘๏ธ Bulk operations - removing inactive items and updating status:')
78
+ const inactiveItems = await db.find({ status: 'inactive' })
79
+ for (const item of inactiveItems) {
80
+ console.log(` ๐Ÿ—‘๏ธ Deleting inactive item: ${item.name}`)
81
+ await db.delete({ id: item.id })
82
+ }
83
+
84
+ // Update remaining items
85
+ for await (const entry of db.iterate({})) {
86
+ if (entry.status === 'active') {
87
+ entry.status = 'available'
88
+ entry.updatedAt = new Date().toISOString()
89
+ }
90
+ }
91
+
92
+ console.log('โœ… Bulk operations completed\n')
93
+
94
+ // 5. Verify results
95
+ console.log('๐Ÿ“‹ Final results:')
96
+ const allItems = await db.find({})
97
+ console.log(`Total items remaining: ${allItems.length}`)
98
+
99
+ for (const item of allItems) {
100
+ console.log(` - ${item.name} (${item.category}): $${item.price} [${item.status}]`)
101
+ }
102
+
103
+ // 6. Performance demonstration with larger dataset
104
+ console.log('\nโšก Performance test with larger dataset...')
105
+
106
+ // Insert more data for performance test
107
+ const startTime = Date.now()
108
+ for (let i = 11; i <= 1000; i++) {
109
+ await db.insert({
110
+ id: i,
111
+ name: `Product${i}`,
112
+ category: ['electronics', 'clothing', 'books', 'home'][i % 4],
113
+ price: Math.random() * 100,
114
+ status: i % 3 === 0 ? 'inactive' : 'active'
115
+ })
116
+ }
117
+
118
+ const insertTime = Date.now() - startTime
119
+ console.log(`๐Ÿ“ Inserted 990 additional records in ${insertTime}ms`)
120
+
121
+ // Bulk update with performance tracking
122
+ const updateStartTime = Date.now()
123
+ let totalProcessed = 0
124
+
125
+ for await (const entry of db.iterate(
126
+ { status: 'active' },
127
+ {
128
+ chunkSize: 100,
129
+ progressCallback: (progress) => {
130
+ if (progress.completed) {
131
+ totalProcessed = progress.processed
132
+ console.log(`๐Ÿ“Š Final stats: ${progress.processed} processed, ${progress.modified} modified in ${progress.elapsed}ms`)
133
+ }
134
+ }
135
+ }
136
+ )) {
137
+ // Add a processing timestamp
138
+ entry.processedAt = Date.now()
139
+ }
140
+
141
+ const updateTime = Date.now() - updateStartTime
142
+ console.log(`โšก Bulk update completed: ${totalProcessed} records processed in ${updateTime}ms`)
143
+ console.log(`๐Ÿ“ˆ Performance: ${Math.round(totalProcessed / (updateTime / 1000))} records/second`)
144
+
145
+ } finally {
146
+ // Clean up
147
+ await db.close()
148
+ console.log('\n๐Ÿงน Database closed and cleaned up')
149
+ }
150
+ }
151
+
152
+ // Run the demonstration
153
+ if (import.meta.url === `file://${process.argv[1]}`) {
154
+ demonstrateIterate().catch(console.error)
155
+ }
156
+
157
+ export { demonstrateIterate }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Simple example of the iterate() method
3
+ * Demonstrates bulk updates with streaming performance
4
+ */
5
+
6
+ import { Database } from '../src/Database.mjs'
7
+
8
+ async function simpleIterateExample() {
9
+ console.log('๐Ÿš€ JexiDB iterate() Method - Simple Example\n')
10
+
11
+ // Create database
12
+ const db = new Database('simple-iterate.jdb', {
13
+ debugMode: false,
14
+ termMapping: true,
15
+ indexedFields: ['category', 'price']
16
+ })
17
+
18
+ await db.init()
19
+
20
+ try {
21
+ // 1. Insert sample data
22
+ console.log('๐Ÿ“ Inserting sample data...')
23
+ const products = [
24
+ { id: 1, name: 'Apple', category: 'fruits', price: 1.50, inStock: true },
25
+ { id: 2, name: 'Banana', category: 'fruits', price: 0.80, inStock: true },
26
+ { id: 3, name: 'Orange', category: 'fruits', price: 1.20, inStock: false },
27
+ { id: 4, name: 'Carrot', category: 'vegetables', price: 0.60, inStock: true },
28
+ { id: 5, name: 'Broccoli', category: 'vegetables', price: 1.80, inStock: true }
29
+ ]
30
+
31
+ for (const product of products) {
32
+ await db.insert(product)
33
+ }
34
+
35
+ console.log(`โœ… Inserted ${products.length} products\n`)
36
+
37
+ // 2. Basic iteration - list all fruits
38
+ console.log('๐ŸŽ Listing all fruits:')
39
+ for await (const entry of db.iterate({ category: 'fruits' })) {
40
+ console.log(` - ${entry.name}: $${entry.price} (${entry.inStock ? 'in stock' : 'out of stock'})`)
41
+ }
42
+ console.log()
43
+
44
+ // 3. Bulk price update - 10% increase for in-stock items
45
+ console.log('๐Ÿ’ฐ Bulk price update - 10% increase for in-stock items:')
46
+ let updatedCount = 0
47
+
48
+ for await (const entry of db.iterate({ inStock: true })) {
49
+ const oldPrice = entry.price
50
+ entry.price = Math.round(entry.price * 1.1 * 100) / 100 // 10% increase
51
+ entry.lastUpdated = new Date().toISOString()
52
+
53
+ if (oldPrice !== entry.price) {
54
+ console.log(` ๐Ÿ’ต ${entry.name}: $${oldPrice} โ†’ $${entry.price}`)
55
+ updatedCount++
56
+ }
57
+ }
58
+
59
+ console.log(`โœ… Updated ${updatedCount} products\n`)
60
+
61
+ // 4. Bulk status update - mark all vegetables as organic
62
+ console.log('๐ŸŒฑ Marking all vegetables as organic:')
63
+ let organicCount = 0
64
+
65
+ for await (const entry of db.iterate({ category: 'vegetables' })) {
66
+ entry.organic = true
67
+ entry.certifiedAt = new Date().toISOString()
68
+ console.log(` ๐ŸŒฑ ${entry.name} is now organic`)
69
+ organicCount++
70
+ }
71
+
72
+ console.log(`โœ… Marked ${organicCount} vegetables as organic\n`)
73
+
74
+ // 5. Performance test with progress tracking
75
+ console.log('โšก Performance test with progress tracking:')
76
+ let processedCount = 0
77
+
78
+ for await (const entry of db.iterate(
79
+ {}, // All records
80
+ {
81
+ chunkSize: 2,
82
+ progressCallback: (progress) => {
83
+ if (progress.completed) {
84
+ console.log(`๐Ÿ“Š Final stats: ${progress.processed} processed, ${progress.modified} modified in ${progress.elapsed}ms`)
85
+ }
86
+ }
87
+ }
88
+ )) {
89
+ // Add processing timestamp
90
+ entry.processedAt = Date.now()
91
+ processedCount++
92
+ }
93
+
94
+ console.log(`โšก Processed ${processedCount} records\n`)
95
+
96
+ // 6. Verify all changes
97
+ console.log('๐Ÿ“‹ Final results:')
98
+ const allProducts = await db.find({})
99
+ for (const product of allProducts) {
100
+ console.log(` - ${product.name} (${product.category}): $${product.price} ${product.organic ? '๐ŸŒฑ' : ''} ${product.inStock ? 'โœ…' : 'โŒ'}`)
101
+ }
102
+
103
+ } finally {
104
+ // Clean up
105
+ await db.close()
106
+ console.log('\n๐Ÿงน Database closed and cleaned up')
107
+ }
108
+ }
109
+
110
+ // Run the example
111
+ if (import.meta.url === `file://${process.argv[1]}`) {
112
+ simpleIterateExample().catch(console.error)
113
+ }
114
+
115
+ export { simpleIterateExample }