@earth-app/collegedb 1.1.3 → 1.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/README.md CHANGED
@@ -19,6 +19,7 @@ A TypeScript library for **true horizontal scaling** of SQLite-style databases p
19
19
  - [Provider Adapters](#provider-adapters)
20
20
  - [NuxtHub + Drizzle Recipes](#nuxthub--drizzle-recipes)
21
21
  - [Sandbox Benchmarks (Docker Compose)](#sandbox-benchmarks-docker-compose)
22
+ - [In-Memory Providers for Testing & Development](#in-memory-providers-for-testing--development)
22
23
  - [Basic Usage](#basic-usage)
23
24
  - [Multi-Key Shard Mappings](#multi-key-shard-mappings)
24
25
  - [Drop-in Replacement for Existing Databases](#drop-in-replacement-for-existing-databases)
@@ -71,6 +72,7 @@ This allows you to:
71
72
  - Automatic query routing (primary key to shard mapping)
72
73
  - Provider adapters for Redis/Valkey/NuxtHub KV plus PostgreSQL/MySQL/SQLite SQL
73
74
  - Drizzle interop through existing SQL providers (`createPostgreSQLProvider`, `createMySQLProvider`, `createSQLiteProvider`)
75
+ - Auto-allocated generated-id inserts via `insert()` and direct-shard inserts via `insertShard()` for AUTOINCREMENT / RETURNING workflows
74
76
  - Hyperdrive helpers for PostgreSQL and MySQL
75
77
  - Multiple allocation strategies: round-robin, random, hash, location-aware, and mixed read/write strategies
76
78
  - Durable Object shard coordination and shard statistics
@@ -193,18 +195,19 @@ CollegeDB includes a benchmark runner that executes each SQL+KV combination acro
193
195
 
194
196
  ### Scenario Catalog
195
197
 
196
- | Scenario Key | Scenario | What Happens | Workload Per Run |
197
- | ----------------- | -------------------------------- | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
198
- | basic_crud | Basic CRUD round-trip | Insert, read, update, and delete a user via routed queries. | 20 iterations; 4 routed SQL ops per iteration |
199
- | advanced_usage | Advanced lookup workflow | Writes user+post, adds lookup aliases, then validates join and alias-based lookup. | 15 iterations; ~5 routed SQL ops + KV lookup-key updates per iteration |
200
- | migration_mapping | Migration-style mapping creation | Inserts legacy records on a fixed shard, then builds shard mappings in batch and validates routing. | 10 iterations; 20 legacy records mapped per iteration |
201
- | bulk_crud | Bulk CRUD pressure | Performs bulk inserts, half updates, and full delete sweep, then validates shard-wide totals. | 7 iterations; 160 inserts + 80 updates + 160 deletes per iteration |
202
- | indexing | Indexed query scan | Creates an index on posts(user_id) and repeatedly queries the indexed path. | 15 iterations after warmup dataset build |
203
- | metadata_fetch | Metadata inspection | Reads table metadata/introspection rows from one shard. | 14 iterations; 1 metadata query per iteration |
204
- | pragma_or_info | PRAGMA / server info | Runs provider-specific PRAGMA/info query to sample low-level metadata latency. | 14 iterations; 1 pragma/info query per iteration |
205
- | counting | Cross-shard counting | Counts users across all shards to measure fanout aggregation overhead. | 14 iterations; all-shard count aggregation per iteration |
206
- | shard_fanout | Shard fanout query | Runs query fanout to all shards and aggregates shard-level responses. | 14 iterations; 1 all-shards query per iteration |
207
- | reassignment | Shard reassignment flow | Creates a record, reassigns it to another shard, and verifies routed reads still succeed. | 10 iterations; insert + reassignment + verification per iteration |
198
+ | Scenario Key | Scenario | What Happens | Workload Per Run |
199
+ | ----------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
200
+ | basic_crud | Basic CRUD round-trip | Insert, read, update, and delete a user via routed queries. | 20 iterations; 4 routed SQL ops per iteration |
201
+ | advanced_usage | Advanced lookup workflow | Writes user+post, adds lookup aliases, then validates join and alias-based lookup. | 15 iterations; ~5 routed SQL ops + KV lookup-key updates per iteration |
202
+ | migration_mapping | Migration-style mapping creation | Inserts legacy records on a fixed shard, then builds shard mappings in batch and validates routing. | 10 iterations; 20 legacy records mapped per iteration |
203
+ | bulk_crud | Bulk CRUD pressure | Performs bulk inserts, half updates, and full delete sweep, then validates shard-wide totals. | 7 iterations; 160 inserts + 80 updates + 160 deletes per iteration |
204
+ | auto_increment | Auto-generated primary keys | Inserts rows with generated ids on an automatically selected shard, captures the generated key, then validates routed readback. | 6 iterations; insert + generated-id readback per iteration |
205
+ | indexing | Indexed query scan | Creates an index on posts(user_id) and repeatedly queries the indexed path. | 15 iterations after warmup dataset build |
206
+ | metadata_fetch | Metadata inspection | Reads table metadata/introspection rows from one shard. | 14 iterations; 1 metadata query per iteration |
207
+ | pragma_or_info | PRAGMA / server info | Runs provider-specific PRAGMA/info query to sample low-level metadata latency. | 14 iterations; 1 pragma/info query per iteration |
208
+ | counting | Cross-shard counting | Counts users across all shards to measure fanout aggregation overhead. | 14 iterations; all-shard count aggregation per iteration |
209
+ | shard_fanout | Shard fanout query | Runs query fanout to all shards and aggregates shard-level responses. | 14 iterations; 1 all-shards query per iteration |
210
+ | reassignment | Shard reassignment flow | Creates a record, reassigns it to another shard, and verifies routed reads still succeed. | 10 iterations; insert + reassignment + verification per iteration |
208
211
 
209
212
  ### Report Matrices
210
213
 
@@ -439,6 +442,7 @@ Benchmark coverage includes:
439
442
  - advanced lookup/routing workflows
440
443
  - migration-style mapping creation
441
444
  - bulk CRUD
445
+ - auto-generated primary key inserts and readback
442
446
  - indexing queries
443
447
  - metadata fetch
444
448
  - pragma/info queries (provider-specific)
@@ -453,6 +457,264 @@ How to read benchmark rows:
453
457
  - `N/A` means the scenario was intentionally skipped in that environment.
454
458
  - Use the detailed section for full `avg`, `p50`, `p95`, `min`, `max`, and sample count (`n`).
455
459
 
460
+ ## In-Memory Providers for Testing & Development
461
+
462
+ CollegeDB includes lightweight, zero-dependency in-memory mock implementations of the `KVStorage` and `SQLDatabase` interfaces. These are ideal for:
463
+
464
+ - **Unit testing** without external dependencies
465
+ - **Integration testing** with multiple shard combinations
466
+ - **Local development** and rapid iteration
467
+ - **Sandboxed playtesting** of routing logic
468
+
469
+ The in-memory providers work in Cloudflare Workers, Node.js, and Deno environments.
470
+
471
+ ### Quick Start with In-Memory Providers
472
+
473
+ ```typescript
474
+ import { createInMemoryKVProvider, createInMemorySQLProvider, initialize, run, first } from '@earth-app/collegedb';
475
+
476
+ // Create fresh in-memory providers for each test
477
+ const config = {
478
+ kv: createInMemoryKVProvider(),
479
+ shards: {
480
+ 'shard-1': createInMemorySQLProvider(),
481
+ 'shard-2': createInMemorySQLProvider(),
482
+ 'shard-3': createInMemorySQLProvider()
483
+ },
484
+ strategy: 'hash'
485
+ };
486
+
487
+ initialize(config);
488
+
489
+ // Use as normal - all operations happen in-memory
490
+ await run('user-1', 'INSERT INTO users (id, name, email) VALUES (?, ?, ?)', ['user-1', 'Alice', 'alice@example.com']);
491
+
492
+ const user = await first<{ id: string; name: string }>('user-1', 'SELECT id, name FROM users WHERE id = ?', ['user-1']);
493
+ console.log(user); // { id: 'user-1', name: 'Alice' }
494
+ ```
495
+
496
+ ### Unit Testing Example
497
+
498
+ ```typescript
499
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
500
+ import { createInMemoryKVProvider, createInMemorySQLProvider, initialize, resetConfig, run, first } from '@earth-app/collegedb';
501
+
502
+ describe('User Shard Routing', () => {
503
+ beforeEach(() => {
504
+ // Fresh providers for each test
505
+ initialize({
506
+ kv: createInMemoryKVProvider(),
507
+ shards: {
508
+ 'shard-1': createInMemorySQLProvider(),
509
+ 'shard-2': createInMemorySQLProvider(),
510
+ 'shard-3': createInMemorySQLProvider()
511
+ },
512
+ strategy: 'hash'
513
+ });
514
+ });
515
+
516
+ afterEach(() => {
517
+ resetConfig();
518
+ });
519
+
520
+ it('should insert and retrieve a user', async () => {
521
+ await run('user-1', 'INSERT INTO users (id, name, email) VALUES (?, ?, ?)', ['user-1', 'Alice', 'alice@example.com']);
522
+
523
+ const user = await first<{ name: string }>('user-1', 'SELECT name FROM users WHERE id = ?', ['user-1']);
524
+
525
+ expect(user?.name).toBe('Alice');
526
+ });
527
+
528
+ it('should distribute users across shards', async () => {
529
+ // Insert multiple users
530
+ for (let i = 0; i < 9; i++) {
531
+ await run(`user-${i}`, 'INSERT INTO users (id, name) VALUES (?, ?)', [`user-${i}`, `User ${i}`]);
532
+ }
533
+
534
+ // Verify each can be retrieved
535
+ for (let i = 0; i < 9; i++) {
536
+ const user = await first(`user-${i}`, 'SELECT id FROM users WHERE id = ?', [`user-${i}`]);
537
+ expect(user).toBeDefined();
538
+ }
539
+ });
540
+
541
+ it('should handle updates correctly', async () => {
542
+ await run('user-1', 'INSERT INTO users (id, name) VALUES (?, ?)', ['user-1', 'Alice']);
543
+
544
+ await run('user-1', 'UPDATE users SET name = ? WHERE id = ?', ['Alice Updated', 'user-1']);
545
+
546
+ const user = await first<{ name: string }>('user-1', 'SELECT name FROM users WHERE id = ?', ['user-1']);
547
+
548
+ expect(user?.name).toBe('Alice Updated');
549
+ });
550
+ });
551
+ ```
552
+
553
+ ### Integration Testing with Multiple Providers
554
+
555
+ Test different combinations without Docker or external services:
556
+
557
+ ```typescript
558
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
559
+ import {
560
+ createInMemoryKVProvider,
561
+ createInMemorySQLProvider,
562
+ initialize,
563
+ resetConfig,
564
+ run,
565
+ first,
566
+ KVShardMapper
567
+ } from '@earth-app/collegedb';
568
+
569
+ describe('Multi-Provider Integration', () => {
570
+ it('should work with different KV/SQL combinations', async () => {
571
+ const combinations = [{ kvName: 'memory', sqlName: 'memory' }];
572
+
573
+ for (const combo of combinations) {
574
+ resetConfig();
575
+
576
+ initialize({
577
+ kv: createInMemoryKVProvider(),
578
+ shards: {
579
+ 'shard-1': createInMemorySQLProvider(),
580
+ 'shard-2': createInMemorySQLProvider()
581
+ },
582
+ strategy: 'hash'
583
+ });
584
+
585
+ // Test basic operations
586
+ await run('key-1', 'INSERT INTO data (id, value) VALUES (?, ?)', ['key-1', 'test-value']);
587
+
588
+ const row = await first('key-1', 'SELECT value FROM data WHERE id = ?', ['key-1']);
589
+
590
+ expect(row?.value).toBe('test-value');
591
+ }
592
+ });
593
+
594
+ it('should support lookup key mapping', async () => {
595
+ initialize({
596
+ kv: createInMemoryKVProvider(),
597
+ shards: { 'shard-1': createInMemorySQLProvider() },
598
+ strategy: 'hash'
599
+ });
600
+
601
+ const mapper = new KVShardMapper(createInMemoryKVProvider());
602
+
603
+ // Add lookup keys
604
+ await mapper.addLookupKeys('user-123', ['email:alice@example.com', 'username:alice']);
605
+
606
+ // Retrieve via lookup key
607
+ const mapping = await mapper.getShardMapping('email:alice@example.com');
608
+ expect(mapping?.shard).toBeDefined();
609
+ });
610
+ });
611
+ ```
612
+
613
+ ### Performance Testing with In-Memory Providers
614
+
615
+ Run quick performance tests locally without external dependencies:
616
+
617
+ ```typescript
618
+ import { createInMemoryKVProvider, createInMemorySQLProvider, initialize, run } from '@earth-app/collegedb';
619
+
620
+ async function benchmarkInserts(iterations: number): Promise<number> {
621
+ initialize({
622
+ kv: createInMemoryKVProvider(),
623
+ shards: {
624
+ 'shard-1': createInMemorySQLProvider(),
625
+ 'shard-2': createInMemorySQLProvider(),
626
+ 'shard-3': createInMemorySQLProvider()
627
+ },
628
+ strategy: 'hash'
629
+ });
630
+
631
+ const startTime = performance.now();
632
+
633
+ for (let i = 0; i < iterations; i++) {
634
+ const id = `perf-user-${i}`;
635
+ await run(id, 'INSERT INTO users (id, name) VALUES (?, ?)', [id, `User ${i}`]);
636
+ }
637
+
638
+ return performance.now() - startTime;
639
+ }
640
+
641
+ const duration = await benchmarkInserts(1000);
642
+ console.log(`1000 inserts: ${duration.toFixed(2)}ms (${((1000 / duration) * 1000).toFixed(0)} ops/sec)`);
643
+ ```
644
+
645
+ ### Running the Memory Provider Sandbox
646
+
647
+ CollegeDB includes a ready-made sandbox example demonstrating multiple scenarios:
648
+
649
+ ```bash
650
+ bun run test:memory
651
+ ```
652
+
653
+ This runs comprehensive benchmarks including:
654
+
655
+ - Basic CRUD operations
656
+ - Multi-shard data distribution
657
+ - KV storage operations
658
+ - Round-robin strategy testing
659
+ - JOIN query performance
660
+
661
+ ### Supported Operations
662
+
663
+ Both in-memory providers support the complete CollegeDB API:
664
+
665
+ **SQLDatabase features:**
666
+
667
+ - CREATE TABLE / DROP TABLE
668
+ - INSERT / UPDATE / DELETE
669
+ - SELECT with WHERE clauses
670
+ - COUNT(\*) queries
671
+ - JOIN queries
672
+ - PRAGMA queries (basic support)
673
+
674
+ **KVStorage features:**
675
+
676
+ - `get()` / `put()` / `delete()`
677
+ - `list()` with prefix filtering and cursor-based pagination
678
+ - TTL/expiration support
679
+
680
+ ### Limitations
681
+
682
+ The in-memory providers are intentionally simple to avoid dependencies:
683
+
684
+ - **SQL Parser**: Basic pattern matching instead of full SQL parsing; works well for standard CollegeDB patterns but may not handle complex SQL edge cases
685
+ - **Joins**: Supported at application level; cross-shard joins work via multiple routed queries
686
+ - **Transactions**: Not supported; operations are atomic per-statement
687
+ - **Indexes**: Created but not actually used for query optimization
688
+ - **Schema**: Inferred from CREATE TABLE statements; dynamic column detection based on binding order
689
+
690
+ For production use, migrate to appropriate providers (D1, Redis, PostgreSQL, etc.). For testing/development, these limitations are intentional to keep the implementation lightweight and zero-dependency.
691
+
692
+ ### Migrating from In-Memory to Production Providers
693
+
694
+ When ready to migrate from testing to production:
695
+
696
+ ```typescript
697
+ // Before (testing)
698
+ import { createInMemoryKVProvider, createInMemorySQLProvider } from '@earth-app/collegedb';
699
+
700
+ const config = {
701
+ kv: createInMemoryKVProvider(),
702
+ shards: { 'shard-1': createInMemorySQLProvider() }
703
+ };
704
+
705
+ // After (production)
706
+ import { createRedisKVProvider, createPostgreSQLProvider } from '@earth-app/collegedb';
707
+
708
+ const config = {
709
+ kv: createRedisKVProvider(redisClient),
710
+ shards: { 'shard-1': createPostgreSQLProvider(pgPool) }
711
+ };
712
+
713
+ // Rest of configuration stays the same!
714
+ ```
715
+
716
+ The API remains identical - only the provider initialization changes.
717
+
456
718
  ## Basic Usage
457
719
 
458
720
  ```typescript
@@ -572,6 +834,67 @@ This approach provides:
572
834
  - **Optimal read performance**: Queries use `hash` strategy for consistent, high-performance routing
573
835
  - **Flexibility**: Each operation type can use the most appropriate routing strategy
574
836
 
837
+ ### Auto-Generated Primary Keys
838
+
839
+ When your table assigns the primary key during insert, use `insert()` for the automatic shard-allocation path or `insertShard()` when you already know the target shard. Both helpers capture the generated id from provider metadata or `RETURNING` rows, then store the generated-id mapping so the normal routed `first()` / `all()` helpers can read the row back.
840
+
841
+ ```typescript
842
+ import { first, insert, insertShard } from '@earth-app/collegedb';
843
+
844
+ // SQLite / D1
845
+ await createSchema(
846
+ env['db-east'],
847
+ `
848
+ CREATE TABLE IF NOT EXISTS auto_users (
849
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
850
+ name TEXT NOT NULL,
851
+ email TEXT UNIQUE,
852
+ created_at INTEGER
853
+ )
854
+ `
855
+ );
856
+
857
+ const created = await insert('INSERT INTO auto_users (name, email, created_at) VALUES (?, ?, ?)', ['Ada', 'ada@example.com', Date.now()]);
858
+
859
+ const row = await first(String(created.generatedId), 'SELECT * FROM auto_users WHERE id = ?', [created.generatedId]);
860
+ ```
861
+
862
+ ```typescript
863
+ // Direct shard insert when you want to pin the write to a specific shard
864
+ const directCreated = await insertShard('db-east', 'INSERT INTO auto_users (name, email, created_at) VALUES (?, ?, ?)', [
865
+ 'Ada',
866
+ 'ada@example.com',
867
+ Date.now()
868
+ ]);
869
+
870
+ console.log(directCreated.generatedId);
871
+ ```
872
+
873
+ ```typescript
874
+ // PostgreSQL / MySQL 8.0.19+ RETURNING path
875
+ await createSchema(
876
+ env['db-east'],
877
+ `
878
+ CREATE TABLE IF NOT EXISTS auto_users (
879
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
880
+ name VARCHAR(255) NOT NULL,
881
+ email VARCHAR(255) UNIQUE,
882
+ created_at BIGINT
883
+ )
884
+ `
885
+ );
886
+
887
+ const created = await insert('INSERT INTO auto_users (name, email, created_at) VALUES (?, ?, ?) RETURNING id', [
888
+ 'Ada',
889
+ 'ada@example.com',
890
+ Date.now()
891
+ ]);
892
+
893
+ const row = await first(String(created.generatedId), 'SELECT * FROM auto_users WHERE id = ?', [created.generatedId]);
894
+ ```
895
+
896
+ If your SQL dialect uses `RETURNING`, include it in the insert statement. The helper will use the returned row instead of provider metadata when present.
897
+
575
898
  ## Multi-Key Shard Mappings
576
899
 
577
900
  CollegeDB supports **multiple lookup keys** for the same record, allowing you to query by username, email, ID, or any unique identifier. Keys are automatically hashed with SHA-256 for security and privacy.
@@ -1022,42 +1345,44 @@ await first('user-123', 'SELECT * FROM users WHERE email = ?', [email]);
1022
1345
 
1023
1346
  ## API Reference
1024
1347
 
1025
- | Function | Description | Parameters |
1026
- | ------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------ |
1027
- | `collegedb(config, callback)` | Initialize CollegeDB, then run a callback | `CollegeDBConfig, () => T` |
1028
- | `initialize(config)` | Initialize CollegeDB with configuration | `CollegeDBConfig` |
1029
- | `createSchema(db, schema)` | Create schema on a shard database | `SQLDatabase, string` |
1030
- | `prepare(key, sql)` | Prepare a SQL statement for execution | `string, string` |
1031
- | `run(key, sql, bindings)` | Execute a SQL query with primary key routing | `string, string, any[]` |
1032
- | `first(key, sql, bindings)` | Execute a SQL query and return first result | `string, string, any[]` |
1033
- | `all(key, sql, bindings)` | Execute a SQL query and return all results | `string, string, any[]` |
1034
- | `index(key, table, columns, options)` | Create an index on routed shard | `string, string, string or index-column array, CreateIndexOptions` |
1035
- | `indexShard(shard, table, columns, options)` | Create an index on one shard | `string, string, string or index-column array, CreateIndexOptions` |
1036
- | `indexAllShards(table, columns, options)` | Create an index on all shards | `string, string or index-column array, CreateIndexOptions` |
1037
- | `firstByLookupKey(key, sql, bindings, batchSize)` | Resolve secondary-key mapping, fallback to fanout | `string, string, any[], number` |
1038
- | `allByLookupKey(key, sql, bindings, batchSize)` | Resolve secondary-key mapping, fallback to fanout | `string, string, any[], number` |
1039
- | `runShard(shard, sql, bindings)` | Execute a query directly on a specific shard | `string, string, any[]` |
1040
- | `allShard(shard, sql, bindings)` | Execute a query on specific shard, return all results | `string, string, any[]` |
1041
- | `firstShard(shard, sql, bindings)` | Execute a query on specific shard, return first result | `string, string, any[]` |
1042
- | `explain(key, sql, bindings, options)` | Inspect query plan on routed shard | `string, string, any[], ExplainOptions` |
1043
- | `explainShard(shard, sql, bindings, options)` | Inspect query plan on one shard | `string, string, any[], ExplainOptions` |
1044
- | `explainAllShards(sql, bindings, options)` | Inspect query plan on all shards | `string, any[], ExplainOptions` |
1045
- | `count(key, table)` | Count rows on routed shard | `string, string` |
1046
- | `countShard(shard, table)` | Count rows on a specific shard | `string, string` |
1047
- | `countAllShards(table, batchSize)` | Count rows per shard and global total | `string, number` |
1048
- | `runAllShards(sql, bindings, batchSize)` | Execute query on all shards | `string, any[], number` |
1049
- | `allAllShards(sql, bindings, batchSize)` | Execute query on all shards (SQL pagination applies per shard) | `string, any[], number` |
1050
- | `firstAllShards(sql, bindings, batchSize)` | Execute query on all shards, return first row per shard | `string, any[], number` |
1051
- | `allAllShardsGlobal(sql, bindings, options)` | Execute query on all shards, then globally merge/sort/paginate | `string, any[], GlobalAllShardsOptions` |
1052
- | `firstAllShardsGlobal(sql, bindings, options)` | Return first row after global merge/sort/paginate | `string, any[], GlobalAllShardsOptions` |
1053
- | `reassignShard(key, newShard)` | Move primary key to different shard | `string, string` |
1054
- | `listKnownShards()` | Get list of available shards | `void` |
1055
- | `getShardStats()` | Get statistics for all shards | `void` |
1056
- | `getDatabaseSizeForKey(key)` | Get size of key-routed shard in bytes | `string` |
1057
- | `getDatabaseSizeForShard(shard)` | Get size of a specific shard in bytes | `string` |
1058
- | `getDatabaseSizesAllShards(batchSize)` | Get per-shard size data | `number` |
1059
- | `getTotalDatabaseSize(batchSize)` | Get total size across all shards | `number` |
1060
- | `flush()` | Clear all shard mappings (development only) | `void` |
1348
+ | Function | Description | Parameters |
1349
+ | ------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------ |
1350
+ | `collegedb(config, callback)` | Initialize CollegeDB, then run a callback | `CollegeDBConfig, () => T` |
1351
+ | `initialize(config)` | Initialize CollegeDB with configuration | `CollegeDBConfig` |
1352
+ | `createSchema(db, schema)` | Create schema on a shard database | `SQLDatabase, string` |
1353
+ | `prepare(key, sql)` | Prepare a SQL statement for execution | `string, string` |
1354
+ | `run(key, sql, bindings)` | Execute a SQL query with primary key routing | `string, string, any[]` |
1355
+ | `insert(sql, bindings)` | Insert on an automatically selected shard and capture the generated id | `string, any[]` |
1356
+ | `insertShard(shard, sql, bindings)` | Insert directly on a specific shard and capture the generated id | `string, string, any[]` |
1357
+ | `first(key, sql, bindings)` | Execute a SQL query and return first result | `string, string, any[]` |
1358
+ | `all(key, sql, bindings)` | Execute a SQL query and return all results | `string, string, any[]` |
1359
+ | `index(key, table, columns, options)` | Create an index on routed shard | `string, string, string or index-column array, CreateIndexOptions` |
1360
+ | `indexShard(shard, table, columns, options)` | Create an index on one shard | `string, string, string or index-column array, CreateIndexOptions` |
1361
+ | `indexAllShards(table, columns, options)` | Create an index on all shards | `string, string or index-column array, CreateIndexOptions` |
1362
+ | `firstByLookupKey(key, sql, bindings, batchSize)` | Resolve secondary-key mapping, fallback to fanout | `string, string, any[], number` |
1363
+ | `allByLookupKey(key, sql, bindings, batchSize)` | Resolve secondary-key mapping, fallback to fanout | `string, string, any[], number` |
1364
+ | `runShard(shard, sql, bindings)` | Execute a query directly on a specific shard | `string, string, any[]` |
1365
+ | `allShard(shard, sql, bindings)` | Execute a query on specific shard, return all results | `string, string, any[]` |
1366
+ | `firstShard(shard, sql, bindings)` | Execute a query on specific shard, return first result | `string, string, any[]` |
1367
+ | `explain(key, sql, bindings, options)` | Inspect query plan on routed shard | `string, string, any[], ExplainOptions` |
1368
+ | `explainShard(shard, sql, bindings, options)` | Inspect query plan on one shard | `string, string, any[], ExplainOptions` |
1369
+ | `explainAllShards(sql, bindings, options)` | Inspect query plan on all shards | `string, any[], ExplainOptions` |
1370
+ | `count(key, table)` | Count rows on routed shard | `string, string` |
1371
+ | `countShard(shard, table)` | Count rows on a specific shard | `string, string` |
1372
+ | `countAllShards(table, batchSize)` | Count rows per shard and global total | `string, number` |
1373
+ | `runAllShards(sql, bindings, batchSize)` | Execute query on all shards | `string, any[], number` |
1374
+ | `allAllShards(sql, bindings, batchSize)` | Execute query on all shards (SQL pagination applies per shard) | `string, any[], number` |
1375
+ | `firstAllShards(sql, bindings, batchSize)` | Execute query on all shards, return first row per shard | `string, any[], number` |
1376
+ | `allAllShardsGlobal(sql, bindings, options)` | Execute query on all shards, then globally merge/sort/paginate | `string, any[], GlobalAllShardsOptions` |
1377
+ | `firstAllShardsGlobal(sql, bindings, options)` | Return first row after global merge/sort/paginate | `string, any[], GlobalAllShardsOptions` |
1378
+ | `reassignShard(key, newShard)` | Move primary key to different shard | `string, string` |
1379
+ | `listKnownShards()` | Get list of available shards | `void` |
1380
+ | `getShardStats()` | Get statistics for all shards | `void` |
1381
+ | `getDatabaseSizeForKey(key)` | Get size of key-routed shard in bytes | `string` |
1382
+ | `getDatabaseSizeForShard(shard)` | Get size of a specific shard in bytes | `string` |
1383
+ | `getDatabaseSizesAllShards(batchSize)` | Get per-shard size data | `number` |
1384
+ | `getTotalDatabaseSize(batchSize)` | Get total size across all shards | `number` |
1385
+ | `flush()` | Clear all shard mappings (development only) | `void` |
1061
1386
 
1062
1387
  ### Provider Adapter Functions
1063
1388
 
package/dist/index.d.ts CHANGED
@@ -8,12 +8,13 @@
8
8
  * @author Gregory Mitchell
9
9
  * @license MIT
10
10
  */
11
- export { all, allAllShards, allAllShardsGlobal, allByLookupKey, allShard, collegedb, count, countAllShards, countShard, createSchema, explain, explainAllShards, explainShard, first, firstAllShards, firstAllShardsGlobal, firstByLookupKey, firstShard, flush, getClosestRegionFromIP, getDatabaseSizeForKey, getDatabaseSizeForShard, getDatabaseSizesAllShards, getShardStats, getTotalDatabaseSize, index, indexAllShards, indexShard, initialize, initializeAsync, listKnownShards, prepare, reassignShard, resetConfig, run, runAllShards, runShard } from './router';
12
- export type { CreateIndexOptions, ExplainOptions, GlobalAllShardsOptions, IndexColumnDefinition, ShardSizeResult, ShardTableCount } from './router';
11
+ export { all, allAllShards, allAllShardsGlobal, allByLookupKey, allShard, collegedb, count, countAllShards, countShard, createSchema, explain, explainAllShards, explainShard, first, firstAllShards, firstAllShardsGlobal, firstByLookupKey, firstShard, flush, getClosestRegionFromIP, getDatabaseSizeForKey, getDatabaseSizeForShard, getDatabaseSizesAllShards, getShardStats, getTotalDatabaseSize, index, indexAllShards, indexShard, initialize, initializeAsync, insert, insertShard, listKnownShards, prepare, reassignShard, resetConfig, run, runAllShards, runShard } from './router';
12
+ export type { CreateIndexOptions, ExplainOptions, GlobalAllShardsOptions, IndexColumnDefinition, InsertResult, ShardSizeResult, ShardTableCount } from './router';
13
13
  export { ShardCoordinator } from './durable';
14
14
  export { CollegeDBError } from './errors';
15
15
  export { KVShardMapper } from './kvmap';
16
16
  export { createDrizzleSQLProvider, createHyperdriveMySQLProvider, createHyperdrivePostgresProvider, createMySQLProvider, createNuxtHubKVProvider, createPostgreSQLProvider, createRedisKVProvider, createSQLiteProvider, createValkeyKVProvider, isKVStorage, isSQLDatabase, type DrizzleClientLike, type DrizzleSqlChunkLike, type DrizzleSqlTagLike, type HyperdriveBindingLike, type HyperdriveMySQLClientFactory, type HyperdrivePostgresClientFactory, type MySQLClientLike, type NuxtHubKVLike, type PostgresClientLike, type RedisLikeClient, type SQLiteClientLike } from './providers';
17
+ export { InMemoryKVStorage, InMemorySQLDatabase, createInMemoryKVProvider, createInMemorySQLProvider } from './providers-memory';
17
18
  export { autoDetectAndMigrate, checkMigrationNeeded, clearMigrationCache, clearShardMigrationCache, createMappingsForExistingKeys, createSchemaAcrossShards, discoverExistingPrimaryKeys, discoverExistingRecordsWithColumns, dropSchema, integrateExistingDatabase, listTables, migrateRecord, schemaExists, validateTableForSharding, type IntegrationOptions, type IntegrationResult, type ValidationResult } from './migrations';
18
19
  export type { CollegeDBConfig, D1Region, Env, KVListResult, KVStorage, MixedShardingStrategy, OperationType, PreparedStatement, QueryResult, QueryResultMeta, SQLDatabase, ShardCoordinatorState, ShardLocation, ShardMapping, ShardStats, ShardingStrategy } from './types';
19
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACN,GAAG,EACH,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,QAAQ,EACR,SAAS,EACT,KAAK,EACL,cAAc,EACd,UAAU,EACV,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,KAAK,EACL,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,EACV,KAAK,EACL,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,aAAa,EACb,oBAAoB,EACpB,KAAK,EACL,cAAc,EACd,UAAU,EACV,UAAU,EACV,eAAe,EACf,eAAe,EACf,OAAO,EACP,aAAa,EACb,WAAW,EACX,GAAG,EACH,YAAY,EACZ,QAAQ,EACR,MAAM,UAAU,CAAC;AAElB,YAAY,EACX,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,EACN,wBAAwB,EACxB,6BAA6B,EAC7B,gCAAgC,EAChC,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,4BAA4B,EACjC,KAAK,+BAA+B,EACpC,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACN,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,2BAA2B,EAC3B,kCAAkC,EAClC,UAAU,EACV,yBAAyB,EACzB,UAAU,EACV,aAAa,EACb,YAAY,EACZ,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACX,eAAe,EACf,QAAQ,EACR,GAAG,EACH,YAAY,EACZ,SAAS,EACT,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,WAAW,EACX,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACN,GAAG,EACH,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,QAAQ,EACR,SAAS,EACT,KAAK,EACL,cAAc,EACd,UAAU,EACV,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,KAAK,EACL,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,EACV,KAAK,EACL,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,aAAa,EACb,oBAAoB,EACpB,KAAK,EACL,cAAc,EACd,UAAU,EACV,UAAU,EACV,eAAe,EACf,MAAM,EACN,WAAW,EACX,eAAe,EACf,OAAO,EACP,aAAa,EACb,WAAW,EACX,GAAG,EACH,YAAY,EACZ,QAAQ,EACR,MAAM,UAAU,CAAC;AAElB,YAAY,EACX,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,YAAY,EACZ,eAAe,EACf,eAAe,EACf,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,EACN,wBAAwB,EACxB,6BAA6B,EAC7B,gCAAgC,EAChC,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,4BAA4B,EACjC,KAAK,+BAA+B,EACpC,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAGjI,OAAO,EACN,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,2BAA2B,EAC3B,kCAAkC,EAClC,UAAU,EACV,yBAAyB,EACzB,UAAU,EACV,aAAa,EACb,YAAY,EACZ,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACX,eAAe,EACf,QAAQ,EACR,GAAG,EACH,YAAY,EACZ,SAAS,EACT,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,WAAW,EACX,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,MAAM,SAAS,CAAC"}