@earth-app/collegedb 1.1.2 → 1.1.3

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
@@ -23,6 +23,8 @@ A TypeScript library for **true horizontal scaling** of SQLite-style databases p
23
23
  - [Multi-Key Shard Mappings](#multi-key-shard-mappings)
24
24
  - [Drop-in Replacement for Existing Databases](#drop-in-replacement-for-existing-databases)
25
25
  - [Troubleshooting](#troubleshooting)
26
+ - [Cross-Shard Pagination Behavior](#cross-shard-pagination-behavior)
27
+ - [Database Query Best Practices](#database-query-best-practices)
26
28
  - [API Reference](#api-reference)
27
29
  - [Architecture](#architecture)
28
30
  - [Cloudflare Setup](#cloudflare-setup)
@@ -616,6 +618,22 @@ await mapper.addLookupKeys('user-456', ['email:jane@example.com', 'username:jane
616
618
  const user = await first('email:jane@example.com', 'SELECT * FROM users WHERE email = ?', ['jane@example.com']);
617
619
  ```
618
620
 
621
+ ### Lookup-Key Read Helpers With Fanout Fallback
622
+
623
+ When you query by a secondary key and want safe behavior even when a lookup mapping is missing or stale, use the router-level helpers:
624
+
625
+ ```typescript
626
+ import { allByLookupKey, firstByLookupKey } from '@earth-app/collegedb';
627
+
628
+ // Uses lookup-key mapping when present, then falls back to all-shard fanout if needed
629
+ const user = await firstByLookupKey('email:john@example.com', 'SELECT * FROM users WHERE email = ? LIMIT 1', ['john@example.com']);
630
+
631
+ // Same resolution flow, but returns merged row sets
632
+ const matches = await allByLookupKey('username:john_doe', 'SELECT id, username FROM users WHERE username = ?', ['john_doe']);
633
+ ```
634
+
635
+ This avoids accidentally creating a new primary-key mapping for secondary identifiers while still returning results when mappings are unavailable.
636
+
619
637
  ### Security and Privacy
620
638
 
621
639
  **SHA-256 Hashing (Enabled by Default)**: Sensitive data like emails are hashed before being stored as KV keys, protecting user privacy:
@@ -908,28 +926,138 @@ for (const [table, pkColumn] of Object.entries(customIntegration)) {
908
926
  }
909
927
  ```
910
928
 
929
+ ## Cross-Shard Pagination Behavior
930
+
931
+ `allAllShards` and `firstAllShards` execute the exact SQL on each shard independently. That means SQL `LIMIT`/`OFFSET` applies per shard, not globally.
932
+
933
+ ```typescript
934
+ // With two shards, this can return up to 20 total rows (10 per shard)
935
+ const perShard = await allAllShards('SELECT * FROM posts ORDER BY created_at DESC LIMIT 10');
936
+ ```
937
+
938
+ If you need true global merge/sort/pagination across all shard results, use `allAllShardsGlobal` / `firstAllShardsGlobal` and pass sort/pagination options to the library:
939
+
940
+ ```typescript
941
+ import { allAllShardsGlobal, firstAllShardsGlobal } from '@earth-app/collegedb';
942
+
943
+ const page = await allAllShardsGlobal<{ id: string; created_at: number }>('SELECT id, created_at FROM posts', [], {
944
+ sortBy: 'created_at',
945
+ sortDirection: 'desc',
946
+ offset: 20,
947
+ limit: 10
948
+ });
949
+
950
+ const newest = await firstAllShardsGlobal<{ id: string; created_at: number }>('SELECT id, created_at FROM posts', [], {
951
+ sortBy: 'created_at',
952
+ sortDirection: 'desc'
953
+ });
954
+ ```
955
+
956
+ ## Database Query Best Practices
957
+
958
+ ### Use Library Utility Operations for DDL and Inspection
959
+
960
+ CollegeDB now exposes utility helpers for operational tasks that need shard awareness:
961
+
962
+ ```typescript
963
+ import { countAllShards, explainAllShards, getDatabaseSizesAllShards, indexAllShards } from '@earth-app/collegedb';
964
+
965
+ // Create index across all shards
966
+ await indexAllShards('posts', [{ name: 'user_id' }, { name: 'created_at', order: 'DESC' }], {
967
+ ifNotExists: true
968
+ });
969
+
970
+ // Inspect query plan across all shards
971
+ const plans = await explainAllShards('SELECT * FROM posts WHERE user_id = ? ORDER BY created_at DESC LIMIT 20', ['user-123']);
972
+
973
+ // Count rows globally
974
+ const counts = await countAllShards('posts');
975
+
976
+ // Get per-shard size measurements
977
+ const sizes = await getDatabaseSizesAllShards();
978
+ ```
979
+
980
+ Recommended pattern:
981
+
982
+ - Use `indexAllShards` for schema/index consistency.
983
+ - Use `explain`/`explainAllShards` before adding indexes or changing query shapes.
984
+ - Use `countAllShards` and `getDatabaseSizesAllShards` for operational dashboards and rebalancing thresholds.
985
+
986
+ ### Create Targeted Indexes
987
+
988
+ ```sql
989
+ CREATE INDEX IF NOT EXISTS idx_posts_user_id_created_at ON posts(user_id, created_at DESC);
990
+ CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
991
+ ```
992
+
993
+ ### Inspect Query Plans and Statistics
994
+
995
+ ```sql
996
+ EXPLAIN QUERY PLAN SELECT * FROM posts WHERE user_id = ? ORDER BY created_at DESC LIMIT 20;
997
+ PRAGMA optimize;
998
+ ANALYZE;
999
+ ```
1000
+
1001
+ ### Use Bound Parameters (SQL Injection Protection)
1002
+
1003
+ ```typescript
1004
+ // Safe: parameterized query
1005
+ await first('user-123', 'SELECT * FROM users WHERE email = ?', [email]);
1006
+
1007
+ // Avoid string interpolation with user input
1008
+ // BAD: `... WHERE email = '${email}'`
1009
+ ```
1010
+
1011
+ ### Design Search for Scale
1012
+
1013
+ - Exact-match or prefix search fields should be indexed.
1014
+ - Prefer bounded result sets (`LIMIT`) and stable sorting.
1015
+ - For global search pages, pair lightweight per-shard SQL with `allAllShardsGlobal` for final merge/sort/pagination.
1016
+
1017
+ ### Pagination Guidance
1018
+
1019
+ - For routed single-key reads (`first`, `all`), SQL pagination is naturally shard-local and predictable.
1020
+ - For fanout (`allAllShards`, `firstAllShards`), SQL pagination is per-shard.
1021
+ - For user-facing global pages, use `allAllShardsGlobal` so offset/limit apply once after merge.
1022
+
911
1023
  ## API Reference
912
1024
 
913
- | Function | Description | Parameters |
914
- | ------------------------------------------ | ---------------------------------------------------------------- | -------------------------- |
915
- | `collegedb(config, callback)` | Initialize CollegeDB, then run a callback | `CollegeDBConfig, () => T` |
916
- | `initialize(config)` | Initialize CollegeDB with configuration | `CollegeDBConfig` |
917
- | `createSchema(db, schema)` | Create schema on a shard database | `SQLDatabase, string` |
918
- | `prepare(key, sql)` | Prepare a SQL statement for execution | `string, string` |
919
- | `run(key, sql, bindings)` | Execute a SQL query with primary key routing | `string, string, any[]` |
920
- | `first(key, sql, bindings)` | Execute a SQL query and return first result | `string, string, any[]` |
921
- | `all(key, sql, bindings)` | Execute a SQL query and return all results | `string, string, any[]` |
922
- | `runShard(shard, sql, bindings)` | Execute a query directly on a specific shard | `string, string, any[]` |
923
- | `allShard(shard, sql, bindings)` | Execute a query on specific shard, return all results | `string, string, any[]` |
924
- | `firstShard(shard, sql, bindings)` | Execute a query on specific shard, return first result | `string, string, any[]` |
925
- | `runAllShards(sql, bindings, batchSize)` | Execute query on all shards | `string, any[], number` |
926
- | `allAllShards(sql, bindings, batchSize)` | Execute query on all shards, return all results from all shards | `string, any[], number` |
927
- | `firstAllShards(sql, bindings, batchSize)` | Execute query on all shards, return first result from all shards | `string, any[], number` |
928
- | `reassignShard(key, newShard)` | Move primary key to different shard | `string, string` |
929
- | `listKnownShards()` | Get list of available shards | `void` |
930
- | `getShardStats()` | Get statistics for all shards | `void` |
931
- | `getDatabaseSizeForShard(shard)` | Get size of a specific shard in bytes | `string` |
932
- | `flush()` | Clear all shard mappings (development only) | `void` |
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` |
933
1061
 
934
1062
  ### Provider Adapter Functions
935
1063
 
@@ -1192,22 +1320,27 @@ const config: CollegeDBConfig = {
1192
1320
 
1193
1321
  CollegeDB exports TypeScript types for better development experience and type safety:
1194
1322
 
1195
- | Type | Description | Example |
1196
- | ----------------------- | ------------------------------ | --------------------------------------------------- |
1197
- | `CollegeDBConfig` | Main configuration object | `{ kv, shards, strategy }` |
1198
- | `KVStorage` | Provider-agnostic KV contract | `createRedisKVProvider(redisClient)` |
1199
- | `SQLDatabase` | Provider-agnostic SQL contract | `createPostgreSQLProvider(pgPool)` |
1200
- | `NuxtHubKVLike` | NuxtHub/Unstorage KV contract | `createNuxtHubKVProvider(kv)` |
1201
- | `DrizzleClientLike` | Minimal Drizzle DB contract | `createPostgreSQLProvider(drizzleDb, sql)` |
1202
- | `DrizzleSqlTagLike` | Drizzle SQL tag contract | `createSQLiteProvider(drizzleDb, sql)` |
1203
- | `QueryResult` | Standard query response shape | `{ success, results, meta }` |
1204
- | `QueryResultMeta` | Query execution metadata | `{ duration, changes?, last_row_id? }` |
1205
- | `ShardingStrategy` | Single strategy options | `'hash' \| 'location' \| 'round-robin' \| 'random'` |
1206
- | `MixedShardingStrategy` | Mixed strategy configuration | `{ read: 'hash', write: 'location' }` |
1207
- | `OperationType` | Database operation types | `'read' \| 'write'` |
1208
- | `D1Region` | Cloudflare D1 regions | `'wnam' \| 'enam' \| 'weur' \| ...` |
1209
- | `ShardLocation` | Geographic shard configuration | `{ region: 'wnam', priority: 2 }` |
1210
- | `ShardStats` | Shard usage statistics | `{ binding: 'db-east', count: 1542 }` |
1323
+ | Type | Description | Example |
1324
+ | ----------------------- | ------------------------------ | ----------------------------------------------------- |
1325
+ | `CollegeDBConfig` | Main configuration object | `{ kv, shards, strategy }` |
1326
+ | `KVStorage` | Provider-agnostic KV contract | `createRedisKVProvider(redisClient)` |
1327
+ | `SQLDatabase` | Provider-agnostic SQL contract | `createPostgreSQLProvider(pgPool)` |
1328
+ | `NuxtHubKVLike` | NuxtHub/Unstorage KV contract | `createNuxtHubKVProvider(kv)` |
1329
+ | `DrizzleClientLike` | Minimal Drizzle DB contract | `createPostgreSQLProvider(drizzleDb, sql)` |
1330
+ | `DrizzleSqlTagLike` | Drizzle SQL tag contract | `createSQLiteProvider(drizzleDb, sql)` |
1331
+ | `QueryResult` | Standard query response shape | `{ success, results, meta }` |
1332
+ | `QueryResultMeta` | Query execution metadata | `{ duration, changes?, last_row_id? }` |
1333
+ | `ShardingStrategy` | Single strategy options | `'hash' \| 'location' \| 'round-robin' \| 'random'` |
1334
+ | `MixedShardingStrategy` | Mixed strategy configuration | `{ read: 'hash', write: 'location' }` |
1335
+ | `OperationType` | Database operation types | `'read' \| 'write'` |
1336
+ | `D1Region` | Cloudflare D1 regions | `'wnam' \| 'enam' \| 'weur' \| ...` |
1337
+ | `ShardLocation` | Geographic shard configuration | `{ region: 'wnam', priority: 2 }` |
1338
+ | `ShardStats` | Shard usage statistics | `{ binding: 'db-east', count: 1542 }` |
1339
+ | `IndexColumnDefinition` | Index column definition | `{ name: 'created_at', order: 'DESC' }` |
1340
+ | `CreateIndexOptions` | Index creation options | `{ ifNotExists: true, unique: false }` |
1341
+ | `ExplainOptions` | Explain mode options | `{ mode: 'query-plan' }` |
1342
+ | `ShardTableCount` | Per-shard row-count result | `{ shard: 'db-east', count: 100, success: true }` |
1343
+ | `ShardSizeResult` | Per-shard size result | `{ shard: 'db-east', size: 10485760, success: true }` |
1211
1344
 
1212
1345
  #### Mixed Strategy Configuration
1213
1346
 
package/dist/index.d.ts CHANGED
@@ -8,7 +8,8 @@
8
8
  * @author Gregory Mitchell
9
9
  * @license MIT
10
10
  */
11
- export { all, allAllShards, allShard, collegedb, createSchema, first, firstAllShards, firstShard, flush, getClosestRegionFromIP, getDatabaseSizeForShard, getShardStats, initialize, initializeAsync, listKnownShards, prepare, reassignShard, resetConfig, run, runAllShards, runShard } 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, listKnownShards, prepare, reassignShard, resetConfig, run, runAllShards, runShard } from './router';
12
+ export type { CreateIndexOptions, ExplainOptions, GlobalAllShardsOptions, IndexColumnDefinition, ShardSizeResult, ShardTableCount } from './router';
12
13
  export { ShardCoordinator } from './durable';
13
14
  export { CollegeDBError } from './errors';
14
15
  export { KVShardMapper } from './kvmap';
@@ -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,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,KAAK,EACL,cAAc,EACd,UAAU,EACV,KAAK,EACL,sBAAsB,EACtB,uBAAuB,EACvB,aAAa,EACb,UAAU,EACV,eAAe,EACf,eAAe,EACf,OAAO,EACP,aAAa,EACb,WAAW,EACX,GAAG,EACH,YAAY,EACZ,QAAQ,EACR,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,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"}
package/dist/index.js CHANGED
@@ -1,21 +1,21 @@
1
- var pJ=Object.defineProperty;var mJ=(J)=>J;function gJ(J,X){this[J]=mJ.bind(null,X)}var jJ=(J,X)=>{for(var Y in X)pJ(J,Y,{get:X[Y],enumerable:!0,configurable:!0,set:gJ.bind(X,Y)})};var JJ=(J,X)=>()=>(J&&(X=J(J=0)),X);var _;var q=JJ(()=>{_=class _ extends Error{code;constructor(J,X){super(J);if(this.name="CollegeDBError",this.code=X,Error.captureStackTrace)Error.captureStackTrace(this,_)}}});var XJ={};jJ(XJ,{KVShardMapper:()=>k});class k{kv;hashKeys;hashCache=new Map;mappingCache=new Map;knownShardsCache={shards:null,expiresAt:0};mappingCacheTtlMs;knownShardsCacheTtlMs;constructor(J,X={}){this.kv=J,this.hashKeys=X.hashShardMappings??!0,this.mappingCacheTtlMs=X.mappingCacheTtlMs??yJ,this.knownShardsCacheTtlMs=X.knownShardsCacheTtlMs??cJ}getCachedMapping(J){let X=this.mappingCache.get(J);if(!X)return;if(X.expiresAt<Date.now()){this.mappingCache.delete(J);return}return X.mapping}setCachedMapping(J,X){if(this.mappingCache.size>50000){let Y=this.mappingCache.keys().next().value;if(Y)this.mappingCache.delete(Y)}this.mappingCache.set(J,{mapping:X,expiresAt:Date.now()+this.mappingCacheTtlMs})}async cacheMappingForKeys(J,X){let Y=await Promise.all(J.map((Z)=>this.hashKey(Z)));for(let Z of Y)this.setCachedMapping(Z,X)}getCachedKnownShards(){if(this.knownShardsCache.shards&&this.knownShardsCache.expiresAt>=Date.now())return[...this.knownShardsCache.shards];return null}setCachedKnownShards(J){this.knownShardsCache.shards=[...J],this.knownShardsCache.expiresAt=Date.now()+this.knownShardsCacheTtlMs}async hashKey(J){if(!this.hashKeys)return J;let X=this.hashCache.get(J);if(X)return X;let Z=new TextEncoder().encode(J),G=await crypto.subtle.digest("SHA-256",Z),$=new Uint8Array(G),W=Array.from($).map((H)=>H.toString(16).padStart(2,"0")).join("");if(this.hashCache.size<1e4)this.hashCache.set(J,W);return W}async getShardMapping(J){let X=await this.hashKey(J),Y=this.getCachedMapping(X);if(Y!==void 0)return Y;let Z=`${x}${X}`,G=await this.kv.get(Z,"json");if(G)return this.setCachedMapping(X,G),G;let $=await this.kv.get(`${N}${X}`,"json");if($){let W={shard:$.shard,createdAt:$.createdAt,updatedAt:$.updatedAt,originalKey:this.hashKeys?void 0:J};if(this.setCachedMapping(X,W),this.hashKeys)for(let H of $.keys)this.setCachedMapping(H,W);return W}return this.setCachedMapping(X,null),null}async setShardMapping(J,X,Y=[]){let Z=[J,...Y],G=Date.now(),$={shard:X,createdAt:G,updatedAt:G,originalKey:this.hashKeys?void 0:J};if(Z.length===1){let W=await this.hashKey(J),H=`${x}${W}`;await this.kv.put(H,JSON.stringify($)),this.setCachedMapping(W,$)}else{let W=await this.hashKey(J),H=`${N}${W}`,V=this.hashKeys?await Promise.all(Z.map((F)=>this.hashKey(F))):Z,U={shard:X,createdAt:G,updatedAt:G,keys:V};await this.kv.put(H,JSON.stringify(U));let O=Z.map(async(F)=>{let L=await this.hashKey(F),j=`${x}${L}`,E={shard:X,createdAt:G,updatedAt:G,originalKey:this.hashKeys?void 0:F};return this.kv.put(j,JSON.stringify(E))});await Promise.all(O),await this.cacheMappingForKeys(Z,$)}}async updateShardMapping(J,X){let Y=await this.getShardMapping(J);if(!Y)throw new _(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");let Z=await this.hashKey(J),G=`${x}${Z}`,$=`${N}${Z}`,W=await this.kv.get($,"json");if(W){let H=Date.now(),V={...W,shard:X,updatedAt:H};await this.kv.put($,JSON.stringify(V));let U=W.keys.length>0?this.hashKeys?W.keys:W.keys:[await this.hashKey(J)],O=U.map(async(L)=>{let j=`${x}${L}`,E={...Y,shard:X,updatedAt:H};return this.kv.put(j,JSON.stringify(E))});await Promise.all(O);let F={...Y,shard:X,updatedAt:H};if(this.hashKeys)for(let L of U)this.setCachedMapping(L,F);this.setCachedMapping(Z,F)}else{let H={...Y,shard:X,updatedAt:Date.now()};await this.kv.put(G,JSON.stringify(H)),this.setCachedMapping(Z,H)}}async deleteShardMapping(J){let X=await this.hashKey(J),Y=`${x}${X}`,Z=`${N}${X}`,G=await this.kv.get(Z,"json");if(G){await this.kv.delete(Z);let $=G.keys.length>0?this.hashKeys?G.keys:G.keys:[await this.hashKey(J)],W=$.map(async(H)=>{let V=`${x}${H}`;return this.kv.delete(V)});if(await Promise.all(W),this.hashKeys)for(let H of $)this.setCachedMapping(H,null);this.setCachedMapping(X,null)}else await this.kv.delete(Y),this.setCachedMapping(X,null)}async getKnownShards(){let J=this.getCachedKnownShards();if(J)return J;let Y=await this.kv.get(QJ,"json")||[];return this.setCachedKnownShards(Y),Y}async setKnownShards(J){if(!J||J.length===0)return;let X=[...new Set(J.filter(Boolean))];if(X.length===0)return;await this.kv.put(QJ,JSON.stringify(X)),this.setCachedKnownShards(X)}async addKnownShard(J){if(!J)return;let X=await this.getKnownShards();if(!X.includes(J))X.push(J),await this.setKnownShards(X)}async getKeysForShard(J){let X=[],Y=await this.kv.list({prefix:x});for(let G of Y.keys){let $=await this.kv.get(G.name,"json");if($?.shard===J){let W=G.name.replace(x,"");if($.originalKey)X.push($.originalKey);else if(!this.hashKeys)X.push(W)}}let Z=await this.kv.list({prefix:N});for(let G of Z.keys){let $=await this.kv.get(G.name,"json");if($?.shard===J)X.push(...$.keys)}return[...new Set(X)]}async getShardKeyCounts(){let J={},X=await this.kv.list({prefix:x});for(let Z of X.keys){let G=await this.kv.get(Z.name,"json");if(G)J[G.shard]=(J[G.shard]||0)+1}let Y=await this.kv.list({prefix:N});for(let Z of Y.keys){let G=await this.kv.get(Z.name,"json");if(G)J[G.shard]=(J[G.shard]||0)+G.keys.length}return J}async clearAllMappings(){let X=(await this.kv.list({prefix:x})).keys.map((G)=>this.kv.delete(G.name)),Z=(await this.kv.list({prefix:N})).keys.map((G)=>this.kv.delete(G.name));await Promise.all([...X,...Z]),this.mappingCache.clear()}async addLookupKeys(J,X){let Y=await this.getShardMapping(J);if(!Y)throw new _(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");let Z=await this.hashKey(J),G=`${N}${Z}`,$=await this.kv.get(G,"json"),W=[J,...X],H=Date.now();if(!$){let O=this.hashKeys?await Promise.all(W.map((F)=>this.hashKey(F))):W;$={shard:Y.shard,createdAt:Y.createdAt,updatedAt:H,keys:O}}else{let O=this.hashKeys?await Promise.all(W.map((F)=>this.hashKey(F))):W;$={...$,updatedAt:H,keys:[...new Set([...$.keys,...O])]}}await this.kv.put(G,JSON.stringify($));let V=X.map(async(O)=>{let F=await this.hashKey(O),L=`${x}${F}`,j={shard:Y.shard,createdAt:Y.createdAt,updatedAt:H,originalKey:this.hashKeys?void 0:O};return this.kv.put(L,JSON.stringify(j))});await Promise.all(V);let U={shard:Y.shard,createdAt:Y.createdAt,updatedAt:H,originalKey:Y.originalKey};await this.cacheMappingForKeys([J,...X],U)}async setShardMappingsBatch(J,X={}){if(J.length===0)return;let Y=Math.max(1,X.concurrency??25),Z=0,G=Array(Math.min(Y,J.length)).fill(null).map(async()=>{while(Z<J.length){let $=Z++,W=J[$];if(!W)continue;await this.setShardMapping(W.primaryKey,W.shard,W.additionalKeys||[])}});await Promise.all(G)}async getAllLookupKeys(J){let X=await this.hashKey(J),Y=`${N}${X}`,Z=await this.kv.get(Y,"json");if(Z)return Z.keys;let G=await this.getShardMapping(J);if(G)return G.originalKey?[G.originalKey]:[J];throw new _(`No mapping found for key: ${J}`,"MAPPING_NOT_FOUND")}}var x="shard:",N="multikey:",QJ="known_shards",yJ=30000,cJ=1e4;var p=JJ(()=>{q()});var i={};jJ(i,{validateTableForSharding:()=>n,schemaExists:()=>GJ,migrateRecord:()=>RJ,listTables:()=>b,integrateExistingDatabase:()=>DJ,dropSchema:()=>TJ,discoverExistingRecordsWithColumns:()=>l,discoverExistingPrimaryKeys:()=>o,createSchemaAcrossShards:()=>EJ,createSchema:()=>ZJ,createMappingsForExistingKeys:()=>zJ,clearShardMigrationCache:()=>vJ,clearMigrationCache:()=>xJ,checkMigrationNeeded:()=>BJ,autoDetectAndMigrate:()=>wJ});async function PJ(J,X,Y){if(J.length===0)return;let Z=Math.max(1,Math.min(X,J.length)),G=0,$=Array(Z).fill(null).map(async()=>{while(G<J.length){let W=G++,H=J[W];if(H===void 0)continue;await Y(H,W)}});await Promise.all($)}function dJ(J,X,Y,Z){let G=Y.length;switch(Z){case"hash":{let $=0;for(let H=0;H<J.length;H++){let V=J.charCodeAt(H);$=($<<5)-$+V,$=$&$}let W=Math.abs($)%G;return Y[W]}case"random":return Y[Math.floor(Math.random()*G)];default:return Y[X%G]}}async function ZJ(J,X){let Y=X.split(";").map((Z)=>Z.trim()).filter((Z)=>Z.length>0&&!Z.startsWith("--"));for(let Z of Y)try{await J.prepare(Z).run()}catch(G){throw console.error("Failed to execute schema statement:",Z,G),new _(`Schema migration failed: ${G}`,"SCHEMA_MIGRATION_FAILED")}}async function EJ(J,X){let Y=Object.entries(J).map(([Z,G])=>{return ZJ(G,X).catch(($)=>{throw new _(`Failed to create schema on shard ${Z}: ${$.message}`,"SCHEMA_CREATION_FAILED")})});await Promise.all(Y)}async function GJ(J,X){try{return await J.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").bind(X).first()!==null}catch{return!1}}async function TJ(J,...X){for(let Y of X)try{await J.prepare(`DROP TABLE IF EXISTS ${Y}`).run()}catch(Z){console.error(`Failed to drop table ${Y}:`,Z)}}async function b(J){try{return(await J.prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").all()).results.map((Y)=>Y.name)}catch{return[]}}async function RJ(J,X,Y,Z){let G=await J.prepare(`SELECT * FROM ${Z} WHERE id = ?`).bind(Y).first();if(!G)throw new _(`Record with primary key ${Y} not found in source database`,"RECORD_NOT_FOUND");if(!await GJ(X,Z))await ZJ(X,Z);let $=Object.keys(G),W=$.map(()=>"?").join(", "),H=$.map((U)=>G[U]),V=`INSERT OR REPLACE INTO ${Z} (${$.join(", ")}) VALUES (${W})`;await X.prepare(V).bind(...H).run(),await J.prepare(`DELETE FROM ${Z} WHERE id = ?`).bind(Y).run()}async function o(J,X,Y="id"){try{return(await J.prepare(`SELECT ${Y} FROM ${X}`).all()).results.map((G)=>String(G[Y]))}catch(Z){throw new _(`Failed to discover primary keys in table ${X}: ${Z}`,"DISCOVERY_FAILED")}}async function l(J,X,Y="id"){try{let Z=`${X}_columns`,G;if(YJ.has(Z))G=YJ.get(Z).map((V)=>V.name);else{let U=(await J.prepare(`PRAGMA table_info(${X})`).all()).results.map((O)=>({name:O.name,type:O.type}));YJ.set(Z,U),G=U.map((O)=>O.name)}let $=[Y];if(G.includes("username"))$.push("username");if(G.includes("email"))$.push("email");if(G.includes("name"))$.push("name");let W=`SELECT ${$.join(", ")} FROM ${X}`;return(await J.prepare(W).all()).results}catch(Z){throw new _(`Failed to discover records with columns in table ${X}: ${Z}`,"DISCOVERY_FAILED")}}async function zJ(J,X,Y,Z,G={}){if(J.length===0||X.length===0)return;let $=Math.max(1,G.concurrency??25),W=J.map((H,V)=>({primaryKey:H,shard:dJ(H,V,X,Y)}));await Z.setShardMappingsBatch(W,{concurrency:$})}async function n(J,X,Y){let Z=[],G=0;try{if(!await J.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").bind(X).first())return Z.push(`Table '${X}' does not exist`),{isValid:!1,tableName:X,primaryKeyColumn:Y,recordCount:0,issues:Z};if(!(await J.prepare(`PRAGMA table_info(${X})`).all()).results.some((U)=>U.name===Y&&U.pk===1))Z.push(`Primary key column '${Y}' not found or not set as primary key`);if(G=(await J.prepare(`SELECT COUNT(*) as count FROM ${X}`).first())?.count||0,G===0)Z.push(`Table '${X}' is empty`)}catch($){Z.push(`Database validation error: ${$}`)}return{isValid:Z.length===0,tableName:X,primaryKeyColumn:Y,recordCount:G,issues:Z}}async function DJ(J,X,Y,Z={}){let{tables:G,primaryKeyColumn:$="id",strategy:W="hash",addShardMappingsTable:H=!0,dryRun:V=!1,migrateOtherColumns:U=!1,concurrency:O=25}=Z,F=Math.max(1,O),L=[],j=0,E=0,z=0;try{let A=(G||await b(J)).filter((I)=>I!=="shard_mappings");for(let I of A)try{let R=await n(J,I,$);if(!R.isValid){L.push(`Table ${I}: ${R.issues.join(", ")}`);continue}if(U){let T=await l(J,I,$);if(T.length===0){L.push(`Table ${I} has no records to process`);continue}if(!V){let P=T.map((Q)=>{let r=String(Q[$]),K=[];if(Q.username&&typeof Q.username==="string")K.push(`username:${Q.username}`);if(Q.email&&typeof Q.email==="string")K.push(`email:${Q.email}`);if(Q.name&&typeof Q.name==="string")K.push(`name:${Q.name}`);return{primaryKey:r,shard:X,additionalKeys:K}});await Y.setShardMappingsBatch(P,{concurrency:F}),z+=P.length}E+=T.length}else{let T=await o(J,I,$);if(T.length===0){L.push(`Table ${I} has no records to process`);continue}if(!V){let P=T.map((Q)=>({primaryKey:Q,shard:X}));await Y.setShardMappingsBatch(P,{concurrency:F}),z+=P.length}E+=T.length}j++}catch(R){L.push(`Failed to process table ${I}: ${R}`)}if(H&&!V){if(!(await b(J)).includes("shard_mappings"))await J.prepare(`
1
+ var $J=Object.defineProperty;var XJ=(G)=>G;function WJ(G,J){this[G]=XJ.bind(null,J)}var vG=(G,J)=>{for(var Y in J)$J(G,Y,{get:J[Y],enumerable:!0,configurable:!0,set:WJ.bind(J,Y)})};var $G=(G,J)=>()=>(G&&(J=G(G=0)),J);var F;var q=$G(()=>{F=class F extends Error{code;constructor(G,J){super(G);if(this.name="CollegeDBError",this.code=J,Error.captureStackTrace)Error.captureStackTrace(this,F)}}});var XG={};vG(XG,{KVShardMapper:()=>S});class S{kv;hashKeys;hashCache=new Map;mappingCache=new Map;knownShardsCache={shards:null,expiresAt:0};mappingCacheTtlMs;knownShardsCacheTtlMs;constructor(G,J={}){this.kv=G,this.hashKeys=J.hashShardMappings??!0,this.mappingCacheTtlMs=J.mappingCacheTtlMs??HJ,this.knownShardsCacheTtlMs=J.knownShardsCacheTtlMs??OJ}getCachedMapping(G){let J=this.mappingCache.get(G);if(!J)return;if(J.expiresAt<Date.now()){this.mappingCache.delete(G);return}return J.mapping}setCachedMapping(G,J){if(this.mappingCache.size>50000){let Y=this.mappingCache.keys().next().value;if(Y)this.mappingCache.delete(Y)}this.mappingCache.set(G,{mapping:J,expiresAt:Date.now()+this.mappingCacheTtlMs})}async cacheMappingForKeys(G,J){let Y=await Promise.all(G.map((Z)=>this.hashKey(Z)));for(let Z of Y)this.setCachedMapping(Z,J)}getCachedKnownShards(){if(this.knownShardsCache.shards&&this.knownShardsCache.expiresAt>=Date.now())return[...this.knownShardsCache.shards];return null}setCachedKnownShards(G){this.knownShardsCache.shards=[...G],this.knownShardsCache.expiresAt=Date.now()+this.knownShardsCacheTtlMs}async hashKey(G){if(!this.hashKeys)return G;let J=this.hashCache.get(G);if(J)return J;let Z=new TextEncoder().encode(G),$=await crypto.subtle.digest("SHA-256",Z),X=new Uint8Array($),W=Array.from(X).map((H)=>H.toString(16).padStart(2,"0")).join("");if(this.hashCache.size<1e4)this.hashCache.set(G,W);return W}async getShardMapping(G){let J=await this.hashKey(G),Y=this.getCachedMapping(J);if(Y!==void 0)return Y;let Z=`${M}${J}`,$=await this.kv.get(Z,"json");if($)return this.setCachedMapping(J,$),$;let X=await this.kv.get(`${N}${J}`,"json");if(X){let W={shard:X.shard,createdAt:X.createdAt,updatedAt:X.updatedAt,originalKey:this.hashKeys?void 0:G};if(this.setCachedMapping(J,W),this.hashKeys)for(let H of X.keys)this.setCachedMapping(H,W);return W}return this.setCachedMapping(J,null),null}async setShardMapping(G,J,Y=[]){let Z=[G,...Y],$=Date.now(),X={shard:J,createdAt:$,updatedAt:$,originalKey:this.hashKeys?void 0:G};if(Z.length===1){let W=await this.hashKey(G),H=`${M}${W}`;await this.kv.put(H,JSON.stringify(X)),this.setCachedMapping(W,X)}else{let W=await this.hashKey(G),H=`${N}${W}`,O=this.hashKeys?await Promise.all(Z.map((V)=>this.hashKey(V))):Z,U={shard:J,createdAt:$,updatedAt:$,keys:O};await this.kv.put(H,JSON.stringify(U));let _=Z.map(async(V)=>{let L=await this.hashKey(V),I=`${M}${L}`,P={shard:J,createdAt:$,updatedAt:$,originalKey:this.hashKeys?void 0:V};return this.kv.put(I,JSON.stringify(P))});await Promise.all(_),await this.cacheMappingForKeys(Z,X)}}async updateShardMapping(G,J){let Y=await this.getShardMapping(G);if(!Y)throw new F(`No existing mapping found for primary key: ${G}`,"MAPPING_NOT_FOUND");let Z=await this.hashKey(G),$=`${M}${Z}`,X=`${N}${Z}`,W=await this.kv.get(X,"json");if(W){let H=Date.now(),O={...W,shard:J,updatedAt:H};await this.kv.put(X,JSON.stringify(O));let U=W.keys.length>0?this.hashKeys?W.keys:W.keys:[await this.hashKey(G)],_=U.map(async(L)=>{let I=`${M}${L}`,P={...Y,shard:J,updatedAt:H};return this.kv.put(I,JSON.stringify(P))});await Promise.all(_);let V={...Y,shard:J,updatedAt:H};if(this.hashKeys)for(let L of U)this.setCachedMapping(L,V);this.setCachedMapping(Z,V)}else{let H={...Y,shard:J,updatedAt:Date.now()};await this.kv.put($,JSON.stringify(H)),this.setCachedMapping(Z,H)}}async deleteShardMapping(G){let J=await this.hashKey(G),Y=`${M}${J}`,Z=`${N}${J}`,$=await this.kv.get(Z,"json");if($){await this.kv.delete(Z);let X=$.keys.length>0?this.hashKeys?$.keys:$.keys:[await this.hashKey(G)],W=X.map(async(H)=>{let O=`${M}${H}`;return this.kv.delete(O)});if(await Promise.all(W),this.hashKeys)for(let H of X)this.setCachedMapping(H,null);this.setCachedMapping(J,null)}else await this.kv.delete(Y),this.setCachedMapping(J,null)}async getKnownShards(){let G=this.getCachedKnownShards();if(G)return G;let Y=await this.kv.get(zG,"json")||[];return this.setCachedKnownShards(Y),Y}async setKnownShards(G){if(!G||G.length===0)return;let J=[...new Set(G.filter(Boolean))];if(J.length===0)return;await this.kv.put(zG,JSON.stringify(J)),this.setCachedKnownShards(J)}async addKnownShard(G){if(!G)return;let J=await this.getKnownShards();if(!J.includes(G))J.push(G),await this.setKnownShards(J)}async getKeysForShard(G){let J=[],Y=await this.kv.list({prefix:M});for(let $ of Y.keys){let X=await this.kv.get($.name,"json");if(X?.shard===G){let W=$.name.replace(M,"");if(X.originalKey)J.push(X.originalKey);else if(!this.hashKeys)J.push(W)}}let Z=await this.kv.list({prefix:N});for(let $ of Z.keys){let X=await this.kv.get($.name,"json");if(X?.shard===G)J.push(...X.keys)}return[...new Set(J)]}async getShardKeyCounts(){let G={},J=await this.kv.list({prefix:M});for(let Z of J.keys){let $=await this.kv.get(Z.name,"json");if($)G[$.shard]=(G[$.shard]||0)+1}let Y=await this.kv.list({prefix:N});for(let Z of Y.keys){let $=await this.kv.get(Z.name,"json");if($)G[$.shard]=(G[$.shard]||0)+$.keys.length}return G}async clearAllMappings(){let J=(await this.kv.list({prefix:M})).keys.map(($)=>this.kv.delete($.name)),Z=(await this.kv.list({prefix:N})).keys.map(($)=>this.kv.delete($.name));await Promise.all([...J,...Z]),this.mappingCache.clear()}async addLookupKeys(G,J){let Y=await this.getShardMapping(G);if(!Y)throw new F(`No existing mapping found for primary key: ${G}`,"MAPPING_NOT_FOUND");let Z=await this.hashKey(G),$=`${N}${Z}`,X=await this.kv.get($,"json"),W=[G,...J],H=Date.now();if(!X){let _=this.hashKeys?await Promise.all(W.map((V)=>this.hashKey(V))):W;X={shard:Y.shard,createdAt:Y.createdAt,updatedAt:H,keys:_}}else{let _=this.hashKeys?await Promise.all(W.map((V)=>this.hashKey(V))):W;X={...X,updatedAt:H,keys:[...new Set([...X.keys,..._])]}}await this.kv.put($,JSON.stringify(X));let O=J.map(async(_)=>{let V=await this.hashKey(_),L=`${M}${V}`,I={shard:Y.shard,createdAt:Y.createdAt,updatedAt:H,originalKey:this.hashKeys?void 0:_};return this.kv.put(L,JSON.stringify(I))});await Promise.all(O);let U={shard:Y.shard,createdAt:Y.createdAt,updatedAt:H,originalKey:Y.originalKey};await this.cacheMappingForKeys([G,...J],U)}async setShardMappingsBatch(G,J={}){if(G.length===0)return;let Y=Math.max(1,J.concurrency??25),Z=0,$=Array(Math.min(Y,G.length)).fill(null).map(async()=>{while(Z<G.length){let X=Z++,W=G[X];if(!W)continue;await this.setShardMapping(W.primaryKey,W.shard,W.additionalKeys||[])}});await Promise.all($)}async getAllLookupKeys(G){let J=await this.hashKey(G),Y=`${N}${J}`,Z=await this.kv.get(Y,"json");if(Z)return Z.keys;let $=await this.getShardMapping(G);if($)return $.originalKey?[$.originalKey]:[G];throw new F(`No mapping found for key: ${G}`,"MAPPING_NOT_FOUND")}}var M="shard:",N="multikey:",zG="known_shards",HJ=30000,OJ=1e4;var u=$G(()=>{q()});var t={};vG(t,{validateTableForSharding:()=>s,schemaExists:()=>OG,migrateRecord:()=>NG,listTables:()=>h,integrateExistingDatabase:()=>kG,dropSchema:()=>wG,discoverExistingRecordsWithColumns:()=>i,discoverExistingPrimaryKeys:()=>l,createSchemaAcrossShards:()=>BG,createSchema:()=>HG,createMappingsForExistingKeys:()=>CG,clearShardMigrationCache:()=>fG,clearMigrationCache:()=>KG,checkMigrationNeeded:()=>SG,autoDetectAndMigrate:()=>qG});async function MG(G,J,Y){if(G.length===0)return;let Z=Math.max(1,Math.min(J,G.length)),$=0,X=Array(Z).fill(null).map(async()=>{while($<G.length){let W=$++,H=G[W];if(H===void 0)continue;await Y(H,W)}});await Promise.all(X)}function UJ(G,J,Y,Z){let $=Y.length;switch(Z){case"hash":{let X=0;for(let H=0;H<G.length;H++){let O=G.charCodeAt(H);X=(X<<5)-X+O,X=X&X}let W=Math.abs(X)%$;return Y[W]}case"random":return Y[Math.floor(Math.random()*$)];default:return Y[J%$]}}async function HG(G,J){let Y=J.split(";").map((Z)=>Z.trim()).filter((Z)=>Z.length>0&&!Z.startsWith("--"));for(let Z of Y)try{await G.prepare(Z).run()}catch($){throw console.error("Failed to execute schema statement:",Z,$),new F(`Schema migration failed: ${$}`,"SCHEMA_MIGRATION_FAILED")}}async function BG(G,J){let Y=Object.entries(G).map(([Z,$])=>{return HG($,J).catch((X)=>{throw new F(`Failed to create schema on shard ${Z}: ${X.message}`,"SCHEMA_CREATION_FAILED")})});await Promise.all(Y)}async function OG(G,J){try{return await G.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").bind(J).first()!==null}catch{return!1}}async function wG(G,...J){for(let Y of J)try{await G.prepare(`DROP TABLE IF EXISTS ${Y}`).run()}catch(Z){console.error(`Failed to drop table ${Y}:`,Z)}}async function h(G){try{return(await G.prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").all()).results.map((Y)=>Y.name)}catch{return[]}}async function NG(G,J,Y,Z){let $=await G.prepare(`SELECT * FROM ${Z} WHERE id = ?`).bind(Y).first();if(!$)throw new F(`Record with primary key ${Y} not found in source database`,"RECORD_NOT_FOUND");if(!await OG(J,Z))await HG(J,Z);let X=Object.keys($),W=X.map(()=>"?").join(", "),H=X.map((U)=>$[U]),O=`INSERT OR REPLACE INTO ${Z} (${X.join(", ")}) VALUES (${W})`;await J.prepare(O).bind(...H).run(),await G.prepare(`DELETE FROM ${Z} WHERE id = ?`).bind(Y).run()}async function l(G,J,Y="id"){try{return(await G.prepare(`SELECT ${Y} FROM ${J}`).all()).results.map(($)=>String($[Y]))}catch(Z){throw new F(`Failed to discover primary keys in table ${J}: ${Z}`,"DISCOVERY_FAILED")}}async function i(G,J,Y="id"){try{let Z=`${J}_columns`,$;if(WG.has(Z))$=WG.get(Z).map((O)=>O.name);else{let U=(await G.prepare(`PRAGMA table_info(${J})`).all()).results.map((_)=>({name:_.name,type:_.type}));WG.set(Z,U),$=U.map((_)=>_.name)}let X=[Y];if($.includes("username"))X.push("username");if($.includes("email"))X.push("email");if($.includes("name"))X.push("name");let W=`SELECT ${X.join(", ")} FROM ${J}`;return(await G.prepare(W).all()).results}catch(Z){throw new F(`Failed to discover records with columns in table ${J}: ${Z}`,"DISCOVERY_FAILED")}}async function CG(G,J,Y,Z,$={}){if(G.length===0||J.length===0)return;let X=Math.max(1,$.concurrency??25),W=G.map((H,O)=>({primaryKey:H,shard:UJ(H,O,J,Y)}));await Z.setShardMappingsBatch(W,{concurrency:X})}async function s(G,J,Y){let Z=[],$=0;try{if(!await G.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").bind(J).first())return Z.push(`Table '${J}' does not exist`),{isValid:!1,tableName:J,primaryKeyColumn:Y,recordCount:0,issues:Z};if(!(await G.prepare(`PRAGMA table_info(${J})`).all()).results.some((U)=>U.name===Y&&U.pk===1))Z.push(`Primary key column '${Y}' not found or not set as primary key`);if($=(await G.prepare(`SELECT COUNT(*) as count FROM ${J}`).first())?.count||0,$===0)Z.push(`Table '${J}' is empty`)}catch(X){Z.push(`Database validation error: ${X}`)}return{isValid:Z.length===0,tableName:J,primaryKeyColumn:Y,recordCount:$,issues:Z}}async function kG(G,J,Y,Z={}){let{tables:$,primaryKeyColumn:X="id",strategy:W="hash",addShardMappingsTable:H=!0,dryRun:O=!1,migrateOtherColumns:U=!1,concurrency:_=25}=Z,V=Math.max(1,_),L=[],I=0,P=0,x=0;try{let A=($||await h(G)).filter((j)=>j!=="shard_mappings");for(let j of A)try{let R=await s(G,j,X);if(!R.isValid){L.push(`Table ${j}: ${R.issues.join(", ")}`);continue}if(U){let D=await i(G,j,X);if(D.length===0){L.push(`Table ${j} has no records to process`);continue}if(!O){let E=D.map((Q)=>{let YG=String(Q[X]),b=[];if(Q.username&&typeof Q.username==="string")b.push(`username:${Q.username}`);if(Q.email&&typeof Q.email==="string")b.push(`email:${Q.email}`);if(Q.name&&typeof Q.name==="string")b.push(`name:${Q.name}`);return{primaryKey:YG,shard:J,additionalKeys:b}});await Y.setShardMappingsBatch(E,{concurrency:V}),x+=E.length}P+=D.length}else{let D=await l(G,j,X);if(D.length===0){L.push(`Table ${j} has no records to process`);continue}if(!O){let E=D.map((Q)=>({primaryKey:Q,shard:J}));await Y.setShardMappingsBatch(E,{concurrency:V}),x+=E.length}P+=D.length}I++}catch(R){L.push(`Failed to process table ${j}: ${R}`)}if(H&&!O){if(!(await h(G)).includes("shard_mappings"))await G.prepare(`
2
2
  CREATE TABLE IF NOT EXISTS shard_mappings (
3
3
  primary_key TEXT PRIMARY KEY,
4
4
  shard_name TEXT NOT NULL,
5
5
  created_at INTEGER NOT NULL,
6
6
  updated_at INTEGER NOT NULL
7
- );`.trim()).run()}if(!V)await Y.addKnownShard(X)}catch(M){L.push(`Integration failed: ${M}`)}return{success:L.length===0||L.length>0&&j>0,shardName:X,tablesProcessed:j,totalRecords:E,mappingsCreated:z,issues:L}}async function wJ(J,X,Y,Z={}){let{primaryKeyColumn:G="id",tablesToCheck:$,skipCache:W=!1,maxRecordsToCheck:H=1000,migrateOtherColumns:V=!1,concurrency:U=Y.migrationConcurrency??25}=Z,O=Math.max(1,U),F=`${X}_migration_check`;if(!W&&S.has(F))return{migrationNeeded:!1,migrationPerformed:!1,recordsMigrated:0,tablesProcessed:0,issues:[]};let L=[],j=0,E=0,z=!1,M=!1;try{let{KVShardMapper:A}=await Promise.resolve().then(() => (p(),XJ)),I=new A(Y.kv,{hashShardMappings:Y.hashShardMappings,mappingCacheTtlMs:Y.mappingCacheTtlMs,knownShardsCacheTtlMs:Y.knownShardsCacheTtlMs}),R=await b(J),T=$||R.filter((P)=>P!=="shard_mappings"&&!P.startsWith("sqlite_")&&P!=="sqlite_sequence");if(T.length===0)return S.set(F,!0),{migrationNeeded:!1,migrationPerformed:!1,recordsMigrated:0,tablesProcessed:0,issues:[]};for(let P of T)try{let Q=await n(J,P,G);if(!Q.isValid||Q.recordCount===0)continue;let r=Math.min(H,Q.recordCount),K=await J.prepare(`
8
- SELECT ${G} FROM ${P}
9
- ORDER BY ${G}
10
- LIMIT ?`.trim()).bind(r).all(),IJ=0,hJ=K.results.slice(0,10).map(async(C)=>{let B=String(C[G]);return{key:B,mapping:await I.getShardMapping(B)}}),uJ=await Promise.all(hJ);for(let C of uJ)if(!C.mapping)IJ++,z=!0;if(IJ>0){if(Y.debug)console.log(`Auto-migrating table ${P} in shard ${X} (${Q.recordCount} records)`);if(V){let C=await l(J,P,G),B=[];if(await PJ(C,O,async(D)=>{let e=String(D[G]);if(await I.getShardMapping(e))return;let d=[];if(D.username&&typeof D.username==="string")d.push(`username:${D.username}`);if(D.email&&typeof D.email==="string")d.push(`email:${D.email}`);if(D.name&&typeof D.name==="string")d.push(`name:${D.name}`);B.push({primaryKey:e,shard:X,additionalKeys:d})}),B.length>0)await I.setShardMappingsBatch(B,{concurrency:O});j+=B.length}else{let C=await o(J,P,G),B=[];if(await PJ(C,O,async(D)=>{if(!await I.getShardMapping(D))B.push({primaryKey:D,shard:X})}),B.length>0)await I.setShardMappingsBatch(B,{concurrency:O});j+=B.length}if(E++,M=!0,Y.debug)console.log(`Auto-migrated ${j} records from table ${P}`)}}catch(Q){L.push(`Auto-migration failed for table ${P}: ${Q}`)}if(M){if(await I.addKnownShard(X),!R.includes("shard_mappings"))await J.prepare(`CREATE TABLE IF NOT EXISTS shard_mappings (
7
+ );`.trim()).run()}if(!O)await Y.addKnownShard(J)}catch(w){L.push(`Integration failed: ${w}`)}return{success:L.length===0||L.length>0&&I>0,shardName:J,tablesProcessed:I,totalRecords:P,mappingsCreated:x,issues:L}}async function qG(G,J,Y,Z={}){let{primaryKeyColumn:$="id",tablesToCheck:X,skipCache:W=!1,maxRecordsToCheck:H=1000,migrateOtherColumns:O=!1,concurrency:U=Y.migrationConcurrency??25}=Z,_=Math.max(1,U),V=`${J}_migration_check`;if(!W&&K.has(V))return{migrationNeeded:!1,migrationPerformed:!1,recordsMigrated:0,tablesProcessed:0,issues:[]};let L=[],I=0,P=0,x=!1,w=!1;try{let{KVShardMapper:A}=await Promise.resolve().then(() => (u(),XG)),j=new A(Y.kv,{hashShardMappings:Y.hashShardMappings,mappingCacheTtlMs:Y.mappingCacheTtlMs,knownShardsCacheTtlMs:Y.knownShardsCacheTtlMs}),R=await h(G),D=X||R.filter((E)=>E!=="shard_mappings"&&!E.startsWith("sqlite_")&&E!=="sqlite_sequence");if(D.length===0)return K.set(V,!0),{migrationNeeded:!1,migrationPerformed:!1,recordsMigrated:0,tablesProcessed:0,issues:[]};for(let E of D)try{let Q=await s(G,E,$);if(!Q.isValid||Q.recordCount===0)continue;let YG=Math.min(H,Q.recordCount),b=await G.prepare(`
8
+ SELECT ${$} FROM ${E}
9
+ ORDER BY ${$}
10
+ LIMIT ?`.trim()).bind(YG).all(),xG=0,YJ=b.results.slice(0,10).map(async(k)=>{let z=String(k[$]);return{key:z,mapping:await j.getShardMapping(z)}}),ZJ=await Promise.all(YJ);for(let k of ZJ)if(!k.mapping)xG++,x=!0;if(xG>0){if(Y.debug)console.log(`Auto-migrating table ${E} in shard ${J} (${Q.recordCount} records)`);if(O){let k=await i(G,E,$),z=[];if(await MG(k,_,async(v)=>{let ZG=String(v[$]);if(await j.getShardMapping(ZG))return;let o=[];if(v.username&&typeof v.username==="string")o.push(`username:${v.username}`);if(v.email&&typeof v.email==="string")o.push(`email:${v.email}`);if(v.name&&typeof v.name==="string")o.push(`name:${v.name}`);z.push({primaryKey:ZG,shard:J,additionalKeys:o})}),z.length>0)await j.setShardMappingsBatch(z,{concurrency:_});I+=z.length}else{let k=await l(G,E,$),z=[];if(await MG(k,_,async(v)=>{if(!await j.getShardMapping(v))z.push({primaryKey:v,shard:J})}),z.length>0)await j.setShardMappingsBatch(z,{concurrency:_});I+=z.length}if(P++,w=!0,Y.debug)console.log(`Auto-migrated ${I} records from table ${E}`)}}catch(Q){L.push(`Auto-migration failed for table ${E}: ${Q}`)}if(w){if(await j.addKnownShard(J),!R.includes("shard_mappings"))await G.prepare(`CREATE TABLE IF NOT EXISTS shard_mappings (
11
11
  primary_key TEXT PRIMARY KEY,
12
12
  shard_name TEXT NOT NULL,
13
13
  created_at INTEGER NOT NULL,
14
14
  updated_at INTEGER NOT NULL
15
15
  );
16
- `).run()}if(S.set(F,!0),M&&Y.debug)console.log(`Auto-migration completed for shard ${X}: ${j} records from ${E} tables`)}catch(A){L.push(`Auto-migration error: ${A}`)}return{migrationNeeded:z,migrationPerformed:M,recordsMigrated:j,tablesProcessed:E,issues:L}}async function BJ(J,X,Y){let Z=`${X}_migration_check`;if(S.has(Z))return!1;try{let G=await b(J);if(G.includes("shard_mappings"))return S.set(Z,!0),!1;let{KVShardMapper:W}=await Promise.resolve().then(() => (p(),XJ)),H=new W(Y.kv,{hashShardMappings:Y.hashShardMappings,mappingCacheTtlMs:Y.mappingCacheTtlMs,knownShardsCacheTtlMs:Y.knownShardsCacheTtlMs}),V=G.filter((U)=>U!=="shard_mappings"&&!U.startsWith("sqlite_")&&U!=="sqlite_sequence");for(let U of V.slice(0,3))try{if(((await J.prepare(`SELECT COUNT(*) as count FROM ${U} LIMIT 1`).first())?.count||0)>0){let L=await J.prepare(`SELECT id FROM ${U} LIMIT 1`).first();if(L){let j=String(L.id);if(!await H.getShardMapping(j))return!0}}}catch{continue}return!1}catch{return!1}}function xJ(){S.clear()}function vJ(J){let X=`${J}_migration_check`;S.delete(X)}var S,YJ;var m=JJ(()=>{q();S=new Map,YJ=new Map});q();p();var y=null,h=null,u=new Map;function f(J){if(!h)h=new k(J.kv,{hashShardMappings:J.hashShardMappings,mappingCacheTtlMs:J.mappingCacheTtlMs,knownShardsCacheTtlMs:J.knownShardsCacheTtlMs});return h}function oJ(J){y=J,h=new k(J.kv,{hashShardMappings:J.hashShardMappings,mappingCacheTtlMs:J.mappingCacheTtlMs,knownShardsCacheTtlMs:J.knownShardsCacheTtlMs}),u.clear();try{let X=f(J);Promise.resolve().then(async()=>{let Y=await X.getKnownShards(),Z=Array.from(new Set([...Y,...Object.keys(J.shards)]));await X.setKnownShards(Z)}).catch(()=>{return})}catch{}if(J.shards&&Object.keys(J.shards).length>0&&!J.disableAutoMigration)NJ(J).catch((X)=>{console.warn("Background auto-migration failed:",X)})}async function MJ(J){y=J,h=new k(J.kv,{hashShardMappings:J.hashShardMappings,mappingCacheTtlMs:J.mappingCacheTtlMs,knownShardsCacheTtlMs:J.knownShardsCacheTtlMs}),u.clear();try{let X=f(J),Y=await X.getKnownShards(),Z=Array.from(new Set([...Y,...Object.keys(J.shards)]));await X.setKnownShards(Z)}catch{}if(J.shards&&Object.keys(J.shards).length>0&&!J.disableAutoMigration)try{await NJ(J)}catch(X){console.warn("Auto migration failed:",X)}}async function lJ(J,X){return await MJ(J),await X()}async function NJ(J){try{let{autoDetectAndMigrate:X}=await Promise.resolve().then(() => (m(),i)),Y=Object.keys(J.shards);if(J.debug)console.log(`\uD83D\uDD0D Checking ${Y.length} shards for existing data...`);let Z=Y.map(async(W)=>{let H=J.shards[W];if(!H)return null;try{let V=await X(H,W,J,{maxRecordsToCheck:1000});return{shardName:W,...V}}catch(V){return console.warn(`Auto-migration failed for shard ${W}:`,V),null}}),$=(await Promise.all(Z)).filter((W)=>W?.migrationPerformed);if(J.debug)if($.length>0){let W=$.reduce((H,V)=>H+(V?.recordsMigrated||0),0);console.log(`\uD83C\uDF89 Auto-migration completed! Migrated ${W} records across ${$.length} shards`),$.forEach((H)=>{if(H)console.log(` ✅ ${H.shardName}: ${H.recordsMigrated} records from ${H.tablesProcessed} tables`)})}else console.log("✅ All shards ready - no migration needed")}catch(X){console.warn("Background auto-migration setup failed:",X)}}function nJ(){y=null,h=null,u.clear()}function w(){if(!y)throw new _("CollegeDB not initialized. Call initialize() first.","NOT_INITIALIZED");return y}function iJ(J){let X=J.trim().toUpperCase();if(X.startsWith("SELECT")||X.startsWith("VALUES")||X.startsWith("TABLE")||X.startsWith("PRAGMA")||X.startsWith("EXPLAIN")||X.startsWith("WITH")||X.startsWith("SHOW"))return"read";return"write"}function sJ(J,X){let Y=J.strategy||"hash";if(typeof Y==="string")return Y;let Z=Y;return Z[X]||Z.write||Z.read||"hash"}function tJ(J,X){if(J===X)return 0;let Y={wnam:{lat:37.7749,lon:-122.4194},enam:{lat:40.7128,lon:-74.006},weur:{lat:51.5074,lon:-0.1278},eeur:{lat:52.52,lon:13.405},apac:{lat:35.6762,lon:139.6503},oc:{lat:-33.8688,lon:151.2093},me:{lat:25.2048,lon:55.2708},af:{lat:-26.2041,lon:28.0473}},Z=Y[J],G=Y[X],$=Z.lat-G.lat,W=Z.lon-G.lon;return Math.sqrt($*$+W*W)}function aJ(J){let X=J.cf;if(!X||!X.country)return"wnam";let{country:Y,continent:Z}=X;if(["US","CA","MX"].includes(Y)){let G=X.region||X.regionCode||"",$=X.timezone||"";if(G.includes("CA")||G.includes("WA")||G.includes("OR")||G.includes("NV")||G.includes("AZ")||G.includes("UT")||$.includes("Pacific")||$.includes("America/Los_Angeles"))return"wnam";return"enam"}if(["GL","PM","BM"].includes(Y))return"enam";if(["GB","IE","FR","ES","PT","NL","BE","LU","CH","AT","IT"].includes(Y))return"weur";if(["DE","PL","CZ","SK","HU","SI","HR","BA","RS","ME","MK","AL","BG","RO","MD","UA","BY","LT","LV","EE","FI","SE","NO","DK","IS"].includes(Y))return"eeur";if(Y==="RU")return"eeur";if(["JP","KR","CN","HK","TW","MO","MN","KP"].includes(Y))return"apac";if(["TH","VN","SG","MY","ID","PH","BN","KH","LA","MM","TL","IN","PK","BD","LK","NP","BT","MV","AF"].includes(Y))return"apac";if(["AU","NZ","PG","FJ","NC","VU","SB","WS","TO","KI","NR","PW","FM","MH","TV"].includes(Y))return"oc";if(["AE","SA","QA","KW","BH","OM","YE","IQ","IR","SY","LB","JO","IL","PS","TR","CY"].includes(Y))return"me";if(Z==="AF"||["EG","LY","TN","DZ","MA","SD","SS","ET","ER","DJ","SO"].includes(Y))return"af";if(["KZ","UZ","TM","TJ","KG"].includes(Y))return"eeur";if(Z==="SA"||["BR","AR","CL","PE","CO","VE","EC","BO","PY","UY","GY","SR","GF"].includes(Y))return"enam";if(["GT","BZ","SV","HN","NI","CR","PA","CU","JM","HT","DO","PR","TT","BB","GD","VC","LC","DM","AG","KN"].includes(Y))return"enam";return"wnam"}function rJ(J){if(typeof J==="string")return J;return J.region||"wnam"}async function CJ(J){try{let[X,Y]=await Promise.all([J.prepare("PRAGMA page_count").first(),J.prepare("PRAGMA page_size").first()]);if(!X?.page_count||!Y?.page_size)throw new _("Failed to retrieve database size information","SIZE_QUERY_FAILED");return X.page_count*Y.page_size}catch(X){throw new _(`Failed to get database size: ${X instanceof Error?X.message:"Unknown error"}`,"SIZE_QUERY_FAILED")}}async function eJ(J,X){let Y=Math.max(0,X.sizeCacheTtlMs??30000),Z=u.get(J);if(Z&&Z.expiresAt>=Date.now())return Z.size;let G=X.shards[J];if(!G)throw new _(`Shard ${J} not found in configuration`,"SHARD_NOT_FOUND");let $=await CJ(G);if(Y>0)u.set(J,{size:$,expiresAt:Date.now()+Y});return $}async function JX(J,X){if(typeof X.maxDatabaseSize!=="number"||!Number.isFinite(X.maxDatabaseSize)||X.maxDatabaseSize<=0)return J;let Y=X.maxDatabaseSize,G=(await Promise.allSettled(J.map(async($)=>{let W=await eJ($,X);return{shard:$,size:W,withinLimit:W<Y}}))).filter(($)=>$.status==="fulfilled"&&$.value.withinLimit).map(($)=>$.value.shard);if(G.length===0){if(X.debug)console.warn("All shards exceed maxDatabaseSize limit. Allowing allocation to prevent failure.");return J}if(X.debug&&G.length<J.length){let $=J.filter((W)=>!G.includes(W));console.log(`Excluded ${$.length} shards due to size limits: ${$.join(", ")}`)}return G}function XX(J,X,Y,Z){let G=X.filter((O)=>Y[O]);if(G.length===0){let O=0;for(let L=0;L<Z.length;L++){let j=Z.charCodeAt(L);O=(O<<5)-O+j,O=O&O}let F=Math.abs(O)%X.length;return X[F]}let $=G.map((O)=>{let F=Y[O],L=tJ(J,rJ(F)),j=typeof F==="object"?F.priority||1:1,E=L-j*0.1;return{shard:O,score:E,distance:L,priority:j}});$.sort((O,F)=>O.score-F.score);let W=$[0].score,H=$.filter((O)=>Math.abs(O.score-W)<0.01);if(H.length===1)return H[0].shard;let V=0;for(let O=0;O<Z.length;O++){let F=Z.charCodeAt(O);V=(V<<5)-V+F,V=V&V}let U=Math.abs(V)%H.length;return H[U].shard}function g(J,X,Y,Z){switch(J){case"hash":{let G=0;for(let W=0;W<X.length;W++){let H=X.charCodeAt(W);G=(G<<5)-G+H,G=G&G}let $=Math.abs(G)%Y.length;return Y[$]||Y[0]}case"location":{if(!Z.targetRegion)return g("hash",X,Y,Z);return XX(Z.targetRegion,Y,Z.shardLocations||{},X)}case"random":return Y[Math.floor(Math.random()*Y.length)]||Y[0];default:return g("hash",X,Y,Z)}}async function YX(J,X="write"){let Y=w(),Z=f(Y),G=await Z.getShardMapping(J);if(G)return G.shard;let $=Object.keys(Y.shards);if($.length===0)throw new _("No shards configured","NO_SHARDS");let W=await JX($,Y),H,V=sJ(Y,X);if(Y.coordinator)try{let U=Y.coordinator.idFromName("default"),F=await Y.coordinator.get(U).fetch("http://coordinator/allocate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({primaryKey:J,strategy:V,operationType:X,targetRegion:Y.targetRegion,shardLocations:Y.shardLocations,availableShards:W})});if(F.ok)H=(await F.json()).shard;else H=g(V,J,W,Y)}catch(U){console.warn("Coordinator allocation failed, falling back to local strategy:",U),H=g(V,J,W,Y)}else H=g(V,J,W,Y);return await Z.setShardMapping(J,H),H}async function ZX(J,X="write"){let Y=w(),Z=await YX(J,X),G=Y.shards[Z];if(!G)throw new _(`Shard ${Z} not found in configuration`,"SHARD_NOT_FOUND");return G}async function GX(J,X){let{createSchema:Y}=await Promise.resolve().then(() => (m(),i));await Y(J,X)}async function s(J,X){let Y=iJ(X);return(await ZX(J,Y)).prepare(X)}async function $X(J,X,Y=[]){let G=await(await s(J,X)).bind(...Y).run();if(!G.success)throw new _(`Query failed: ${G.error||"Unknown error"}`,"QUERY_FAILED");return G}async function WX(J,X,Y=[]){let G=await(await s(J,X)).bind(...Y).all();if(!G.success)throw new _(`Query failed: ${G.error||"Unknown error"}`,"QUERY_FAILED");return G}async function HX(J,X,Y=[]){return await(await s(J,X)).bind(...Y).first()}async function VX(J,X,Y){let Z=w();if(!Z.shards[X])throw new _(`Shard ${X} not found in configuration`,"SHARD_NOT_FOUND");let G=f(Z),$=await G.getShardMapping(J);if(!$)throw new _(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");if($.shard!==X){let{migrateRecord:W}=await Promise.resolve().then(() => (m(),i)),H=Z.shards[$.shard],V=Z.shards[X];if(!H||!V)throw new _("Source or target shard not available","SHARD_UNAVAILABLE");await W(H,V,J,Y)}await G.updateShardMapping(J,X)}async function UX(){let J=w();if(J.coordinator)try{let X=J.coordinator.idFromName("default"),Z=await J.coordinator.get(X).fetch("http://coordinator/shards");if(Z.ok)return await Z.json()}catch(X){console.warn("Failed to get shards from coordinator:",X)}try{let Y=await f(J).getKnownShards(),Z=new Set([...Object.keys(J.shards),...Y]);return Array.from(Z)}catch{return Object.keys(J.shards)}}async function OX(){let J=w();if(J.coordinator)try{let G=J.coordinator.idFromName("default"),W=await J.coordinator.get(G).fetch("http://coordinator/stats");if(W.ok)return await W.json()}catch(G){console.warn("Failed to get stats from coordinator:",G)}let X=f(J),Y=await X.getShardKeyCounts(),Z=Object.keys(J.shards);try{let G=await X.getKnownShards();Z=Array.from(new Set([...Z,...G]))}catch{}return Z.map((G)=>({binding:G,count:Y[G]||0}))}async function _X(J,X,Y=[]){let G=w().shards[J];if(!G)throw new _(`Shard ${J} not found`,"SHARD_NOT_FOUND");let $=await G.prepare(X).bind(...Y).run();if(!$.success)throw new _(`Query failed: ${$.error||"Unknown error"}`,"QUERY_FAILED");return $}async function FX(J,X,Y=[]){let G=w().shards[J];if(!G)throw new _(`Shard ${J} not found`,"SHARD_NOT_FOUND");return await G.prepare(X).bind(...Y).all()}async function LX(J,X,Y=[]){let G=w().shards[J];if(!G)throw new _(`Shard ${J} not found`,"SHARD_NOT_FOUND");return await G.prepare(X).bind(...Y).first()}async function AX(J,X=[],Y=50){let Z=w(),G=[];for(let[W,H]of Object.entries(Z.shards)){if(!W||!H){console.error(`Shard ${W??"<null>"} not found, skipping`);continue}G.push(()=>H.prepare(J).bind(...X).run().catch((V)=>{return console.error(`Error executing query on shard ${W}:`,V),{success:!1,results:[],error:V instanceof Error?V.message:String(V),meta:{duration:0}}}))}let $=[];for(let W=0;W<G.length;W+=Y){let H=G.slice(W,W+Y).map((V)=>V());$.push(...await Promise.all(H))}return $}async function IX(J,X=[],Y=50){let Z=w(),G=[];for(let[W,H]of Object.entries(Z.shards)){if(!W||!H){console.error(`Shard ${W??"<null>"} not found, skipping`);continue}G.push(()=>H.prepare(J).bind(...X).all().catch((V)=>{return console.error(`Error executing query on shard ${W}:`,V),{success:!1,results:[],error:V instanceof Error?V.message:String(V),meta:{duration:0}}}))}let $=[];for(let W=0;W<G.length;W+=Y){let H=G.slice(W,W+Y).map((V)=>V());$.push(...await Promise.all(H))}return $}async function jX(J,X=[],Y=50){let Z=w(),G=[];for(let[W,H]of Object.entries(Z.shards)){if(!W||!H){console.error(`Shard ${W??"<null>"} not found, skipping`);continue}G.push(()=>H.prepare(J).bind(...X).first().catch((V)=>{return console.error(`Error executing query on shard ${W}:`,V),null}))}let $=[];for(let W=0;W<G.length;W+=Y){let H=G.slice(W,W+Y).map((V)=>V());$.push(...await Promise.all(H))}return $}async function QX(){let J=w();if(await f(J).clearAllMappings(),u.clear(),J.coordinator)try{let Y=J.coordinator.idFromName("default");await J.coordinator.get(Y).fetch("http://coordinator/flush",{method:"POST"})}catch(Y){console.warn("Failed to flush coordinator:",Y)}}async function PX(J){let Y=w().shards[J];if(!Y)throw new _(`Shard ${J} not found`,"SHARD_NOT_FOUND");return await CJ(Y)}q();class $J{state;constructor(J){this.state=J}async getState(){return await this.state.storage.get("coordinator_state")||{knownShards:[],shardStats:{},strategy:"round-robin",roundRobinIndex:0}}async saveState(J){await this.state.storage.put("coordinator_state",J)}async fetch(J){let Y=new URL(J.url).pathname,Z=J.method;try{switch(`${Z} ${Y}`){case"GET /shards":return this.handleListShards();case"POST /shards":return this.handleAddShard(J);case"DELETE /shards":return this.handleRemoveShard(J);case"GET /stats":return this.handleGetStats();case"POST /stats":return this.handleUpdateStats(J);case"POST /allocate":return this.handleAllocateShard(J);case"POST /flush":return this.handleFlush();case"GET /health":return new Response("OK",{status:200});default:return new Response("Not Found",{status:404})}}catch(G){return console.error("ShardCoordinator error:",G),new Response("Internal Server Error",{status:500})}}async handleListShards(){let J=await this.getState();return new Response(JSON.stringify(J.knownShards),{headers:{"Content-Type":"application/json"}})}async handleAddShard(J){let{shard:X}=await J.json();if(!X||typeof X!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Y=await this.getState();if(!Y.knownShards.includes(X))Y.knownShards.push(X),Y.shardStats[X]={binding:X,count:0,lastUpdated:Date.now()},await this.saveState(Y);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleRemoveShard(J){let{shard:X}=await J.json();if(!X||typeof X!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Y=await this.getState(),Z=Y.knownShards.indexOf(X);if(Z>-1){if(Y.knownShards.splice(Z,1),delete Y.shardStats[X],Y.roundRobinIndex>=Y.knownShards.length)Y.roundRobinIndex=0;await this.saveState(Y)}return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleGetStats(){let J=await this.getState(),X=Object.values(J.shardStats);return new Response(JSON.stringify(X),{headers:{"Content-Type":"application/json"}})}async handleUpdateStats(J){let{shard:X,count:Y}=await J.json();if(!X||typeof X!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});if(Y===void 0||typeof Y!=="number")return new Response(JSON.stringify({error:"Missing or invalid count parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Z=await this.getState();if(Z.shardStats[X])Z.shardStats[X].count=Y,Z.shardStats[X].lastUpdated=Date.now(),await this.saveState(Z);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleAllocateShard(J){let{primaryKey:X,strategy:Y,operationType:Z,availableShards:G}=await J.json();if(!X||typeof X!=="string")return new Response(JSON.stringify({error:"Missing or invalid primaryKey parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let $=await this.getState(),W=G||$.knownShards;if(W.length===0)return new Response(JSON.stringify({error:"No shards available"}),{status:400,headers:{"Content-Type":"application/json"}});let H=this.resolveStrategy($.strategy,Y,Z||"write"),V=this.selectShard(X,$,H,W);if(H==="round-robin")$.roundRobinIndex=($.roundRobinIndex+1)%W.length,await this.saveState($);return new Response(JSON.stringify({shard:V}),{headers:{"Content-Type":"application/json"}})}async handleFlush(){return await this.state.storage.deleteAll(),new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}resolveStrategy(J,X,Y="write"){if(X)return X;if(typeof J==="string")return J;return J[Y]}selectShard(J,X,Y,Z){let G=Z||X.knownShards;if(G.length===0)throw new _("No shards available","NO_SHARDS");switch(Y){case"round-robin":return G[X.roundRobinIndex]??G[0];case"random":return G[Math.floor(Math.random()*G.length)];case"hash":{let $=0;for(let H=0;H<J.length;H++){let V=J.charCodeAt(H);$=($<<5)-$+V,$=$&$}let W=Math.abs($)%G.length;return G[W]}case"location":{let $=X.targetRegion,W=X.shardLocations||{},H=G.filter((A)=>W[A]);if(!$||H.length===0){let A=0;for(let R=0;R<J.length;R++){let T=J.charCodeAt(R);A=(A<<5)-A+T,A=A&A}let I=Math.abs(A)%G.length;return G[I]}let V={wnam:{lat:37.7749,lon:-122.4194},enam:{lat:40.7357,lon:-74.1724},weur:{lat:51.5074,lon:-0.1278},eeur:{lat:52.2297,lon:21.0122},apac:{lat:35.6762,lon:139.6503},oc:{lat:-33.8688,lon:151.2093},me:{lat:25.2048,lon:55.2708},af:{lat:-26.2041,lon:28.0473}},U=(A,I)=>(I in A),O=(A)=>U(V,A)?A:"wnam",F=(A,I)=>{let R=V[O(A)],T=V[O(I)],P=R.lat-T.lat,Q=R.lon-T.lon;return Math.sqrt(P*P+Q*Q)},L=H.map((A)=>{let I=W[A],R=F($,I.region),T=I.priority||1;return{shard:A,score:R-T*0.1}});L.sort((A,I)=>A.score-I.score);let j=L[0].score,E=L.filter((A)=>Math.abs(A.score-j)<0.01);if(E.length===1)return E[0].shard;let z=0;for(let A=0;A<J.length;A++){let I=J.charCodeAt(A);z=(z<<5)-z+I,z=z&z}let M=Math.abs(z)%E.length;return E[M].shard}default:return G[0]}}async incrementShardCount(J){let X=await this.getState();if(X.shardStats[J])X.shardStats[J].count++,X.shardStats[J].lastUpdated=Date.now(),await this.saveState(X)}async decrementShardCount(J){let X=await this.getState();if(X.shardStats[J]&&X.shardStats[J].count>0)X.shardStats[J].count--,X.shardStats[J].lastUpdated=Date.now(),await this.saveState(X)}}if(typeof global<"u"){class J{data=new Map;async get(Z){return this.data.get(Z)}async put(Z,G){this.data.set(Z,G)}async delete(Z){return this.data.delete(Z)}async deleteAll(){this.data.clear()}async list(Z){if(!Z?.prefix)return new Map(this.data);let G=new Map;for(let[$,W]of this.data.entries())if($.startsWith(Z.prefix))G.set($,W);return G}}class X{storage;constructor(){this.storage=new J}}class Y{coordinator;mockState;constructor(){this.mockState=new X,this.coordinator=new $J(this.mockState)}async testShardAllocation(){await this.coordinator.fetch(new Request("http://test/shards",{method:"POST",body:JSON.stringify({shard:"db-east"})})),await this.coordinator.fetch(new Request("http://test/shards",{method:"POST",body:JSON.stringify({shard:"db-west"})}));let G=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"user-1",strategy:"round-robin"})}))).json(),W=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"user-2",strategy:"round-robin"})}))).json();console.assert(G.shard!==W.shard,"Round-robin should alternate shards");let V=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"consistent-key",strategy:"hash"})}))).json(),O=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"consistent-key",strategy:"hash"})}))).json();console.assert(V.shard===O.shard,"Hash allocation should be consistent"),console.log("✅ Shard allocation tests passed")}async testShardStats(){await this.coordinator.fetch(new Request("http://test/flush",{method:"POST"})),await this.coordinator.fetch(new Request("http://test/shards",{method:"POST",body:JSON.stringify({shard:"db-stats-test"})})),await this.coordinator.fetch(new Request("http://test/stats",{method:"POST",body:JSON.stringify({shard:"db-stats-test",count:42})}));let G=await(await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"}))).json();console.assert(G.length===1,"Should have one shard stat"),console.assert(G[0]?.binding==="db-stats-test","Should have correct binding name"),console.assert(G[0]?.count===42,"Should have correct count"),console.log("✅ Shard stats tests passed")}async testErrorHandling(){await this.coordinator.fetch(new Request("http://test/flush",{method:"POST"}));let Z=await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"test-key"})}));console.assert(Z.status===400,"Should return 400 for no shards available");let G=await this.coordinator.fetch(new Request("http://test/invalid",{method:"GET"}));console.assert(G.status===404,"Should return 404 for invalid endpoint"),console.log("✅ Error handling tests passed")}async testCountManagement(){await this.coordinator.fetch(new Request("http://test/shards",{method:"POST",body:JSON.stringify({shard:"db-count-test"})})),await this.coordinator.incrementShardCount("db-count-test"),await this.coordinator.incrementShardCount("db-count-test");let Z=await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"})),G=await Z.json(),$=G.find((H)=>H.binding==="db-count-test");console.assert($?.count===2,"Count should be 2 after two increments"),await this.coordinator.decrementShardCount("db-count-test"),Z=await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"})),G=await Z.json();let W=G.find((H)=>H.binding==="db-count-test");console.assert(W?.count===1,"Count should be 1 after decrement"),console.log("✅ Count management tests passed")}async runAllTests(){console.log("\uD83E\uDDEA Running ShardCoordinator tests...");try{return await this.testShardAllocation(),await this.testShardStats(),await this.testErrorHandling(),await this.testCountManagement(),console.log("\uD83C\uDF89 All ShardCoordinator tests passed!"),!0}catch(Z){return console.error("❌ ShardCoordinator tests failed:",Z),!1}}}globalThis.testShardCoordinator=()=>new Y}q();p();q();var EX=500;function SJ(J,X={}){let Y=X.scanCount??EX;return{async get(Z,G="text"){let $=await J.get(Z);if($===null)return null;if(G!=="json")return $;try{return JSON.parse($)}catch(W){throw new _(`Failed to parse JSON from Redis for key ${Z}: ${W instanceof Error?W.message:String(W)}`,"KV_JSON_PARSE_FAILED")}},async put(Z,G){await J.set(Z,G)},async delete(Z){await J.del(Z)},async list(Z){let G=Z?.prefix??"",$=`${G}*`,W=Z?.cursor??"0",H=Z?.limit,V=[];do{let U=await vX(J,W,$,Y);W=U.cursor;for(let O of U.keys){if(!G||O.startsWith(G))V.push(O);if(H&&V.length>=H)break}if(H&&V.length>=H)break}while(W!=="0");return{keys:V.map((U)=>({name:U})),cursor:W,list_complete:W==="0"}}}}function TX(J,X={}){return SJ(J,X)}function fJ(J,X){if(X)return a(J,X);return{prepare(Y){return new _J(J,Y)}}}function KJ(J,X){if(X)return a(J,X);return{prepare(Y){return new FJ(J,Y)}}}function RX(J,X){if(X)return a(J,X);return{prepare(Y){return new LJ(J,Y)}}}function a(J,X){return{prepare(Y){return new AJ(J,X,Y)}}}function zX(J){return{async get(X,Y="text"){let Z=await qX(J,X);if(Z===null||Z===void 0)return null;if(Y==="json"){if(typeof Z==="string")try{return JSON.parse(Z)}catch(G){throw new _(`Failed to parse JSON from NuxtHub KV for key ${X}: ${G instanceof Error?G.message:String(G)}`,"KV_JSON_PARSE_FAILED")}return Z}return typeof Z==="string"?Z:JSON.stringify(Z)},async put(X,Y){await kX(J,X,Y)},async delete(X){await SX(J,X)},async list(X){let Y=X?.prefix??"",Z=await fX(J,Y);return{keys:(typeof X?.limit==="number"?Z.slice(0,X.limit):Z).map(($)=>({name:$})),list_complete:!0}}}}function DX(J,X){return fJ({query:async(Z,G=[])=>{let $=X(J.connectionString);if(typeof $.connect==="function")await $.connect();try{return await $.query(Z,G)}finally{if(typeof $.release==="function")$.release();else if(typeof $.end==="function")await $.end()}}})}function wX(J,X){return KJ({execute:async(Z,G=[])=>{let $=X(J.connectionString);try{if(typeof $.execute==="function")return await $.execute(Z,G);if(typeof $.query==="function")return await $.query(Z,G);throw new _("Hyperdrive MySQL client is missing execute/query methods","MYSQL_CLIENT_INVALID")}finally{if(typeof $.end==="function")await $.end();else if(typeof $.close==="function")await $.close();else if(typeof $.destroy==="function")$.destroy()}}})}function BX(J){if(!J||typeof J!=="object")return!1;return typeof J.prepare==="function"}function xX(J){if(!J||typeof J!=="object")return!1;let X=J;return typeof X.get==="function"&&typeof X.put==="function"&&typeof X.delete==="function"&&typeof X.list==="function"}class _J{client;sql;bindings;constructor(J,X,Y=[]){this.client=J,this.sql=X,this.bindings=Y}bind(...J){return new _J(this.client,this.sql,J)}async run(){let J=Date.now(),X=OJ(this.sql),Y=await this.client.query(X,this.bindings);return{success:!0,results:Y.rows??[],meta:v(J,{changes:typeof Y.rowCount==="number"?Y.rowCount:void 0,command:Y.command})}}async all(){let J=Date.now(),X=OJ(this.sql),Y=await this.client.query(X,this.bindings);return{success:!0,results:Y.rows??[],meta:v(J,{changes:typeof Y.rowCount==="number"?Y.rowCount:void 0,command:Y.command})}}async first(){let J=OJ(this.sql);return(await this.client.query(J,this.bindings)).rows?.[0]??null}}class FJ{client;sql;bindings;constructor(J,X,Y=[]){this.client=J,this.sql=X,this.bindings=Y}bind(...J){return new FJ(this.client,this.sql,J)}async run(){let J=Date.now(),X=await WJ(this.client,this.sql,this.bindings);if(Array.isArray(X))return{success:!0,results:X,meta:v(J)};let Y=X;return{success:!0,results:[],meta:v(J,{changes:Y.affectedRows,last_row_id:Y.insertId,warningStatus:Y.warningStatus})}}async all(){let J=Date.now(),X=await WJ(this.client,this.sql,this.bindings);return{success:!0,results:Array.isArray(X)?X:[],meta:v(J,{changes:!Array.isArray(X)?X.affectedRows:void 0})}}async first(){let J=await WJ(this.client,this.sql,this.bindings);if(!Array.isArray(J)||J.length===0)return null;return J[0]}}class LJ{client;sql;bindings;constructor(J,X,Y=[]){this.client=J,this.sql=X,this.bindings=Y}bind(...J){return new LJ(this.client,this.sql,J)}async run(){let J=Date.now();if(typeof this.client.execute==="function"){let G=await this.client.execute(this.sql,this.bindings);return{success:!0,results:UJ(G),meta:v(J)}}let X=this.client.prepare?.(this.sql);if(!X||typeof X.run!=="function")throw new _("SQLite client must expose execute() or prepare().run()","SQLITE_CLIENT_INVALID");let Z=await X.run(...this.bindings)??{};return{success:!0,results:[],meta:v(J,{changes:t(Z.changes),last_row_id:Z.lastInsertRowid??Z.lastID})}}async all(){let J=Date.now();if(typeof this.client.execute==="function"){let Z=await this.client.execute(this.sql,this.bindings);return{success:!0,results:UJ(Z),meta:v(J)}}let X=this.client.prepare?.(this.sql);if(!X||typeof X.all!=="function")throw new _("SQLite client must expose execute() or prepare().all()","SQLITE_CLIENT_INVALID");let Y=await X.all(...this.bindings);return{success:!0,results:Array.isArray(Y)?Y:[],meta:v(J)}}async first(){if(typeof this.client.execute==="function"){let X=await this.client.execute(this.sql,this.bindings);return UJ(X)[0]??null}let J=this.client.prepare?.(this.sql);if(!J)throw new _("SQLite client must expose execute() or prepare().get()","SQLITE_CLIENT_INVALID");if(typeof J.get==="function"){let X=await J.get(...this.bindings);return X===void 0||X===null?null:X}if(typeof J.all==="function"){let X=await J.all(...this.bindings);if(!Array.isArray(X)||X.length===0)return null;let Y=X[0];return Y===void 0||Y===null?null:Y}throw new _("SQLite prepare() result must expose get() or all()","SQLITE_CLIENT_INVALID")}}class AJ{client;sqlTag;sqlText;bindings;constructor(J,X,Y,Z=[]){this.client=J,this.sqlTag=X,this.sqlText=Y,this.bindings=Z}bind(...J){return new AJ(this.client,this.sqlTag,this.sqlText,J)}async run(){let J=Date.now(),X=HJ(this.sqlTag,this.sqlText,this.bindings),Y=await MX(this.client,X);return{success:!0,results:VJ(Y),meta:v(J,kJ(Y))}}async all(){let J=Date.now(),X=HJ(this.sqlTag,this.sqlText,this.bindings),Y=await bJ(this.client,X);return{success:!0,results:VJ(Y),meta:v(J,kJ(Y))}}async first(){let J=HJ(this.sqlTag,this.sqlText,this.bindings),X=await NX(this.client,J),Y=VJ(X);if(Y.length>0)return Y[0]??null;if(X&&typeof X==="object"&&"row"in X){let Z=X.row;return Z===void 0||Z===null?null:Z}if(X&&typeof X==="object"&&!Array.isArray(X)&&!("rows"in X)&&!("results"in X)&&!("data"in X))return X;return null}}async function vX(J,X,Y,Z){try{let G=await J.scan(X,{MATCH:Y,COUNT:Z});return qJ(G)}catch{let G=await J.scan(X,"MATCH",Y,"COUNT",String(Z));return qJ(G)}}function qJ(J){if(Array.isArray(J))return{cursor:String(J[0]??"0"),keys:Array.isArray(J[1])?J[1]:[]};return{cursor:String(J.cursor??"0"),keys:Array.isArray(J.keys)?J.keys:[]}}async function WJ(J,X,Y){if(typeof J.execute==="function"){let Z=await J.execute(X,Y);if(Array.isArray(Z))return Z[0];return Z}if(typeof J.query==="function"){let Z=await J.query(X,Y);if(Array.isArray(Z))return Z[0];return Z}throw new _("MySQL client must expose execute() or query()","MYSQL_CLIENT_INVALID")}async function MX(J,X){if(typeof J.run==="function")return await J.run(X);if(typeof J.execute==="function")return await J.execute(X);if(typeof J.all==="function")return await J.all(X);throw new _("Drizzle client must expose run(), execute(), or all()","DRIZZLE_CLIENT_INVALID")}async function bJ(J,X){if(typeof J.all==="function")return await J.all(X);if(typeof J.execute==="function")return await J.execute(X);if(typeof J.run==="function")return await J.run(X);throw new _("Drizzle client must expose all(), execute(), or run()","DRIZZLE_CLIENT_INVALID")}async function NX(J,X){if(typeof J.get==="function")return await J.get(X);return await bJ(J,X)}function HJ(J,X,Y){let Z=CX(X),G=Z.length-1;if(G!==Y.length)throw new _(`Drizzle binding mismatch: expected ${G} bindings, received ${Y.length}`,"DRIZZLE_BINDINGS_MISMATCH");if(G===0)return J.raw(X);let $=typeof J.empty==="function"?J.empty():J.raw("");for(let W=0;W<Z.length;W++){let H=Z[W];if(H)$.append(J.raw(H));if(W<G)$.append(J`${Y[W]}`)}return $}function CX(J){let X=[],Y=0,Z=!1,G=!1,$=!1,W=!1;for(let H=0;H<J.length;H++){let V=J[H],U=H+1<J.length?J[H+1]:"";if($){if(V===`
17
- `)$=!1;continue}if(W){if(V==="*"&&U==="/")H++,W=!1;continue}if(!Z&&!G){if(V==="-"&&U==="-"){H++,$=!0;continue}if(V==="/"&&U==="*"){H++,W=!0;continue}}if(V==="'"&&!G){if(Z&&U==="'"){H++;continue}Z=!Z;continue}if(V==='"'&&!Z){if(G&&U==='"'){H++;continue}G=!G;continue}if(V==="?"&&!Z&&!G)X.push(J.slice(Y,H)),Y=H+1}return X.push(J.slice(Y)),X}function VJ(J){if(Array.isArray(J)){if(J.length===2&&Array.isArray(J[0]))return J[0];if(J.length===2&&J[0]&&typeof J[0]==="object"&&!Array.isArray(J[0])&&(Array.isArray(J[1])||J[1]===null||J[1]===void 0))return[];return J}if(J&&typeof J==="object"){let X=J;if(Array.isArray(X.rows))return X.rows;if(Array.isArray(X.results))return X.results;if(Array.isArray(X.data))return X.data}return[]}function kJ(J){if(!J)return{};let X;if(Array.isArray(J)&&J.length===2&&J[0]&&typeof J[0]==="object"&&!Array.isArray(J[0]))X=J[0];else if(typeof J==="object"&&!Array.isArray(J))X=J;if(!X)return{};let Y={},Z=t(X.rowCount)??t(X.changes)??t(X.affectedRows);if(Z!==void 0)Y.changes=Z;let G=X.lastInsertRowid??X.lastInsertId??X.insertId;if(typeof G==="number"||typeof G==="string")Y.last_row_id=G;if(X.meta&&typeof X.meta==="object")Object.assign(Y,X.meta);return Y}async function qX(J,X){if(typeof J.get==="function")return await J.get(X);if(typeof J.getItem==="function")return await J.getItem(X);throw new _("NuxtHub KV client must expose get() or getItem()","NUXTHUB_KV_CLIENT_INVALID")}async function kX(J,X,Y){if(typeof J.set==="function"){await J.set(X,Y);return}if(typeof J.setItem==="function"){await J.setItem(X,Y);return}throw new _("NuxtHub KV client must expose set() or setItem()","NUXTHUB_KV_CLIENT_INVALID")}async function SX(J,X){if(typeof J.del==="function"){await J.del(X);return}if(typeof J.removeItem==="function"){await J.removeItem(X);return}throw new _("NuxtHub KV client must expose del() or removeItem()","NUXTHUB_KV_CLIENT_INVALID")}async function fX(J,X){let Y;if(typeof J.keys==="function")Y=await J.keys(X);else if(typeof J.getKeys==="function")Y=await J.getKeys(X);else throw new _("NuxtHub KV client must expose keys() or getKeys()","NUXTHUB_KV_CLIENT_INVALID");if(!Array.isArray(Y))return[];if(!X)return[...Y];return Y.filter((Z)=>Z.startsWith(X))}function UJ(J){if(Array.isArray(J))return J;if(J&&typeof J==="object"){let X=J;if(Array.isArray(X.rows))return X.rows;if(Array.isArray(X.results))return X.results}return[]}function v(J,X={}){return{duration:Date.now()-J,...X}}function t(J){if(typeof J==="number"&&Number.isFinite(J))return J;return}var c=new Map;function OJ(J){let X=c.get(J);if(X)return X;let Y="",Z=0,G=!1,$=!1,W=!1,H=!1;for(let V=0;V<J.length;V++){let U=J[V],O=V+1<J.length?J[V+1]:"";if(W){if(Y+=U,U===`
18
- `)W=!1;continue}if(H){if(Y+=U,U==="*"&&O==="/")Y+="/",V++,H=!1;continue}if(!G&&!$){if(U==="-"&&O==="-"){Y+="--",V++,W=!0;continue}if(U==="/"&&O==="*"){Y+="/*",V++,H=!0;continue}}if(U==="'"&&!$){G=!G,Y+=U;continue}if(U==='"'&&!G){$=!$,Y+=U;continue}if(U==="?"&&!G&&!$){Z++,Y+=`$${Z}`;continue}Y+=U}if(c.set(J,Y),c.size>5000){let V=c.keys().next().value;if(V)c.delete(V)}return Y}m();export{n as validateTableForSharding,GJ as schemaExists,_X as runShard,AX as runAllShards,$X as run,nJ as resetConfig,VX as reassignShard,s as prepare,RJ as migrateRecord,b as listTables,UX as listKnownShards,BX as isSQLDatabase,xX as isKVStorage,DJ as integrateExistingDatabase,MJ as initializeAsync,oJ as initialize,OX as getShardStats,PX as getDatabaseSizeForShard,aJ as getClosestRegionFromIP,QX as flush,LX as firstShard,jX as firstAllShards,HX as first,TJ as dropSchema,l as discoverExistingRecordsWithColumns,o as discoverExistingPrimaryKeys,TX as createValkeyKVProvider,EJ as createSchemaAcrossShards,GX as createSchema,RX as createSQLiteProvider,SJ as createRedisKVProvider,fJ as createPostgreSQLProvider,zX as createNuxtHubKVProvider,KJ as createMySQLProvider,zJ as createMappingsForExistingKeys,DX as createHyperdrivePostgresProvider,wX as createHyperdriveMySQLProvider,a as createDrizzleSQLProvider,lJ as collegedb,vJ as clearShardMigrationCache,xJ as clearMigrationCache,BJ as checkMigrationNeeded,wJ as autoDetectAndMigrate,FX as allShard,IX as allAllShards,WX as all,$J as ShardCoordinator,k as KVShardMapper,_ as CollegeDBError};
16
+ `).run()}if(K.set(V,!0),w&&Y.debug)console.log(`Auto-migration completed for shard ${J}: ${I} records from ${P} tables`)}catch(A){L.push(`Auto-migration error: ${A}`)}return{migrationNeeded:x,migrationPerformed:w,recordsMigrated:I,tablesProcessed:P,issues:L}}async function SG(G,J,Y){let Z=`${J}_migration_check`;if(K.has(Z))return!1;try{let $=await h(G);if($.includes("shard_mappings"))return K.set(Z,!0),!1;let{KVShardMapper:W}=await Promise.resolve().then(() => (u(),XG)),H=new W(Y.kv,{hashShardMappings:Y.hashShardMappings,mappingCacheTtlMs:Y.mappingCacheTtlMs,knownShardsCacheTtlMs:Y.knownShardsCacheTtlMs}),O=$.filter((U)=>U!=="shard_mappings"&&!U.startsWith("sqlite_")&&U!=="sqlite_sequence");for(let U of O.slice(0,3))try{if(((await G.prepare(`SELECT COUNT(*) as count FROM ${U} LIMIT 1`).first())?.count||0)>0){let L=await G.prepare(`SELECT id FROM ${U} LIMIT 1`).first();if(L){let I=String(L.id);if(!await H.getShardMapping(I))return!0}}}catch{continue}return!1}catch{return!1}}function KG(){K.clear()}function fG(G){let J=`${G}_migration_check`;K.delete(J)}var K,WG;var g=$G(()=>{q();K=new Map,WG=new Map});q();u();var c=null,p=null,y=new Map;function C(G){if(!p)p=new S(G.kv,{hashShardMappings:G.hashShardMappings,mappingCacheTtlMs:G.mappingCacheTtlMs,knownShardsCacheTtlMs:G.knownShardsCacheTtlMs});return p}function _J(G){c=G,p=new S(G.kv,{hashShardMappings:G.hashShardMappings,mappingCacheTtlMs:G.mappingCacheTtlMs,knownShardsCacheTtlMs:G.knownShardsCacheTtlMs}),y.clear();try{let J=C(G);Promise.resolve().then(async()=>{let Y=await J.getKnownShards(),Z=Array.from(new Set([...Y,...Object.keys(G.shards)]));await J.setKnownShards(Z)}).catch(()=>{return})}catch{}if(G.shards&&Object.keys(G.shards).length>0&&!G.disableAutoMigration)yG(G).catch((J)=>{console.warn("Background auto-migration failed:",J)})}async function pG(G){c=G,p=new S(G.kv,{hashShardMappings:G.hashShardMappings,mappingCacheTtlMs:G.mappingCacheTtlMs,knownShardsCacheTtlMs:G.knownShardsCacheTtlMs}),y.clear();try{let J=C(G),Y=await J.getKnownShards(),Z=Array.from(new Set([...Y,...Object.keys(G.shards)]));await J.setKnownShards(Z)}catch{}if(G.shards&&Object.keys(G.shards).length>0&&!G.disableAutoMigration)try{await yG(G)}catch(J){console.warn("Auto migration failed:",J)}}async function VJ(G,J){return await pG(G),await J()}async function yG(G){try{let{autoDetectAndMigrate:J}=await Promise.resolve().then(() => (g(),t)),Y=Object.keys(G.shards);if(G.debug)console.log(`\uD83D\uDD0D Checking ${Y.length} shards for existing data...`);let Z=Y.map(async(W)=>{let H=G.shards[W];if(!H)return null;try{let O=await J(H,W,G,{maxRecordsToCheck:1000});return{shardName:W,...O}}catch(O){return console.warn(`Auto-migration failed for shard ${W}:`,O),null}}),X=(await Promise.all(Z)).filter((W)=>W?.migrationPerformed);if(G.debug)if(X.length>0){let W=X.reduce((H,O)=>H+(O?.recordsMigrated||0),0);console.log(`\uD83C\uDF89 Auto-migration completed! Migrated ${W} records across ${X.length} shards`),X.forEach((H)=>{if(H)console.log(` ✅ ${H.shardName}: ${H.recordsMigrated} records from ${H.tablesProcessed} tables`)})}else console.log("✅ All shards ready - no migration needed")}catch(J){console.warn("Background auto-migration setup failed:",J)}}function FJ(){c=null,p=null,y.clear()}function T(){if(!c)throw new F("CollegeDB not initialized. Call initialize() first.","NOT_INITIALIZED");return c}function LJ(G){let J=G.trim().toUpperCase();if(J.startsWith("SELECT")||J.startsWith("VALUES")||J.startsWith("TABLE")||J.startsWith("PRAGMA")||J.startsWith("EXPLAIN")||J.startsWith("WITH")||J.startsWith("SHOW"))return"read";return"write"}function AJ(G,J){let Y=G.strategy||"hash";if(typeof Y==="string")return Y;let Z=Y;return Z[J]||Z.write||Z.read||"hash"}function jJ(G,J){if(G===J)return 0;let Y={wnam:{lat:37.7749,lon:-122.4194},enam:{lat:40.7128,lon:-74.006},weur:{lat:51.5074,lon:-0.1278},eeur:{lat:52.52,lon:13.405},apac:{lat:35.6762,lon:139.6503},oc:{lat:-33.8688,lon:151.2093},me:{lat:25.2048,lon:55.2708},af:{lat:-26.2041,lon:28.0473}},Z=Y[G],$=Y[J],X=Z.lat-$.lat,W=Z.lon-$.lon;return Math.sqrt(X*X+W*W)}function IJ(G){let J=G.cf;if(!J||!J.country)return"wnam";let{country:Y,continent:Z}=J;if(["US","CA","MX"].includes(Y)){let $=J.region||J.regionCode||"",X=J.timezone||"";if($.includes("CA")||$.includes("WA")||$.includes("OR")||$.includes("NV")||$.includes("AZ")||$.includes("UT")||X.includes("Pacific")||X.includes("America/Los_Angeles"))return"wnam";return"enam"}if(["GL","PM","BM"].includes(Y))return"enam";if(["GB","IE","FR","ES","PT","NL","BE","LU","CH","AT","IT"].includes(Y))return"weur";if(["DE","PL","CZ","SK","HU","SI","HR","BA","RS","ME","MK","AL","BG","RO","MD","UA","BY","LT","LV","EE","FI","SE","NO","DK","IS"].includes(Y))return"eeur";if(Y==="RU")return"eeur";if(["JP","KR","CN","HK","TW","MO","MN","KP"].includes(Y))return"apac";if(["TH","VN","SG","MY","ID","PH","BN","KH","LA","MM","TL","IN","PK","BD","LK","NP","BT","MV","AF"].includes(Y))return"apac";if(["AU","NZ","PG","FJ","NC","VU","SB","WS","TO","KI","NR","PW","FM","MH","TV"].includes(Y))return"oc";if(["AE","SA","QA","KW","BH","OM","YE","IQ","IR","SY","LB","JO","IL","PS","TR","CY"].includes(Y))return"me";if(Z==="AF"||["EG","LY","TN","DZ","MA","SD","SS","ET","ER","DJ","SO"].includes(Y))return"af";if(["KZ","UZ","TM","TJ","KG"].includes(Y))return"eeur";if(Z==="SA"||["BR","AR","CL","PE","CO","VE","EC","BO","PY","UY","GY","SR","GF"].includes(Y))return"enam";if(["GT","BZ","SV","HN","NI","CR","PA","CU","JM","HT","DO","PR","TT","BB","GD","VC","LC","DM","AG","KN"].includes(Y))return"enam";return"wnam"}function PJ(G){if(typeof G==="string")return G;return G.region||"wnam"}async function a(G){try{let[J,Y]=await Promise.all([G.prepare("PRAGMA page_count").first(),G.prepare("PRAGMA page_size").first()]);if(!J?.page_count||!Y?.page_size)throw new F("Failed to retrieve database size information","SIZE_QUERY_FAILED");return J.page_count*Y.page_size}catch(J){throw new F(`Failed to get database size: ${J instanceof Error?J.message:"Unknown error"}`,"SIZE_QUERY_FAILED")}}async function QJ(G,J){let Y=Math.max(0,J.sizeCacheTtlMs??30000),Z=y.get(G);if(Z&&Z.expiresAt>=Date.now())return Z.size;let $=J.shards[G];if(!$)throw new F(`Shard ${G} not found in configuration`,"SHARD_NOT_FOUND");let X=await a($);if(Y>0)y.set(G,{size:X,expiresAt:Date.now()+Y});return X}async function EJ(G,J){if(typeof J.maxDatabaseSize!=="number"||!Number.isFinite(J.maxDatabaseSize)||J.maxDatabaseSize<=0)return G;let Y=J.maxDatabaseSize,$=(await Promise.allSettled(G.map(async(X)=>{let W=await QJ(X,J);return{shard:X,size:W,withinLimit:W<Y}}))).filter((X)=>X.status==="fulfilled"&&X.value.withinLimit).map((X)=>X.value.shard);if($.length===0){if(J.debug)console.warn("All shards exceed maxDatabaseSize limit. Allowing allocation to prevent failure.");return G}if(J.debug&&$.length<G.length){let X=G.filter((W)=>!$.includes(W));console.log(`Excluded ${X.length} shards due to size limits: ${X.join(", ")}`)}return $}function TJ(G,J,Y,Z){let $=J.filter((_)=>Y[_]);if($.length===0){let _=0;for(let L=0;L<Z.length;L++){let I=Z.charCodeAt(L);_=(_<<5)-_+I,_=_&_}let V=Math.abs(_)%J.length;return J[V]}let X=$.map((_)=>{let V=Y[_],L=jJ(G,PJ(V)),I=typeof V==="object"?V.priority||1:1,P=L-I*0.1;return{shard:_,score:P,distance:L,priority:I}});X.sort((_,V)=>_.score-V.score);let W=X[0].score,H=X.filter((_)=>Math.abs(_.score-W)<0.01);if(H.length===1)return H[0].shard;let O=0;for(let _=0;_<Z.length;_++){let V=Z.charCodeAt(_);O=(O<<5)-O+V,O=O&O}let U=Math.abs(O)%H.length;return H[U].shard}function m(G,J,Y,Z){switch(G){case"hash":{let $=0;for(let W=0;W<J.length;W++){let H=J.charCodeAt(W);$=($<<5)-$+H,$=$&$}let X=Math.abs($)%Y.length;return Y[X]||Y[0]}case"location":{if(!Z.targetRegion)return m("hash",J,Y,Z);return TJ(Z.targetRegion,Y,Z.shardLocations||{},J)}case"random":return Y[Math.floor(Math.random()*Y.length)]||Y[0];default:return m("hash",J,Y,Z)}}async function uG(G,J="write"){let Y=T(),Z=C(Y),$=await Z.getShardMapping(G);if($)return $.shard;let X=Object.keys(Y.shards);if(X.length===0)throw new F("No shards configured","NO_SHARDS");let W=await EJ(X,Y),H,O=AJ(Y,J);if(Y.coordinator)try{let U=Y.coordinator.idFromName("default"),V=await Y.coordinator.get(U).fetch("http://coordinator/allocate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({primaryKey:G,strategy:O,operationType:J,targetRegion:Y.targetRegion,shardLocations:Y.shardLocations,availableShards:W})});if(V.ok)H=(await V.json()).shard;else H=m(O,G,W,Y)}catch(U){console.warn("Coordinator allocation failed, falling back to local strategy:",U),H=m(O,G,W,Y)}else H=m(O,G,W,Y);return await Z.setShardMapping(G,H),H}async function DJ(G,J="write"){let Y=T(),Z=await uG(G,J),$=Y.shards[Z];if(!$)throw new F(`Shard ${Z} not found in configuration`,"SHARD_NOT_FOUND");return $}async function RJ(G,J){let{createSchema:Y}=await Promise.resolve().then(() => (g(),t));await Y(G,J)}async function r(G,J){let Y=LJ(J);return(await DJ(G,Y)).prepare(J)}async function gG(G,J,Y=[]){let $=await(await r(G,J)).bind(...Y).run();if(!$.success)throw new F(`Query failed: ${$.error||"Unknown error"}`,"QUERY_FAILED");return $}async function mG(G,J,Y=[]){let $=await(await r(G,J)).bind(...Y).all();if(!$.success)throw new F(`Query failed: ${$.error||"Unknown error"}`,"QUERY_FAILED");return $}async function cG(G,J,Y=[]){return await(await r(G,J)).bind(...Y).first()}async function xJ(G,J,Y=[],Z=50){let $=T(),W=await C($).getShardMapping(G);if(W){if($.shards[W.shard]){let U=await UG(W.shard,J,Y);if(U.success&&U.results.length>0)return U}}let H=await e(J,Y,Z);return oG(H)}async function vJ(G,J,Y=[],Z=50){let $=T(),W=await C($).getShardMapping(G);if(W){if($.shards[W.shard]){let U=await _G(W.shard,J,Y);if(U!==null)return U}}return(await iG(J,Y,Z)).find((O)=>O!==null)??null}async function zJ(G,J,Y){let Z=T();if(!Z.shards[J])throw new F(`Shard ${J} not found in configuration`,"SHARD_NOT_FOUND");let $=C(Z),X=await $.getShardMapping(G);if(!X)throw new F(`No existing mapping found for primary key: ${G}`,"MAPPING_NOT_FOUND");if(X.shard!==J){let{migrateRecord:W}=await Promise.resolve().then(() => (g(),t)),H=Z.shards[X.shard],O=Z.shards[J];if(!H||!O)throw new F("Source or target shard not available","SHARD_UNAVAILABLE");await W(H,O,G,Y)}await $.updateShardMapping(G,J)}async function MJ(){let G=T();if(G.coordinator)try{let J=G.coordinator.idFromName("default"),Z=await G.coordinator.get(J).fetch("http://coordinator/shards");if(Z.ok)return await Z.json()}catch(J){console.warn("Failed to get shards from coordinator:",J)}try{let Y=await C(G).getKnownShards(),Z=new Set([...Object.keys(G.shards),...Y]);return Array.from(Z)}catch{return Object.keys(G.shards)}}async function BJ(){let G=T();if(G.coordinator)try{let $=G.coordinator.idFromName("default"),W=await G.coordinator.get($).fetch("http://coordinator/stats");if(W.ok)return await W.json()}catch($){console.warn("Failed to get stats from coordinator:",$)}let J=C(G),Y=await J.getShardKeyCounts(),Z=Object.keys(G.shards);try{let $=await J.getKnownShards();Z=Array.from(new Set([...Z,...$]))}catch{}return Z.map(($)=>({binding:$,count:Y[$]||0}))}async function dG(G,J,Y=[]){let $=T().shards[G];if(!$)throw new F(`Shard ${G} not found`,"SHARD_NOT_FOUND");let X=await $.prepare(J).bind(...Y).run();if(!X.success)throw new F(`Query failed: ${X.error||"Unknown error"}`,"QUERY_FAILED");return X}async function UG(G,J,Y=[]){let $=T().shards[G];if(!$)throw new F(`Shard ${G} not found`,"SHARD_NOT_FOUND");return await $.prepare(J).bind(...Y).all()}async function _G(G,J,Y=[]){let $=T().shards[G];if(!$)throw new F(`Shard ${G} not found`,"SHARD_NOT_FOUND");return await $.prepare(J).bind(...Y).first()}async function nG(G,J=[],Y=50){let Z=T(),$=[];for(let[W,H]of Object.entries(Z.shards)){if(!W||!H){console.error(`Shard ${W??"<null>"} not found, skipping`);continue}$.push(()=>H.prepare(G).bind(...J).run().catch((O)=>{return console.error(`Error executing query on shard ${W}:`,O),{success:!1,results:[],error:O instanceof Error?O.message:String(O),meta:{duration:0}}}))}let X=[];for(let W=0;W<$.length;W+=Y){let H=$.slice(W,W+Y).map((O)=>O());X.push(...await Promise.all(H))}return X}async function e(G,J=[],Y=50){let Z=T(),$=[];for(let[W,H]of Object.entries(Z.shards)){if(!W||!H){console.error(`Shard ${W??"<null>"} not found, skipping`);continue}$.push(()=>H.prepare(G).bind(...J).all().catch((O)=>{return console.error(`Error executing query on shard ${W}:`,O),{success:!1,results:[],error:O instanceof Error?O.message:String(O),meta:{duration:0}}}))}let X=[];for(let W=0;W<$.length;W+=Y){let H=$.slice(W,W+Y).map((O)=>O());X.push(...await Promise.all(H))}return X}function d(G,J=50){if(!Number.isFinite(G??J))return J;return Math.max(1,Math.floor(G??J))}function wJ(G){if(!Number.isFinite(G??0))return 0;return Math.max(0,Math.floor(G??0))}function NJ(G){if(G===void 0)return;if(!Number.isFinite(G))return;return Math.max(0,Math.floor(G))}function bG(G,J){if(typeof J==="function")return J(G);if(!J||typeof G!=="object"||G===null)return;return G[String(J)]}function CJ(G,J){if(G===J)return 0;if(G===null||G===void 0)return 1;if(J===null||J===void 0)return-1;if(typeof G==="number"&&typeof J==="number")return G-J;if(typeof G==="bigint"&&typeof J==="bigint")return G<J?-1:1;if(G instanceof Date&&J instanceof Date)return G.getTime()-J.getTime();if(typeof G==="boolean"&&typeof J==="boolean")return Number(G)-Number(J);return String(G).localeCompare(String(J),void 0,{numeric:!0,sensitivity:"base"})}function oG(G){let J=G.flatMap((X)=>X.results||[]),Y=G.filter((X)=>!X.success),Z=G.reduce((X,W)=>X+(W.meta?.duration||0),0);if(Y.length===0)return{success:!0,results:J,meta:{duration:Z}};let $=Y.map((X)=>X.error||"Unknown shard query error").filter(Boolean).join("; ");return{success:!1,results:J,error:$||"One or more shard queries failed",meta:{duration:Z}}}async function lG(G,J=[],Y={}){let Z=d(Y.batchSize),$=wJ(Y.offset),X=NJ(Y.limit),W=oG(await e(G,J,Z)),H=W.results;if(Y.filter)H=H.filter((_)=>Y.filter?.(_));if(Y.comparator)H=[...H].sort(Y.comparator);else if(Y.sortBy){let _=Y.sortDirection==="desc"?-1:1;H=[...H].sort((V,L)=>{let I=bG(V,Y.sortBy),P=bG(L,Y.sortBy);return CJ(I,P)*_})}let O=X===void 0?void 0:$+X,U=H.slice($,O);return{...W,results:U}}async function iG(G,J=[],Y=50){let Z=T(),$=[];for(let[W,H]of Object.entries(Z.shards)){if(!W||!H){console.error(`Shard ${W??"<null>"} not found, skipping`);continue}$.push(()=>H.prepare(G).bind(...J).first().catch((O)=>{return console.error(`Error executing query on shard ${W}:`,O),null}))}let X=[];for(let W=0;W<$.length;W+=Y){let H=$.slice(W,W+Y).map((O)=>O());X.push(...await Promise.all(H))}return X}async function kJ(G,J=[],Y={}){return(await lG(G,J,{...Y,limit:1})).results[0]??null}async function qJ(){let G=T();if(await C(G).clearAllMappings(),y.clear(),G.coordinator)try{let Y=G.coordinator.idFromName("default");await G.coordinator.get(Y).fetch("http://coordinator/flush",{method:"POST"})}catch(Y){console.warn("Failed to flush coordinator:",Y)}}async function SJ(G){let Y=T().shards[G];if(!Y)throw new F(`Shard ${G} not found`,"SHARD_NOT_FOUND");return await a(Y)}var KJ=/^[A-Za-z_][A-Za-z0-9_]*$/;function f(G){let J=G.trim();if(!J)throw new F("Identifier cannot be empty","INVALID_IDENTIFIER");let Y=J.split(".").map((Z)=>Z.trim());if(Y.some((Z)=>!Z||!KJ.test(Z)))throw new F(`Invalid SQL identifier: ${G}`,"INVALID_IDENTIFIER");return Y.map((Z)=>`"${Z}"`).join(".")}function hG(G){return G.toLowerCase().replace(/[^a-z0-9_]+/g,"_").replace(/_+/g,"_").replace(/^_+|_+$/g,"")}function fJ(G){if(typeof G==="string")return[{name:G}];if(!Array.isArray(G)||G.length===0)throw new F("At least one index column is required","INVALID_INDEX_COLUMNS");return G.map((J)=>{if(typeof J==="string")return{name:J};if(!J?.name)throw new F("Index column name is required","INVALID_INDEX_COLUMNS");return{name:J.name,order:J.order,collate:J.collate}})}function VG(G,J,Y={}){let Z=fJ(J),$=f(G),X=Y.indexName?Y.indexName:["idx",hG(G),...Z.map((V)=>hG(V.name))].filter(Boolean).join("_").slice(0,120),W=f(X||"idx_auto"),H=Z.map((V)=>{let L=f(V.name),I=V.order?` ${V.order}`:"",P=V.collate?` COLLATE ${f(V.collate).replace(/"/g,"")}`:"";return`${L}${P}${I}`}).join(", "),O=Y.ifNotExists===!1?"":" IF NOT EXISTS",U=Y.unique?"UNIQUE ":"",_=Y.where?.trim()?` WHERE ${Y.where.trim()}`:"";return`CREATE ${U}INDEX${O} ${W} ON ${$} (${H})${_}`}async function bJ(G,J,Y,Z={}){let $=VG(J,Y,Z);return gG(G,$)}async function hJ(G,J,Y,Z={}){let $=VG(J,Y,Z);return dG(G,$)}async function pJ(G,J,Y={}){let Z=VG(G,J,Y);return nG(Z,[],d(Y.batchSize))}function FG(G,J="query-plan"){switch(J){case"raw":return`EXPLAIN ${G}`;case"analyze":return`EXPLAIN ANALYZE ${G}`;case"query-plan":default:return`EXPLAIN QUERY PLAN ${G}`}}async function yJ(G,J,Y=[],Z={}){return mG(G,FG(J,Z.mode),Y)}async function uJ(G,J,Y=[],Z={}){return UG(G,FG(J,Z.mode),Y)}async function gJ(G,J=[],Y={}){return e(FG(G,Y.mode),J,d(Y.batchSize))}async function mJ(G,J){let Y=f(J),Z=await cG(G,`SELECT COUNT(*) AS row_count FROM ${Y}`);if(!Z||Z.row_count===void 0||Z.row_count===null)return 0;return Number(Z.row_count)||0}async function cJ(G,J){let Y=f(J),Z=await _G(G,`SELECT COUNT(*) AS row_count FROM ${Y}`);if(!Z||Z.row_count===void 0||Z.row_count===null)return 0;return Number(Z.row_count)||0}async function dJ(G,J=50){let Y=T(),Z=d(J),X=`SELECT COUNT(*) AS row_count FROM ${f(G)}`,W=[];for(let[U,_]of Object.entries(Y.shards)){if(!U||!_)continue;W.push(async()=>{try{let V=await _.prepare(X).first(),L=Number(V?.row_count??0);return{shard:U,count:Number.isFinite(L)?L:0,success:!0}}catch(V){return{shard:U,count:null,success:!1,error:V instanceof Error?V.message:String(V)}}})}let H=[];for(let U=0;U<W.length;U+=Z){let _=W.slice(U,U+Z).map((V)=>V());H.push(...await Promise.all(_))}return{total:H.reduce((U,_)=>U+(_.count??0),0),shards:H}}async function nJ(G){let J=T(),Y=await uG(G,"read"),Z=J.shards[Y];if(!Z)throw new F(`Shard ${Y} not found in configuration`,"SHARD_NOT_FOUND");return a(Z)}async function sG(G=50){let J=T(),Y=d(G),Z=[];for(let[X,W]of Object.entries(J.shards)){if(!X||!W)continue;Z.push(async()=>{try{return{shard:X,size:await a(W),success:!0}}catch(H){return{shard:X,size:null,success:!1,error:H instanceof Error?H.message:String(H)}}})}let $=[];for(let X=0;X<Z.length;X+=Y){let W=Z.slice(X,X+Y).map((H)=>H());$.push(...await Promise.all(W))}return $}async function oJ(G=50){return(await sG(G)).reduce((Y,Z)=>Y+(Z.size??0),0)}q();class LG{state;constructor(G){this.state=G}async getState(){return await this.state.storage.get("coordinator_state")||{knownShards:[],shardStats:{},strategy:"round-robin",roundRobinIndex:0}}async saveState(G){await this.state.storage.put("coordinator_state",G)}async fetch(G){let Y=new URL(G.url).pathname,Z=G.method;try{switch(`${Z} ${Y}`){case"GET /shards":return this.handleListShards();case"POST /shards":return this.handleAddShard(G);case"DELETE /shards":return this.handleRemoveShard(G);case"GET /stats":return this.handleGetStats();case"POST /stats":return this.handleUpdateStats(G);case"POST /allocate":return this.handleAllocateShard(G);case"POST /flush":return this.handleFlush();case"GET /health":return new Response("OK",{status:200});default:return new Response("Not Found",{status:404})}}catch($){return console.error("ShardCoordinator error:",$),new Response("Internal Server Error",{status:500})}}async handleListShards(){let G=await this.getState();return new Response(JSON.stringify(G.knownShards),{headers:{"Content-Type":"application/json"}})}async handleAddShard(G){let{shard:J}=await G.json();if(!J||typeof J!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Y=await this.getState();if(!Y.knownShards.includes(J))Y.knownShards.push(J),Y.shardStats[J]={binding:J,count:0,lastUpdated:Date.now()},await this.saveState(Y);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleRemoveShard(G){let{shard:J}=await G.json();if(!J||typeof J!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Y=await this.getState(),Z=Y.knownShards.indexOf(J);if(Z>-1){if(Y.knownShards.splice(Z,1),delete Y.shardStats[J],Y.roundRobinIndex>=Y.knownShards.length)Y.roundRobinIndex=0;await this.saveState(Y)}return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleGetStats(){let G=await this.getState(),J=Object.values(G.shardStats);return new Response(JSON.stringify(J),{headers:{"Content-Type":"application/json"}})}async handleUpdateStats(G){let{shard:J,count:Y}=await G.json();if(!J||typeof J!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});if(Y===void 0||typeof Y!=="number")return new Response(JSON.stringify({error:"Missing or invalid count parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Z=await this.getState();if(Z.shardStats[J])Z.shardStats[J].count=Y,Z.shardStats[J].lastUpdated=Date.now(),await this.saveState(Z);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleAllocateShard(G){let{primaryKey:J,strategy:Y,operationType:Z,availableShards:$}=await G.json();if(!J||typeof J!=="string")return new Response(JSON.stringify({error:"Missing or invalid primaryKey parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let X=await this.getState(),W=$||X.knownShards;if(W.length===0)return new Response(JSON.stringify({error:"No shards available"}),{status:400,headers:{"Content-Type":"application/json"}});let H=this.resolveStrategy(X.strategy,Y,Z||"write"),O=this.selectShard(J,X,H,W);if(H==="round-robin")X.roundRobinIndex=(X.roundRobinIndex+1)%W.length,await this.saveState(X);return new Response(JSON.stringify({shard:O}),{headers:{"Content-Type":"application/json"}})}async handleFlush(){return await this.state.storage.deleteAll(),new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}resolveStrategy(G,J,Y="write"){if(J)return J;if(typeof G==="string")return G;return G[Y]}selectShard(G,J,Y,Z){let $=Z||J.knownShards;if($.length===0)throw new F("No shards available","NO_SHARDS");switch(Y){case"round-robin":return $[J.roundRobinIndex]??$[0];case"random":return $[Math.floor(Math.random()*$.length)];case"hash":{let X=0;for(let H=0;H<G.length;H++){let O=G.charCodeAt(H);X=(X<<5)-X+O,X=X&X}let W=Math.abs(X)%$.length;return $[W]}case"location":{let X=J.targetRegion,W=J.shardLocations||{},H=$.filter((A)=>W[A]);if(!X||H.length===0){let A=0;for(let R=0;R<G.length;R++){let D=G.charCodeAt(R);A=(A<<5)-A+D,A=A&A}let j=Math.abs(A)%$.length;return $[j]}let O={wnam:{lat:37.7749,lon:-122.4194},enam:{lat:40.7357,lon:-74.1724},weur:{lat:51.5074,lon:-0.1278},eeur:{lat:52.2297,lon:21.0122},apac:{lat:35.6762,lon:139.6503},oc:{lat:-33.8688,lon:151.2093},me:{lat:25.2048,lon:55.2708},af:{lat:-26.2041,lon:28.0473}},U=(A,j)=>(j in A),_=(A)=>U(O,A)?A:"wnam",V=(A,j)=>{let R=O[_(A)],D=O[_(j)],E=R.lat-D.lat,Q=R.lon-D.lon;return Math.sqrt(E*E+Q*Q)},L=H.map((A)=>{let j=W[A],R=V(X,j.region),D=j.priority||1;return{shard:A,score:R-D*0.1}});L.sort((A,j)=>A.score-j.score);let I=L[0].score,P=L.filter((A)=>Math.abs(A.score-I)<0.01);if(P.length===1)return P[0].shard;let x=0;for(let A=0;A<G.length;A++){let j=G.charCodeAt(A);x=(x<<5)-x+j,x=x&x}let w=Math.abs(x)%P.length;return P[w].shard}default:return $[0]}}async incrementShardCount(G){let J=await this.getState();if(J.shardStats[G])J.shardStats[G].count++,J.shardStats[G].lastUpdated=Date.now(),await this.saveState(J)}async decrementShardCount(G){let J=await this.getState();if(J.shardStats[G]&&J.shardStats[G].count>0)J.shardStats[G].count--,J.shardStats[G].lastUpdated=Date.now(),await this.saveState(J)}}if(typeof global<"u"){class G{data=new Map;async get(Z){return this.data.get(Z)}async put(Z,$){this.data.set(Z,$)}async delete(Z){return this.data.delete(Z)}async deleteAll(){this.data.clear()}async list(Z){if(!Z?.prefix)return new Map(this.data);let $=new Map;for(let[X,W]of this.data.entries())if(X.startsWith(Z.prefix))$.set(X,W);return $}}class J{storage;constructor(){this.storage=new G}}class Y{coordinator;mockState;constructor(){this.mockState=new J,this.coordinator=new LG(this.mockState)}async testShardAllocation(){await this.coordinator.fetch(new Request("http://test/shards",{method:"POST",body:JSON.stringify({shard:"db-east"})})),await this.coordinator.fetch(new Request("http://test/shards",{method:"POST",body:JSON.stringify({shard:"db-west"})}));let $=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"user-1",strategy:"round-robin"})}))).json(),W=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"user-2",strategy:"round-robin"})}))).json();console.assert($.shard!==W.shard,"Round-robin should alternate shards");let O=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"consistent-key",strategy:"hash"})}))).json(),_=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"consistent-key",strategy:"hash"})}))).json();console.assert(O.shard===_.shard,"Hash allocation should be consistent"),console.log("✅ Shard allocation tests passed")}async testShardStats(){await this.coordinator.fetch(new Request("http://test/flush",{method:"POST"})),await this.coordinator.fetch(new Request("http://test/shards",{method:"POST",body:JSON.stringify({shard:"db-stats-test"})})),await this.coordinator.fetch(new Request("http://test/stats",{method:"POST",body:JSON.stringify({shard:"db-stats-test",count:42})}));let $=await(await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"}))).json();console.assert($.length===1,"Should have one shard stat"),console.assert($[0]?.binding==="db-stats-test","Should have correct binding name"),console.assert($[0]?.count===42,"Should have correct count"),console.log("✅ Shard stats tests passed")}async testErrorHandling(){await this.coordinator.fetch(new Request("http://test/flush",{method:"POST"}));let Z=await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"test-key"})}));console.assert(Z.status===400,"Should return 400 for no shards available");let $=await this.coordinator.fetch(new Request("http://test/invalid",{method:"GET"}));console.assert($.status===404,"Should return 404 for invalid endpoint"),console.log("✅ Error handling tests passed")}async testCountManagement(){await this.coordinator.fetch(new Request("http://test/shards",{method:"POST",body:JSON.stringify({shard:"db-count-test"})})),await this.coordinator.incrementShardCount("db-count-test"),await this.coordinator.incrementShardCount("db-count-test");let Z=await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"})),$=await Z.json(),X=$.find((H)=>H.binding==="db-count-test");console.assert(X?.count===2,"Count should be 2 after two increments"),await this.coordinator.decrementShardCount("db-count-test"),Z=await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"})),$=await Z.json();let W=$.find((H)=>H.binding==="db-count-test");console.assert(W?.count===1,"Count should be 1 after decrement"),console.log("✅ Count management tests passed")}async runAllTests(){console.log("\uD83E\uDDEA Running ShardCoordinator tests...");try{return await this.testShardAllocation(),await this.testShardStats(),await this.testErrorHandling(),await this.testCountManagement(),console.log("\uD83C\uDF89 All ShardCoordinator tests passed!"),!0}catch(Z){return console.error("❌ ShardCoordinator tests failed:",Z),!1}}}globalThis.testShardCoordinator=()=>new Y}q();u();q();var lJ=500;function rG(G,J={}){let Y=J.scanCount??lJ;return{async get(Z,$="text"){let X=await G.get(Z);if(X===null)return null;if($!=="json")return X;try{return JSON.parse(X)}catch(W){throw new F(`Failed to parse JSON from Redis for key ${Z}: ${W instanceof Error?W.message:String(W)}`,"KV_JSON_PARSE_FAILED")}},async put(Z,$){await G.set(Z,$)},async delete(Z){await G.del(Z)},async list(Z){let $=Z?.prefix??"",X=`${$}*`,W=Z?.cursor??"0",H=Z?.limit,O=[];do{let U=await JY(G,W,X,Y);W=U.cursor;for(let _ of U.keys){if(!$||_.startsWith($))O.push(_);if(H&&O.length>=H)break}if(H&&O.length>=H)break}while(W!=="0");return{keys:O.map((U)=>({name:U})),cursor:W,list_complete:W==="0"}}}}function iJ(G,J={}){return rG(G,J)}function eG(G,J){if(J)return JG(G,J);return{prepare(Y){return new EG(G,Y)}}}function GJ(G,J){if(J)return JG(G,J);return{prepare(Y){return new TG(G,Y)}}}function sJ(G,J){if(J)return JG(G,J);return{prepare(Y){return new DG(G,Y)}}}function JG(G,J){return{prepare(Y){return new RG(G,J,Y)}}}function tJ(G){return{async get(J,Y="text"){let Z=await XY(G,J);if(Z===null||Z===void 0)return null;if(Y==="json"){if(typeof Z==="string")try{return JSON.parse(Z)}catch($){throw new F(`Failed to parse JSON from NuxtHub KV for key ${J}: ${$ instanceof Error?$.message:String($)}`,"KV_JSON_PARSE_FAILED")}return Z}return typeof Z==="string"?Z:JSON.stringify(Z)},async put(J,Y){await WY(G,J,Y)},async delete(J){await HY(G,J)},async list(J){let Y=J?.prefix??"",Z=await OY(G,Y);return{keys:(typeof J?.limit==="number"?Z.slice(0,J.limit):Z).map((X)=>({name:X})),list_complete:!0}}}}function aJ(G,J){return eG({query:async(Z,$=[])=>{let X=J(G.connectionString);if(typeof X.connect==="function")await X.connect();try{return await X.query(Z,$)}finally{if(typeof X.release==="function")X.release();else if(typeof X.end==="function")await X.end()}}})}function rJ(G,J){return GJ({execute:async(Z,$=[])=>{let X=J(G.connectionString);try{if(typeof X.execute==="function")return await X.execute(Z,$);if(typeof X.query==="function")return await X.query(Z,$);throw new F("Hyperdrive MySQL client is missing execute/query methods","MYSQL_CLIENT_INVALID")}finally{if(typeof X.end==="function")await X.end();else if(typeof X.close==="function")await X.close();else if(typeof X.destroy==="function")X.destroy()}}})}function eJ(G){if(!G||typeof G!=="object")return!1;return typeof G.prepare==="function"}function GY(G){if(!G||typeof G!=="object")return!1;let J=G;return typeof J.get==="function"&&typeof J.put==="function"&&typeof J.delete==="function"&&typeof J.list==="function"}class EG{client;sql;bindings;constructor(G,J,Y=[]){this.client=G,this.sql=J,this.bindings=Y}bind(...G){return new EG(this.client,this.sql,G)}async run(){let G=Date.now(),J=QG(this.sql),Y=await this.client.query(J,this.bindings);return{success:!0,results:Y.rows??[],meta:B(G,{changes:typeof Y.rowCount==="number"?Y.rowCount:void 0,command:Y.command})}}async all(){let G=Date.now(),J=QG(this.sql),Y=await this.client.query(J,this.bindings);return{success:!0,results:Y.rows??[],meta:B(G,{changes:typeof Y.rowCount==="number"?Y.rowCount:void 0,command:Y.command})}}async first(){let G=QG(this.sql);return(await this.client.query(G,this.bindings)).rows?.[0]??null}}class TG{client;sql;bindings;constructor(G,J,Y=[]){this.client=G,this.sql=J,this.bindings=Y}bind(...G){return new TG(this.client,this.sql,G)}async run(){let G=Date.now(),J=await AG(this.client,this.sql,this.bindings);if(Array.isArray(J))return{success:!0,results:J,meta:B(G)};let Y=J;return{success:!0,results:[],meta:B(G,{changes:Y.affectedRows,last_row_id:Y.insertId,warningStatus:Y.warningStatus})}}async all(){let G=Date.now(),J=await AG(this.client,this.sql,this.bindings);return{success:!0,results:Array.isArray(J)?J:[],meta:B(G,{changes:!Array.isArray(J)?J.affectedRows:void 0})}}async first(){let G=await AG(this.client,this.sql,this.bindings);if(!Array.isArray(G)||G.length===0)return null;return G[0]}}class DG{client;sql;bindings;constructor(G,J,Y=[]){this.client=G,this.sql=J,this.bindings=Y}bind(...G){return new DG(this.client,this.sql,G)}async run(){let G=Date.now();if(typeof this.client.execute==="function"){let $=await this.client.execute(this.sql,this.bindings);return{success:!0,results:PG($),meta:B(G)}}let J=this.client.prepare?.(this.sql);if(!J||typeof J.run!=="function")throw new F("SQLite client must expose execute() or prepare().run()","SQLITE_CLIENT_INVALID");let Z=await J.run(...this.bindings)??{};return{success:!0,results:[],meta:B(G,{changes:GG(Z.changes),last_row_id:Z.lastInsertRowid??Z.lastID})}}async all(){let G=Date.now();if(typeof this.client.execute==="function"){let Z=await this.client.execute(this.sql,this.bindings);return{success:!0,results:PG(Z),meta:B(G)}}let J=this.client.prepare?.(this.sql);if(!J||typeof J.all!=="function")throw new F("SQLite client must expose execute() or prepare().all()","SQLITE_CLIENT_INVALID");let Y=await J.all(...this.bindings);return{success:!0,results:Array.isArray(Y)?Y:[],meta:B(G)}}async first(){if(typeof this.client.execute==="function"){let J=await this.client.execute(this.sql,this.bindings);return PG(J)[0]??null}let G=this.client.prepare?.(this.sql);if(!G)throw new F("SQLite client must expose execute() or prepare().get()","SQLITE_CLIENT_INVALID");if(typeof G.get==="function"){let J=await G.get(...this.bindings);return J===void 0||J===null?null:J}if(typeof G.all==="function"){let J=await G.all(...this.bindings);if(!Array.isArray(J)||J.length===0)return null;let Y=J[0];return Y===void 0||Y===null?null:Y}throw new F("SQLite prepare() result must expose get() or all()","SQLITE_CLIENT_INVALID")}}class RG{client;sqlTag;sqlText;bindings;constructor(G,J,Y,Z=[]){this.client=G,this.sqlTag=J,this.sqlText=Y,this.bindings=Z}bind(...G){return new RG(this.client,this.sqlTag,this.sqlText,G)}async run(){let G=Date.now(),J=jG(this.sqlTag,this.sqlText,this.bindings),Y=await YY(this.client,J);return{success:!0,results:IG(Y),meta:B(G,aG(Y))}}async all(){let G=Date.now(),J=jG(this.sqlTag,this.sqlText,this.bindings),Y=await JJ(this.client,J);return{success:!0,results:IG(Y),meta:B(G,aG(Y))}}async first(){let G=jG(this.sqlTag,this.sqlText,this.bindings),J=await ZY(this.client,G),Y=IG(J);if(Y.length>0)return Y[0]??null;if(J&&typeof J==="object"&&"row"in J){let Z=J.row;return Z===void 0||Z===null?null:Z}if(J&&typeof J==="object"&&!Array.isArray(J)&&!("rows"in J)&&!("results"in J)&&!("data"in J))return J;return null}}async function JY(G,J,Y,Z){try{let $=await G.scan(J,{MATCH:Y,COUNT:Z});return tG($)}catch{let $=await G.scan(J,"MATCH",Y,"COUNT",String(Z));return tG($)}}function tG(G){if(Array.isArray(G))return{cursor:String(G[0]??"0"),keys:Array.isArray(G[1])?G[1]:[]};return{cursor:String(G.cursor??"0"),keys:Array.isArray(G.keys)?G.keys:[]}}async function AG(G,J,Y){if(typeof G.execute==="function"){let Z=await G.execute(J,Y);if(Array.isArray(Z))return Z[0];return Z}if(typeof G.query==="function"){let Z=await G.query(J,Y);if(Array.isArray(Z))return Z[0];return Z}throw new F("MySQL client must expose execute() or query()","MYSQL_CLIENT_INVALID")}async function YY(G,J){if(typeof G.run==="function")return await G.run(J);if(typeof G.execute==="function")return await G.execute(J);if(typeof G.all==="function")return await G.all(J);throw new F("Drizzle client must expose run(), execute(), or all()","DRIZZLE_CLIENT_INVALID")}async function JJ(G,J){if(typeof G.all==="function")return await G.all(J);if(typeof G.execute==="function")return await G.execute(J);if(typeof G.run==="function")return await G.run(J);throw new F("Drizzle client must expose all(), execute(), or run()","DRIZZLE_CLIENT_INVALID")}async function ZY(G,J){if(typeof G.get==="function")return await G.get(J);return await JJ(G,J)}function jG(G,J,Y){let Z=$Y(J),$=Z.length-1;if($!==Y.length)throw new F(`Drizzle binding mismatch: expected ${$} bindings, received ${Y.length}`,"DRIZZLE_BINDINGS_MISMATCH");if($===0)return G.raw(J);let X=typeof G.empty==="function"?G.empty():G.raw("");for(let W=0;W<Z.length;W++){let H=Z[W];if(H)X.append(G.raw(H));if(W<$)X.append(G`${Y[W]}`)}return X}function $Y(G){let J=[],Y=0,Z=!1,$=!1,X=!1,W=!1;for(let H=0;H<G.length;H++){let O=G[H],U=H+1<G.length?G[H+1]:"";if(X){if(O===`
17
+ `)X=!1;continue}if(W){if(O==="*"&&U==="/")H++,W=!1;continue}if(!Z&&!$){if(O==="-"&&U==="-"){H++,X=!0;continue}if(O==="/"&&U==="*"){H++,W=!0;continue}}if(O==="'"&&!$){if(Z&&U==="'"){H++;continue}Z=!Z;continue}if(O==='"'&&!Z){if($&&U==='"'){H++;continue}$=!$;continue}if(O==="?"&&!Z&&!$)J.push(G.slice(Y,H)),Y=H+1}return J.push(G.slice(Y)),J}function IG(G){if(Array.isArray(G)){if(G.length===2&&Array.isArray(G[0]))return G[0];if(G.length===2&&G[0]&&typeof G[0]==="object"&&!Array.isArray(G[0])&&(Array.isArray(G[1])||G[1]===null||G[1]===void 0))return[];return G}if(G&&typeof G==="object"){let J=G;if(Array.isArray(J.rows))return J.rows;if(Array.isArray(J.results))return J.results;if(Array.isArray(J.data))return J.data}return[]}function aG(G){if(!G)return{};let J;if(Array.isArray(G)&&G.length===2&&G[0]&&typeof G[0]==="object"&&!Array.isArray(G[0]))J=G[0];else if(typeof G==="object"&&!Array.isArray(G))J=G;if(!J)return{};let Y={},Z=GG(J.rowCount)??GG(J.changes)??GG(J.affectedRows);if(Z!==void 0)Y.changes=Z;let $=J.lastInsertRowid??J.lastInsertId??J.insertId;if(typeof $==="number"||typeof $==="string")Y.last_row_id=$;if(J.meta&&typeof J.meta==="object")Object.assign(Y,J.meta);return Y}async function XY(G,J){if(typeof G.get==="function")return await G.get(J);if(typeof G.getItem==="function")return await G.getItem(J);throw new F("NuxtHub KV client must expose get() or getItem()","NUXTHUB_KV_CLIENT_INVALID")}async function WY(G,J,Y){if(typeof G.set==="function"){await G.set(J,Y);return}if(typeof G.setItem==="function"){await G.setItem(J,Y);return}throw new F("NuxtHub KV client must expose set() or setItem()","NUXTHUB_KV_CLIENT_INVALID")}async function HY(G,J){if(typeof G.del==="function"){await G.del(J);return}if(typeof G.removeItem==="function"){await G.removeItem(J);return}throw new F("NuxtHub KV client must expose del() or removeItem()","NUXTHUB_KV_CLIENT_INVALID")}async function OY(G,J){let Y;if(typeof G.keys==="function")Y=await G.keys(J);else if(typeof G.getKeys==="function")Y=await G.getKeys(J);else throw new F("NuxtHub KV client must expose keys() or getKeys()","NUXTHUB_KV_CLIENT_INVALID");if(!Array.isArray(Y))return[];if(!J)return[...Y];return Y.filter((Z)=>Z.startsWith(J))}function PG(G){if(Array.isArray(G))return G;if(G&&typeof G==="object"){let J=G;if(Array.isArray(J.rows))return J.rows;if(Array.isArray(J.results))return J.results}return[]}function B(G,J={}){return{duration:Date.now()-G,...J}}function GG(G){if(typeof G==="number"&&Number.isFinite(G))return G;return}var n=new Map;function QG(G){let J=n.get(G);if(J)return J;let Y="",Z=0,$=!1,X=!1,W=!1,H=!1;for(let O=0;O<G.length;O++){let U=G[O],_=O+1<G.length?G[O+1]:"";if(W){if(Y+=U,U===`
18
+ `)W=!1;continue}if(H){if(Y+=U,U==="*"&&_==="/")Y+="/",O++,H=!1;continue}if(!$&&!X){if(U==="-"&&_==="-"){Y+="--",O++,W=!0;continue}if(U==="/"&&_==="*"){Y+="/*",O++,H=!0;continue}}if(U==="'"&&!X){$=!$,Y+=U;continue}if(U==='"'&&!$){X=!X,Y+=U;continue}if(U==="?"&&!$&&!X){Z++,Y+=`$${Z}`;continue}Y+=U}if(n.set(G,Y),n.size>5000){let O=n.keys().next().value;if(O)n.delete(O)}return Y}g();export{s as validateTableForSharding,OG as schemaExists,dG as runShard,nG as runAllShards,gG as run,FJ as resetConfig,zJ as reassignShard,r as prepare,NG as migrateRecord,h as listTables,MJ as listKnownShards,eJ as isSQLDatabase,GY as isKVStorage,kG as integrateExistingDatabase,pG as initializeAsync,_J as initialize,hJ as indexShard,pJ as indexAllShards,bJ as index,oJ as getTotalDatabaseSize,BJ as getShardStats,sG as getDatabaseSizesAllShards,SJ as getDatabaseSizeForShard,nJ as getDatabaseSizeForKey,IJ as getClosestRegionFromIP,qJ as flush,_G as firstShard,vJ as firstByLookupKey,kJ as firstAllShardsGlobal,iG as firstAllShards,cG as first,uJ as explainShard,gJ as explainAllShards,yJ as explain,wG as dropSchema,i as discoverExistingRecordsWithColumns,l as discoverExistingPrimaryKeys,iJ as createValkeyKVProvider,BG as createSchemaAcrossShards,RJ as createSchema,sJ as createSQLiteProvider,rG as createRedisKVProvider,eG as createPostgreSQLProvider,tJ as createNuxtHubKVProvider,GJ as createMySQLProvider,CG as createMappingsForExistingKeys,aJ as createHyperdrivePostgresProvider,rJ as createHyperdriveMySQLProvider,JG as createDrizzleSQLProvider,cJ as countShard,dJ as countAllShards,mJ as count,VJ as collegedb,fG as clearShardMigrationCache,KG as clearMigrationCache,SG as checkMigrationNeeded,qG as autoDetectAndMigrate,UG as allShard,xJ as allByLookupKey,lG as allAllShardsGlobal,e as allAllShards,mG as all,LG as ShardCoordinator,S as KVShardMapper,F as CollegeDBError};
19
19
 
20
- //# debugId=5E9B10391C3C7EF564756E2164756E21
20
+ //# debugId=DEC582821021CEEA64756E2164756E21
21
21
  //# sourceMappingURL=index.js.map