@earth-app/collegedb 1.0.7 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +453 -117
- package/dist/durable.d.ts +9 -4
- package/dist/durable.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -7
- package/dist/index.js.map +9 -8
- package/dist/kvmap.d.ts +69 -7
- package/dist/kvmap.d.ts.map +1 -1
- package/dist/migrations.d.ts +18 -15
- package/dist/migrations.d.ts.map +1 -1
- package/dist/providers.d.ts +207 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/router.d.ts +25 -10
- package/dist/router.d.ts.map +1 -1
- package/dist/types.d.ts +147 -11
- package/dist/types.d.ts.map +1 -1
- package/package.json +39 -14
package/dist/durable.d.ts
CHANGED
|
@@ -7,10 +7,14 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```typescript
|
|
10
|
-
* // In wrangler.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* // In wrangler.jsonc:
|
|
11
|
+
* // {
|
|
12
|
+
* // "durable_objects": {
|
|
13
|
+
* // "bindings": [
|
|
14
|
+
* // { "name": "ShardCoordinator", "class_name": "ShardCoordinator" }
|
|
15
|
+
* // ]
|
|
16
|
+
* // }
|
|
17
|
+
* // }
|
|
14
18
|
*
|
|
15
19
|
* // Usage in a Worker:
|
|
16
20
|
* const coordinatorId = env.ShardCoordinator.idFromName('default');
|
|
@@ -212,6 +216,7 @@ export declare class ShardCoordinator {
|
|
|
212
216
|
* @param primaryKey - The primary key to allocate a shard for
|
|
213
217
|
* @param state - Current coordinator state containing available shards
|
|
214
218
|
* @param strategy - The allocation strategy to use
|
|
219
|
+
* @param eligibleShards - Optional filtered list of shards to choose from
|
|
215
220
|
* @returns The selected shard binding name
|
|
216
221
|
* @throws {CollegeDBError} If no shards are available
|
|
217
222
|
* @example
|
package/dist/durable.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable.d.ts","sourceRoot":"","sources":["../src/durable.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"durable.d.ts","sourceRoot":"","sources":["../src/durable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAIpE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,gBAAgB;IAC5B;;;OAGG;IACH,OAAO,CAAC,KAAK,CAAqB;IAElC;;;OAGG;gBACS,KAAK,EAAE,kBAAkB;IAIrC;;;;;;;;;;OAUG;YACW,QAAQ;IAYtB;;;;;;;;;;OAUG;YACW,SAAS;IAIvB;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACG,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAgChD;;;;;;OAMG;YACW,gBAAgB;IAO9B;;;;;;;;;OASG;YACW,cAAc;IA4B5B;;;;;;;;;OASG;YACW,iBAAiB;IA6B/B;;;;;;OAMG;YACW,cAAc;IAQ5B;;;;;;;;OAQG;YACW,iBAAiB;IA+B/B;;;;;;;;;;;;;;;OAeG;YACW,mBAAmB;IAsCjC;;;;;;;;;;OAUG;YACW,WAAW;IAOzB;;;;;;;;OAQG;IACH,OAAO,CAAC,eAAe;IAmBvB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,OAAO,CAAC,WAAW;IAgGnB;;;;;;;;;;;OAWG;IACG,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASvD;;;;;;;;;;;OAWG;IACG,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQvD"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
* @author Gregory Mitchell
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
export { all, allAllShards, allShard, collegedb, createSchema, first, firstAllShards, firstShard, flush, getClosestRegionFromIP, getShardStats, initialize, initializeAsync, listKnownShards, prepare, reassignShard, resetConfig, run, runAllShards, runShard } from './router.js';
|
|
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.js';
|
|
12
12
|
export { ShardCoordinator } from './durable.js';
|
|
13
13
|
export { CollegeDBError } from './errors.js';
|
|
14
14
|
export { KVShardMapper } from './kvmap.js';
|
|
15
|
+
export { createHyperdriveMySQLProvider, createHyperdrivePostgresProvider, createMySQLProvider as createMySQLSQLProvider, createPostgreSQLProvider as createPostgresSQLProvider, createRedisKVProvider, createSQLiteProvider as createSQLiteSQLProvider, createValkeyKVProvider, isKVStorage, isSQLDatabase, type HyperdriveBindingLike, type HyperdriveMySQLClientFactory, type HyperdrivePostgresClientFactory, type MySQLClientLike, type PostgresClientLike, type RedisLikeClient, type SQLiteClientLike } from './providers.js';
|
|
15
16
|
export { autoDetectAndMigrate, checkMigrationNeeded, clearMigrationCache, clearShardMigrationCache, createMappingsForExistingKeys, createSchemaAcrossShards, discoverExistingPrimaryKeys, discoverExistingRecordsWithColumns, dropSchema, integrateExistingDatabase, listTables, migrateRecord, schemaExists, validateTableForSharding, type IntegrationOptions, type IntegrationResult, type ValidationResult } from './migrations.js';
|
|
16
|
-
export type { CollegeDBConfig, D1Region, Env, MixedShardingStrategy, OperationType, ShardCoordinatorState, ShardLocation, ShardMapping, ShardStats, ShardingStrategy } from './types.js';
|
|
17
|
+
export type { CollegeDBConfig, D1Region, Env, KVListResult, KVStorage, MixedShardingStrategy, OperationType, PreparedStatement, QueryResult, QueryResultMeta, SQLDatabase, ShardCoordinatorState, ShardLocation, ShardMapping, ShardStats, ShardingStrategy } from './types.js';
|
|
17
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,aAAa,EACb,UAAU,EACV,eAAe,EACf,eAAe,EACf,OAAO,EACP,aAAa,EACb,WAAW,EACX,GAAG,EACH,YAAY,EACZ,QAAQ,EACR,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3C,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,iBAAiB,CAAC;AAGzB,YAAY,EACX,eAAe,EACf,QAAQ,EACR,GAAG,EACH,qBAAqB,EACrB,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,MAAM,YAAY,CAAC"}
|
|
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,aAAa,CAAC;AAGrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3C,OAAO,EACN,6BAA6B,EAC7B,gCAAgC,EAChC,mBAAmB,IAAI,sBAAsB,EAC7C,wBAAwB,IAAI,yBAAyB,EACrD,qBAAqB,EACrB,oBAAoB,IAAI,uBAAuB,EAC/C,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,KAAK,qBAAqB,EAC1B,KAAK,4BAA4B,EACjC,KAAK,+BAA+B,EACpC,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,MAAM,gBAAgB,CAAC;AAGxB,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,iBAAiB,CAAC;AAGzB,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,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
var FJ=Object.defineProperty;var s=(J,Z)=>{for(var Q in Z)FJ(J,Q,{get:Z[Q],enumerable:!0,configurable:!0,set:(V)=>Z[Q]=()=>V})};var y=(J,Z)=>()=>(J&&(Z=J(J=0)),Z);var F;var k=y(()=>{F=class F extends Error{code;constructor(J,Z){super(J);if(this.name="CollegeDBError",this.code=Z,Error.captureStackTrace)Error.captureStackTrace(this,F)}}});var l={};s(l,{KVShardMapper:()=>_});class _{kv;hashKeys;hashCache=new Map;constructor(J,Z={}){this.kv=J,this.hashKeys=Z.hashShardMappings??!0}async hashKey(J){if(!this.hashKeys)return J;let Z=this.hashCache.get(J);if(Z)return Z;let V=new TextEncoder().encode(J),$=await crypto.subtle.digest("SHA-256",V),W=new Uint8Array($),O=Array.from(W).map((j)=>j.toString(16).padStart(2,"0")).join("");if(this.hashCache.size<1e4)this.hashCache.set(J,O);return O}async getShardMapping(J){let Z=await this.hashKey(J),Q=`${w}${Z}`,V=await this.kv.get(Q,"json");if(V)return V;let $=await this.kv.get(`${v}${Z}`,"json");if($)return{shard:$.shard,createdAt:$.createdAt,updatedAt:$.updatedAt,originalKey:this.hashKeys?void 0:J};return null}async setShardMapping(J,Z,Q=[]){let V=[J,...Q],$=Date.now();if(V.length===1){let W=await this.hashKey(J),O=`${w}${W}`,j={shard:Z,createdAt:$,updatedAt:$,originalKey:this.hashKeys?void 0:J};await this.kv.put(O,JSON.stringify(j))}else{let W=await this.hashKey(J),O=`${v}${W}`,j={shard:Z,createdAt:$,updatedAt:$,keys:this.hashKeys?[]:V};await this.kv.put(O,JSON.stringify(j));let U=V.map(async(z)=>{let Y=await this.hashKey(z),x=`${w}${Y}`,G={shard:Z,createdAt:$,updatedAt:$,originalKey:this.hashKeys?void 0:z};return this.kv.put(x,JSON.stringify(G))});await Promise.all(U)}}async updateShardMapping(J,Z){let Q=await this.getShardMapping(J);if(!Q)throw new F(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");let V=await this.hashKey(J),$=`${w}${V}`,W=`${v}${V}`,O=await this.kv.get(W,"json");if(O){let j={...O,shard:Z,updatedAt:Date.now()};await this.kv.put(W,JSON.stringify(j));let U=O.keys.map(async(z)=>{let Y=await this.hashKey(z),x=`${w}${Y}`,G={...Q,shard:Z,updatedAt:Date.now()};return this.kv.put(x,JSON.stringify(G))});await Promise.all(U)}else{let j={...Q,shard:Z,updatedAt:Date.now()};await this.kv.put($,JSON.stringify(j))}}async deleteShardMapping(J){let Z=await this.hashKey(J),Q=`${w}${Z}`,V=`${v}${Z}`,$=await this.kv.get(V,"json");if($){await this.kv.delete(V);let W=$.keys.map(async(O)=>{let j=await this.hashKey(O),U=`${w}${j}`;return this.kv.delete(U)});await Promise.all(W)}else await this.kv.delete(Q)}async getKnownShards(){return await this.kv.get(r,"json")||[]}async setKnownShards(J){if(!J||J.length===0)return;await this.kv.put(r,JSON.stringify(J))}async addKnownShard(J){if(!J)return;let Z=await this.getKnownShards();if(!Z.includes(J))Z.push(J),await this.setKnownShards(Z)}async getKeysForShard(J){let Z=[],Q=await this.kv.list({prefix:w});for(let $ of Q.keys){let W=await this.kv.get($.name,"json");if(W?.shard===J){let O=$.name.replace(w,"");if(W.originalKey)Z.push(W.originalKey);else if(!this.hashKeys)Z.push(O)}}let V=await this.kv.list({prefix:v});for(let $ of V.keys){let W=await this.kv.get($.name,"json");if(W?.shard===J)Z.push(...W.keys)}return[...new Set(Z)]}async getShardKeyCounts(){let J={},Z=await this.kv.list({prefix:w});for(let V of Z.keys){let $=await this.kv.get(V.name,"json");if($)J[$.shard]=(J[$.shard]||0)+1}let Q=await this.kv.list({prefix:v});for(let V of Q.keys){let $=await this.kv.get(V.name,"json");if($)J[$.shard]=(J[$.shard]||0)+$.keys.length}return J}async clearAllMappings(){let Z=(await this.kv.list({prefix:w})).keys.map(($)=>this.kv.delete($.name)),V=(await this.kv.list({prefix:v})).keys.map(($)=>this.kv.delete($.name));await Promise.all([...Z,...V])}async addLookupKeys(J,Z){let Q=await this.getShardMapping(J);if(!Q)throw new F(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");let V=await this.hashKey(J),$=`${v}${V}`,W=await this.kv.get($,"json"),O=[J,...Z],j=Date.now();if(!W)W={shard:Q.shard,createdAt:Q.createdAt,updatedAt:j,keys:this.hashKeys?[]:O};else W={...W,updatedAt:j,keys:this.hashKeys?[]:[...new Set([...W.keys,...O])]};await this.kv.put($,JSON.stringify(W));let U=Z.map(async(z)=>{let Y=await this.hashKey(z),x=`${w}${Y}`,G={shard:Q.shard,createdAt:Q.createdAt,updatedAt:j,originalKey:this.hashKeys?void 0:z};return this.kv.put(x,JSON.stringify(G))});await Promise.all(U)}async getAllLookupKeys(J){let Z=await this.hashKey(J),Q=`${v}${Z}`,V=await this.kv.get(Q,"json");if(V)return V.keys;let $=await this.getShardMapping(J);if($)return $.originalKey?[$.originalKey]:[J];throw new F(`No mapping found for key: ${J}`,"MAPPING_NOT_FOUND")}}var w="shard:",v="multikey:",r="known_shards";var N=y(()=>{k()});var h={};s(h,{validateTableForSharding:()=>c,schemaExists:()=>o,migrateRecord:()=>JJ,listTables:()=>M,integrateExistingDatabase:()=>$J,dropSchema:()=>e,discoverExistingRecordsWithColumns:()=>g,discoverExistingPrimaryKeys:()=>K,createSchemaAcrossShards:()=>a,createSchema:()=>n,createMappingsForExistingKeys:()=>ZJ,clearShardMigrationCache:()=>OJ,clearMigrationCache:()=>WJ,checkMigrationNeeded:()=>VJ,autoDetectAndMigrate:()=>QJ});async function n(J,Z){let Q=Z.split(";").map((V)=>V.trim()).filter((V)=>V.length>0&&!V.startsWith("--"));for(let V of Q)try{await J.prepare(V).run()}catch($){throw console.error("Failed to execute schema statement:",V,$),new F(`Schema migration failed: ${$}`,"SCHEMA_MIGRATION_FAILED")}}async function a(J,Z){let Q=Object.entries(J).map(([V,$])=>{return n($,Z).catch((W)=>{throw new F(`Failed to create schema on shard ${V}: ${W.message}`,"SCHEMA_CREATION_FAILED")})});await Promise.all(Q)}async function o(J,Z){try{return await J.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").bind(Z).first()!==null}catch{return!1}}async function e(J,...Z){for(let Q of Z)try{await J.prepare(`DROP TABLE IF EXISTS ${Q}`).run()}catch(V){console.error(`Failed to drop table ${Q}:`,V)}}async function M(J){try{return(await J.prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").all()).results.map((Q)=>Q.name)}catch{return[]}}async function JJ(J,Z,Q,V){let $=await J.prepare(`SELECT * FROM ${V} WHERE id = ?`).bind(Q).first();if(!$)throw new F(`Record with primary key ${Q} not found in source database`,"RECORD_NOT_FOUND");if(!await o(Z,V))await n(Z,V);let W=Object.keys($),O=W.map(()=>"?").join(", "),j=W.map((z)=>$[z]),U=`INSERT OR REPLACE INTO ${V} (${W.join(", ")}) VALUES (${O})`;await Z.prepare(U).bind(...j).run(),await J.prepare(`DELETE FROM ${V} WHERE id = ?`).bind(Q).run()}async function K(J,Z,Q="id"){try{return(await J.prepare(`SELECT ${Q} FROM ${Z}`).all()).results.map(($)=>String($[Q]))}catch(V){throw new F(`Failed to discover primary keys in table ${Z}: ${V}`,"DISCOVERY_FAILED")}}async function g(J,Z,Q="id"){try{let V=`${Z}_columns`,$;if(d.has(V))$=d.get(V).map((U)=>U.name);else{let z=(await J.prepare(`PRAGMA table_info(${Z})`).all()).results.map((Y)=>({name:Y.name,type:Y.type}));d.set(V,z),$=z.map((Y)=>Y.name)}let W=[Q];if($.includes("username"))W.push("username");if($.includes("email"))W.push("email");if($.includes("name"))W.push("name");let O=`SELECT ${W.join(", ")} FROM ${Z}`;return(await J.prepare(O).all()).results}catch(V){throw new F(`Failed to discover records with columns in table ${Z}: ${V}`,"DISCOVERY_FAILED")}}async function ZJ(J,Z,Q,V){let $=Z.length;for(let W=0;W<J.length;W++){let O=J[W],j;switch(Q){case"hash":let U=0;for(let Y=0;Y<O.length;Y++){let x=O.charCodeAt(Y);U=(U<<5)-U+x,U=U&U}let z=Math.abs(U)%$;j=Z[z];break;case"random":j=Z[Math.floor(Math.random()*$)];break;default:j=Z[W%$];break}await V.setShardMapping(O,j)}}async function c(J,Z,Q){let V=[],$=0;try{if(!await J.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").bind(Z).first())return V.push(`Table '${Z}' does not exist`),{isValid:!1,tableName:Z,primaryKeyColumn:Q,recordCount:0,issues:V};if(!(await J.prepare(`PRAGMA table_info(${Z})`).all()).results.some((z)=>z.name===Q&&z.pk===1))V.push(`Primary key column '${Q}' not found or not set as primary key`);if($=(await J.prepare(`SELECT COUNT(*) as count FROM ${Z}`).first())?.count||0,$===0)V.push(`Table '${Z}' is empty`)}catch(W){V.push(`Database validation error: ${W}`)}return{isValid:V.length===0,tableName:Z,primaryKeyColumn:Q,recordCount:$,issues:V}}async function $J(J,Z,Q,V={}){let{tables:$,primaryKeyColumn:W="id",strategy:O="hash",addShardMappingsTable:j=!0,dryRun:U=!1,migrateOtherColumns:z=!1}=V,Y=[],x=0,G=0,T=0;try{let S=($||await M(J)).filter((X)=>X!=="shard_mappings");for(let X of S)try{let q=await c(J,X,W);if(!q.isValid){Y.push(`Table ${X}: ${q.issues.join(", ")}`);continue}if(z){let B=await g(J,X,W);if(B.length===0){Y.push(`Table ${X} has no records to process`);continue}if(!U)for(let L of B){let E=String(L[W]),C=[];if(L.username&&typeof L.username==="string")C.push(`username:${L.username}`);if(L.email&&typeof L.email==="string")C.push(`email:${L.email}`);if(L.name&&typeof L.name==="string")C.push(`name:${L.name}`);await Q.setShardMapping(E,Z,C),T++}G+=B.length}else{let B=await K(J,X,W);if(B.length===0){Y.push(`Table ${X} has no records to process`);continue}if(!U)for(let L of B)await Q.setShardMapping(L,Z),T++;G+=B.length}x++}catch(q){Y.push(`Failed to process table ${X}: ${q}`)}if(j&&!U){if(!(await M(J)).includes("shard_mappings"))await J.prepare(`
|
|
1
|
+
var kV=Object.defineProperty;var SV=(V)=>V;function fV(V,J){this[V]=SV.bind(null,J)}var OV=(V,J)=>{for(var X in J)kV(V,X,{get:J[X],enumerable:!0,configurable:!0,set:fV.bind(J,X)})};var a=(V,J)=>()=>(V&&(J=V(V=0)),J);var O;var C=a(()=>{O=class O extends Error{code;constructor(V,J){super(V);if(this.name="CollegeDBError",this.code=J,Error.captureStackTrace)Error.captureStackTrace(this,O)}}});var e={};OV(e,{KVShardMapper:()=>k});class k{kv;hashKeys;hashCache=new Map;mappingCache=new Map;knownShardsCache={shards:null,expiresAt:0};mappingCacheTtlMs;knownShardsCacheTtlMs;constructor(V,J={}){this.kv=V,this.hashKeys=J.hashShardMappings??!0,this.mappingCacheTtlMs=J.mappingCacheTtlMs??KV,this.knownShardsCacheTtlMs=J.knownShardsCacheTtlMs??bV}getCachedMapping(V){let J=this.mappingCache.get(V);if(!J)return;if(J.expiresAt<Date.now()){this.mappingCache.delete(V);return}return J.mapping}setCachedMapping(V,J){if(this.mappingCache.size>50000){let X=this.mappingCache.keys().next().value;if(X)this.mappingCache.delete(X)}this.mappingCache.set(V,{mapping:J,expiresAt:Date.now()+this.mappingCacheTtlMs})}async cacheMappingForKeys(V,J){let X=await Promise.all(V.map((Z)=>this.hashKey(Z)));for(let Z of X)this.setCachedMapping(Z,J)}getCachedKnownShards(){if(this.knownShardsCache.shards&&this.knownShardsCache.expiresAt>=Date.now())return[...this.knownShardsCache.shards];return null}setCachedKnownShards(V){this.knownShardsCache.shards=[...V],this.knownShardsCache.expiresAt=Date.now()+this.knownShardsCacheTtlMs}async hashKey(V){if(!this.hashKeys)return V;let J=this.hashCache.get(V);if(J)return J;let Z=new TextEncoder().encode(V),Y=await crypto.subtle.digest("SHA-256",Z),G=new Uint8Array(Y),H=Array.from(G).map(($)=>$.toString(16).padStart(2,"0")).join("");if(this.hashCache.size<1e4)this.hashCache.set(V,H);return H}async getShardMapping(V){let J=await this.hashKey(V),X=this.getCachedMapping(J);if(X!==void 0)return X;let Z=`${B}${J}`,Y=await this.kv.get(Z,"json");if(Y)return this.setCachedMapping(J,Y),Y;let G=await this.kv.get(`${v}${J}`,"json");if(G){let H={shard:G.shard,createdAt:G.createdAt,updatedAt:G.updatedAt,originalKey:this.hashKeys?void 0:V};if(this.setCachedMapping(J,H),this.hashKeys)for(let $ of G.keys)this.setCachedMapping($,H);return H}return this.setCachedMapping(J,null),null}async setShardMapping(V,J,X=[]){let Z=[V,...X],Y=Date.now(),G={shard:J,createdAt:Y,updatedAt:Y,originalKey:this.hashKeys?void 0:V};if(Z.length===1){let H=await this.hashKey(V),$=`${B}${H}`;await this.kv.put($,JSON.stringify(G)),this.setCachedMapping(H,G)}else{let H=await this.hashKey(V),$=`${v}${H}`,W=this.hashKeys?await Promise.all(Z.map((_)=>this.hashKey(_))):Z,U={shard:J,createdAt:Y,updatedAt:Y,keys:W};await this.kv.put($,JSON.stringify(U));let F=Z.map(async(_)=>{let L=await this.hashKey(_),A=`${B}${L}`,T={shard:J,createdAt:Y,updatedAt:Y,originalKey:this.hashKeys?void 0:_};return this.kv.put(A,JSON.stringify(T))});await Promise.all(F),await this.cacheMappingForKeys(Z,G)}}async updateShardMapping(V,J){let X=await this.getShardMapping(V);if(!X)throw new O(`No existing mapping found for primary key: ${V}`,"MAPPING_NOT_FOUND");let Z=await this.hashKey(V),Y=`${B}${Z}`,G=`${v}${Z}`,H=await this.kv.get(G,"json");if(H){let $=Date.now(),W={...H,shard:J,updatedAt:$};await this.kv.put(G,JSON.stringify(W));let U=H.keys.length>0?this.hashKeys?H.keys:H.keys:[await this.hashKey(V)],F=U.map(async(L)=>{let A=`${B}${L}`,T={...X,shard:J,updatedAt:$};return this.kv.put(A,JSON.stringify(T))});await Promise.all(F);let _={...X,shard:J,updatedAt:$};if(this.hashKeys)for(let L of U)this.setCachedMapping(L,_);this.setCachedMapping(Z,_)}else{let $={...X,shard:J,updatedAt:Date.now()};await this.kv.put(Y,JSON.stringify($)),this.setCachedMapping(Z,$)}}async deleteShardMapping(V){let J=await this.hashKey(V),X=`${B}${J}`,Z=`${v}${J}`,Y=await this.kv.get(Z,"json");if(Y){await this.kv.delete(Z);let G=Y.keys.length>0?this.hashKeys?Y.keys:Y.keys:[await this.hashKey(V)],H=G.map(async($)=>{let W=`${B}${$}`;return this.kv.delete(W)});if(await Promise.all(H),this.hashKeys)for(let $ of G)this.setCachedMapping($,null);this.setCachedMapping(J,null)}else await this.kv.delete(X),this.setCachedMapping(J,null)}async getKnownShards(){let V=this.getCachedKnownShards();if(V)return V;let X=await this.kv.get(_V,"json")||[];return this.setCachedKnownShards(X),X}async setKnownShards(V){if(!V||V.length===0)return;let J=[...new Set(V.filter(Boolean))];if(J.length===0)return;await this.kv.put(_V,JSON.stringify(J)),this.setCachedKnownShards(J)}async addKnownShard(V){if(!V)return;let J=await this.getKnownShards();if(!J.includes(V))J.push(V),await this.setKnownShards(J)}async getKeysForShard(V){let J=[],X=await this.kv.list({prefix:B});for(let Y of X.keys){let G=await this.kv.get(Y.name,"json");if(G?.shard===V){let H=Y.name.replace(B,"");if(G.originalKey)J.push(G.originalKey);else if(!this.hashKeys)J.push(H)}}let Z=await this.kv.list({prefix:v});for(let Y of Z.keys){let G=await this.kv.get(Y.name,"json");if(G?.shard===V)J.push(...G.keys)}return[...new Set(J)]}async getShardKeyCounts(){let V={},J=await this.kv.list({prefix:B});for(let Z of J.keys){let Y=await this.kv.get(Z.name,"json");if(Y)V[Y.shard]=(V[Y.shard]||0)+1}let X=await this.kv.list({prefix:v});for(let Z of X.keys){let Y=await this.kv.get(Z.name,"json");if(Y)V[Y.shard]=(V[Y.shard]||0)+Y.keys.length}return V}async clearAllMappings(){let J=(await this.kv.list({prefix:B})).keys.map((Y)=>this.kv.delete(Y.name)),Z=(await this.kv.list({prefix:v})).keys.map((Y)=>this.kv.delete(Y.name));await Promise.all([...J,...Z]),this.mappingCache.clear()}async addLookupKeys(V,J){let X=await this.getShardMapping(V);if(!X)throw new O(`No existing mapping found for primary key: ${V}`,"MAPPING_NOT_FOUND");let Z=await this.hashKey(V),Y=`${v}${Z}`,G=await this.kv.get(Y,"json"),H=[V,...J],$=Date.now();if(!G){let F=this.hashKeys?await Promise.all(H.map((_)=>this.hashKey(_))):H;G={shard:X.shard,createdAt:X.createdAt,updatedAt:$,keys:F}}else{let F=this.hashKeys?await Promise.all(H.map((_)=>this.hashKey(_))):H;G={...G,updatedAt:$,keys:[...new Set([...G.keys,...F])]}}await this.kv.put(Y,JSON.stringify(G));let W=J.map(async(F)=>{let _=await this.hashKey(F),L=`${B}${_}`,A={shard:X.shard,createdAt:X.createdAt,updatedAt:$,originalKey:this.hashKeys?void 0:F};return this.kv.put(L,JSON.stringify(A))});await Promise.all(W);let U={shard:X.shard,createdAt:X.createdAt,updatedAt:$,originalKey:X.originalKey};await this.cacheMappingForKeys([V,...J],U)}async setShardMappingsBatch(V,J={}){if(V.length===0)return;let X=Math.max(1,J.concurrency??25),Z=0,Y=Array(Math.min(X,V.length)).fill(null).map(async()=>{while(Z<V.length){let G=Z++,H=V[G];if(!H)continue;await this.setShardMapping(H.primaryKey,H.shard,H.additionalKeys||[])}});await Promise.all(Y)}async getAllLookupKeys(V){let J=await this.hashKey(V),X=`${v}${J}`,Z=await this.kv.get(X,"json");if(Z)return Z.keys;let Y=await this.getShardMapping(V);if(Y)return Y.originalKey?[Y.originalKey]:[V];throw new O(`No mapping found for key: ${V}`,"MAPPING_NOT_FOUND")}}var B="shard:",v="multikey:",_V="known_shards",KV=30000,bV=1e4;var g=a(()=>{C()});var t={};OV(t,{validateTableForSharding:()=>o,schemaExists:()=>XV,migrateRecord:()=>AV,listTables:()=>b,integrateExistingDatabase:()=>PV,dropSchema:()=>jV,discoverExistingRecordsWithColumns:()=>n,discoverExistingPrimaryKeys:()=>l,createSchemaAcrossShards:()=>QV,createSchema:()=>JV,createMappingsForExistingKeys:()=>IV,clearShardMigrationCache:()=>zV,clearMigrationCache:()=>RV,checkMigrationNeeded:()=>EV,autoDetectAndMigrate:()=>TV});async function LV(V,J,X){if(V.length===0)return;let Z=Math.max(1,Math.min(J,V.length)),Y=0,G=Array(Z).fill(null).map(async()=>{while(Y<V.length){let H=Y++,$=V[H];if($===void 0)continue;await X($,H)}});await Promise.all(G)}function uV(V,J,X,Z){let Y=X.length;switch(Z){case"hash":{let G=0;for(let $=0;$<V.length;$++){let W=V.charCodeAt($);G=(G<<5)-G+W,G=G&G}let H=Math.abs(G)%Y;return X[H]}case"random":return X[Math.floor(Math.random()*Y)];default:return X[J%Y]}}async function JV(V,J){let X=J.split(";").map((Z)=>Z.trim()).filter((Z)=>Z.length>0&&!Z.startsWith("--"));for(let Z of X)try{await V.prepare(Z).run()}catch(Y){throw console.error("Failed to execute schema statement:",Z,Y),new O(`Schema migration failed: ${Y}`,"SCHEMA_MIGRATION_FAILED")}}async function QV(V,J){let X=Object.entries(V).map(([Z,Y])=>{return JV(Y,J).catch((G)=>{throw new O(`Failed to create schema on shard ${Z}: ${G.message}`,"SCHEMA_CREATION_FAILED")})});await Promise.all(X)}async function XV(V,J){try{return await V.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").bind(J).first()!==null}catch{return!1}}async function jV(V,...J){for(let X of J)try{await V.prepare(`DROP TABLE IF EXISTS ${X}`).run()}catch(Z){console.error(`Failed to drop table ${X}:`,Z)}}async function b(V){try{return(await V.prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").all()).results.map((X)=>X.name)}catch{return[]}}async function AV(V,J,X,Z){let Y=await V.prepare(`SELECT * FROM ${Z} WHERE id = ?`).bind(X).first();if(!Y)throw new O(`Record with primary key ${X} not found in source database`,"RECORD_NOT_FOUND");if(!await XV(J,Z))await JV(J,Z);let G=Object.keys(Y),H=G.map(()=>"?").join(", "),$=G.map((U)=>Y[U]),W=`INSERT OR REPLACE INTO ${Z} (${G.join(", ")}) VALUES (${H})`;await J.prepare(W).bind(...$).run(),await V.prepare(`DELETE FROM ${Z} WHERE id = ?`).bind(X).run()}async function l(V,J,X="id"){try{return(await V.prepare(`SELECT ${X} FROM ${J}`).all()).results.map((Y)=>String(Y[X]))}catch(Z){throw new O(`Failed to discover primary keys in table ${J}: ${Z}`,"DISCOVERY_FAILED")}}async function n(V,J,X="id"){try{let Z=`${J}_columns`,Y;if(VV.has(Z))Y=VV.get(Z).map((W)=>W.name);else{let U=(await V.prepare(`PRAGMA table_info(${J})`).all()).results.map((F)=>({name:F.name,type:F.type}));VV.set(Z,U),Y=U.map((F)=>F.name)}let G=[X];if(Y.includes("username"))G.push("username");if(Y.includes("email"))G.push("email");if(Y.includes("name"))G.push("name");let H=`SELECT ${G.join(", ")} FROM ${J}`;return(await V.prepare(H).all()).results}catch(Z){throw new O(`Failed to discover records with columns in table ${J}: ${Z}`,"DISCOVERY_FAILED")}}async function IV(V,J,X,Z,Y={}){if(V.length===0||J.length===0)return;let G=Math.max(1,Y.concurrency??25),H=V.map(($,W)=>({primaryKey:$,shard:uV($,W,J,X)}));await Z.setShardMappingsBatch(H,{concurrency:G})}async function o(V,J,X){let Z=[],Y=0;try{if(!await V.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:X,recordCount:0,issues:Z};if(!(await V.prepare(`PRAGMA table_info(${J})`).all()).results.some((U)=>U.name===X&&U.pk===1))Z.push(`Primary key column '${X}' not found or not set as primary key`);if(Y=(await V.prepare(`SELECT COUNT(*) as count FROM ${J}`).first())?.count||0,Y===0)Z.push(`Table '${J}' is empty`)}catch(G){Z.push(`Database validation error: ${G}`)}return{isValid:Z.length===0,tableName:J,primaryKeyColumn:X,recordCount:Y,issues:Z}}async function PV(V,J,X,Z={}){let{tables:Y,primaryKeyColumn:G="id",strategy:H="hash",addShardMappingsTable:$=!0,dryRun:W=!1,migrateOtherColumns:U=!1,concurrency:F=25}=Z,_=Math.max(1,F),L=[],A=0,T=0,z=0;try{let Q=(Y||await b(V)).filter((j)=>j!=="shard_mappings");for(let j of Q)try{let R=await o(V,j,G);if(!R.isValid){L.push(`Table ${j}: ${R.issues.join(", ")}`);continue}if(U){let E=await n(V,j,G);if(E.length===0){L.push(`Table ${j} has no records to process`);continue}if(!W){let P=E.map((I)=>{let s=String(I[G]),K=[];if(I.username&&typeof I.username==="string")K.push(`username:${I.username}`);if(I.email&&typeof I.email==="string")K.push(`email:${I.email}`);if(I.name&&typeof I.name==="string")K.push(`name:${I.name}`);return{primaryKey:s,shard:J,additionalKeys:K}});await X.setShardMappingsBatch(P,{concurrency:_}),z+=P.length}T+=E.length}else{let E=await l(V,j,G);if(E.length===0){L.push(`Table ${j} has no records to process`);continue}if(!W){let P=E.map((I)=>({primaryKey:I,shard:J}));await X.setShardMappingsBatch(P,{concurrency:_}),z+=P.length}T+=E.length}A++}catch(R){L.push(`Failed to process table ${j}: ${R}`)}if($&&!W){if(!(await b(V)).includes("shard_mappings"))await V.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(!
|
|
8
|
-
SELECT ${
|
|
9
|
-
ORDER BY ${
|
|
10
|
-
LIMIT ?`.trim()).bind(
|
|
7
|
+
);`.trim()).run()}if(!W)await X.addKnownShard(J)}catch(q){L.push(`Integration failed: ${q}`)}return{success:L.length===0||L.length>0&&A>0,shardName:J,tablesProcessed:A,totalRecords:T,mappingsCreated:z,issues:L}}async function TV(V,J,X,Z={}){let{primaryKeyColumn:Y="id",tablesToCheck:G,skipCache:H=!1,maxRecordsToCheck:$=1000,migrateOtherColumns:W=!1,concurrency:U=X.migrationConcurrency??25}=Z,F=Math.max(1,U),_=`${J}_migration_check`;if(!H&&S.has(_))return{migrationNeeded:!1,migrationPerformed:!1,recordsMigrated:0,tablesProcessed:0,issues:[]};let L=[],A=0,T=0,z=!1,q=!1;try{let{KVShardMapper:Q}=await Promise.resolve().then(() => (g(),e)),j=new Q(X.kv,{hashShardMappings:X.hashShardMappings,mappingCacheTtlMs:X.mappingCacheTtlMs,knownShardsCacheTtlMs:X.knownShardsCacheTtlMs}),R=await b(V),E=G||R.filter((P)=>P!=="shard_mappings"&&!P.startsWith("sqlite_")&&P!=="sqlite_sequence");if(E.length===0)return S.set(_,!0),{migrationNeeded:!1,migrationPerformed:!1,recordsMigrated:0,tablesProcessed:0,issues:[]};for(let P of E)try{let I=await o(V,P,Y);if(!I.isValid||I.recordCount===0)continue;let s=Math.min($,I.recordCount),K=await V.prepare(`
|
|
8
|
+
SELECT ${Y} FROM ${P}
|
|
9
|
+
ORDER BY ${Y}
|
|
10
|
+
LIMIT ?`.trim()).bind(s).all(),UV=0,NV=K.results.slice(0,10).map(async(N)=>{let w=String(N[Y]);return{key:w,mapping:await j.getShardMapping(w)}}),CV=await Promise.all(NV);for(let N of CV)if(!N.mapping)UV++,z=!0;if(UV>0){if(X.debug)console.log(`Auto-migrating table ${P} in shard ${J} (${I.recordCount} records)`);if(W){let N=await n(V,P,Y),w=[];if(await LV(N,F,async(D)=>{let r=String(D[Y]);if(await j.getShardMapping(r))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}`);w.push({primaryKey:r,shard:J,additionalKeys:d})}),w.length>0)await j.setShardMappingsBatch(w,{concurrency:F});A+=w.length}else{let N=await l(V,P,Y),w=[];if(await LV(N,F,async(D)=>{if(!await j.getShardMapping(D))w.push({primaryKey:D,shard:J})}),w.length>0)await j.setShardMappingsBatch(w,{concurrency:F});A+=w.length}if(T++,q=!0,X.debug)console.log(`Auto-migrated ${A} records from table ${P}`)}}catch(I){L.push(`Auto-migration failed for table ${P}: ${I}`)}if(q){if(await j.addKnownShard(J),!R.includes("shard_mappings"))await V.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(P.set(z,!0),D&&Q.debug)console.log(`Auto-migration completed for shard ${Z}: ${x} records from ${G} tables`)}catch(S){Y.push(`Auto-migration error: ${S}`)}return{migrationNeeded:T,migrationPerformed:D,recordsMigrated:x,tablesProcessed:G,issues:Y}}async function VJ(J,Z,Q){let V=`${Z}_migration_check`;if(P.has(V))return!1;try{let $=await M(J);if($.includes("shard_mappings"))return P.set(V,!0),!1;let{KVShardMapper:O}=await Promise.resolve().then(() => (N(),l)),j=new O(Q.kv,{hashShardMappings:Q.hashShardMappings}),U=$.filter((z)=>z!=="shard_mappings"&&!z.startsWith("sqlite_")&&z!=="sqlite_sequence");for(let z of U.slice(0,3))try{if(((await J.prepare(`SELECT COUNT(*) as count FROM ${z} LIMIT 1`).first())?.count||0)>0){let G=await J.prepare(`SELECT id FROM ${z} LIMIT 1`).first();if(G){let T=String(G.id);if(!await j.getShardMapping(T))return!0}}}catch{continue}return!1}catch{return!1}}function WJ(){P.clear()}function OJ(J){let Z=`${J}_migration_check`;P.delete(Z)}var P,d;var f=y(()=>{k();P=new Map,d=new Map});k();N();var b=null;function GJ(J){if(b=J,J.shards&&Object.keys(J.shards).length>0&&!J.disableAutoMigration)YJ(J).catch((Z)=>{console.warn("Background auto-migration failed:",Z)})}async function UJ(J){if(b=J,J.shards&&Object.keys(J.shards).length>0&&!J.disableAutoMigration)try{await YJ(J)}catch(Z){console.warn("Auto migration failed:",Z)}}async function LJ(J,Z){return await UJ(J),await Z()}async function YJ(J){try{let{autoDetectAndMigrate:Z}=await Promise.resolve().then(() => (f(),h)),Q=Object.keys(J.shards);if(J.debug)console.log(`\uD83D\uDD0D Checking ${Q.length} shards for existing data...`);let V=Q.map(async(O)=>{let j=J.shards[O];if(!j)return null;try{let U=await Z(j,O,J,{maxRecordsToCheck:1000});return{shardName:O,...U}}catch(U){return console.warn(`Auto-migration failed for shard ${O}:`,U),null}}),W=(await Promise.all(V)).filter((O)=>O?.migrationPerformed);if(J.debug)if(W.length>0){let O=W.reduce((j,U)=>j+(U?.recordsMigrated||0),0);console.log(`\uD83C\uDF89 Auto-migration completed! Migrated ${O} records across ${W.length} shards`),W.forEach((j)=>{if(j)console.log(` ✅ ${j.shardName}: ${j.recordsMigrated} records from ${j.tablesProcessed} tables`)})}else console.log("✅ All shards ready - no migration needed")}catch(Z){console.warn("Background auto-migration setup failed:",Z)}}function XJ(){b=null}function A(){if(!b)throw new F("CollegeDB not initialized. Call initialize() first.","NOT_INITIALIZED");return b}function TJ(J){let Z=J.trim().toUpperCase();if(Z.startsWith("SELECT")||Z.startsWith("VALUES")||Z.startsWith("TABLE")||Z.startsWith("PRAGMA")||Z.startsWith("EXPLAIN")||Z.startsWith("WITH")||Z.startsWith("SHOW"))return"read";return"write"}function HJ(J,Z){let Q=J.strategy||"hash";if(typeof Q==="string")return Q;return Q[Z]}function wJ(J,Z){if(J===Z)return 0;let Q={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}},V=Q[J],$=Q[Z],W=V.lat-$.lat,O=V.lon-$.lon;return Math.sqrt(W*W+O*O)}function AJ(J){let Z=J.cf;if(!Z||!Z.country)return"wnam";let{country:Q,continent:V}=Z;if(["US","CA","MX"].includes(Q)){let $=Z.region||Z.regionCode||"",W=Z.timezone||"";if($.includes("CA")||$.includes("WA")||$.includes("OR")||$.includes("NV")||$.includes("AZ")||$.includes("UT")||W.includes("Pacific")||W.includes("America/Los_Angeles"))return"wnam";return"enam"}if(["GL","PM","BM"].includes(Q))return"enam";if(["GB","IE","FR","ES","PT","NL","BE","LU","CH","AT","IT"].includes(Q))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(Q))return"eeur";if(Q==="RU")return"eeur";if(["JP","KR","CN","HK","TW","MO","MN","KP"].includes(Q))return"apac";if(["TH","VN","SG","MY","ID","PH","BN","KH","LA","MM","TL","IN","PK","BD","LK","NP","BT","MV","AF"].includes(Q))return"apac";if(["AU","NZ","PG","FJ","NC","VU","SB","WS","TO","KI","NR","PW","FM","MH","TV"].includes(Q))return"oc";if(["AE","SA","QA","KW","BH","OM","YE","IQ","IR","SY","LB","JO","IL","PS","TR","CY"].includes(Q))return"me";if(V==="AF"||["EG","LY","TN","DZ","MA","SD","SS","ET","ER","DJ","SO"].includes(Q))return"af";if(["KZ","UZ","TM","TJ","KG"].includes(Q))return"eeur";if(V==="SA"||["BR","AR","CL","PE","CO","VE","EC","BO","PY","UY","GY","SR","GF"].includes(Q))return"enam";if(["GT","BZ","SV","HN","NI","CR","PA","CU","JM","HT","DO","PR","TT","BB","GD","VC","LC","DM","AG","KN"].includes(Q))return"enam";return"wnam"}function DJ(J,Z,Q,V){let $=Z.filter((Y)=>Q[Y]);if($.length===0){let Y=0;for(let G=0;G<V.length;G++){let T=V.charCodeAt(G);Y=(Y<<5)-Y+T,Y=Y&Y}let x=Math.abs(Y)%Z.length;return Z[x]}let W=$.map((Y)=>{let x=Q[Y],G=wJ(J,x.region),T=x.priority||1,D=G-T*0.1;return{shard:Y,score:D,distance:G,priority:T}});W.sort((Y,x)=>Y.score-x.score);let O=W[0].score,j=W.filter((Y)=>Math.abs(Y.score-O)<0.01);if(j.length===1)return j[0].shard;let U=0;for(let Y=0;Y<V.length;Y++){let x=V.charCodeAt(Y);U=(U<<5)-U+x,U=U&U}let z=Math.abs(U)%j.length;return j[z].shard}async function BJ(J,Z="write"){let Q=A(),V=new _(Q.kv,{hashShardMappings:Q.hashShardMappings}),$=await V.getShardMapping(J);if($)return $.shard;let W=Object.keys(Q.shards);if(W.length===0)throw new F("No shards configured","NO_SHARDS");let O,j=HJ(Q,Z);if(Q.coordinator)try{let U=Q.coordinator.idFromName("default"),Y=await Q.coordinator.get(U).fetch("http://coordinator/allocate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({primaryKey:J,strategy:j,operationType:Z,targetRegion:Q.targetRegion,shardLocations:Q.shardLocations})});if(Y.ok)O=(await Y.json()).shard;else O=W[Math.floor(Math.random()*W.length)]}catch(U){console.warn("Coordinator allocation failed, falling back to local strategy:",U),O=W[Math.floor(Math.random()*W.length)]}else switch(j){case"hash":let U=0;for(let Y=0;Y<J.length;Y++){let x=J.charCodeAt(Y);U=(U<<5)-U+x,U=U&U}let z=Math.abs(U)%W.length;O=W[z]||W[0];break;case"location":if(!Q.targetRegion){console.warn("Location strategy requires targetRegion in config, falling back to hash");let Y=0;for(let G=0;G<J.length;G++){let T=J.charCodeAt(G);Y=(Y<<5)-Y+T,Y=Y&Y}let x=Math.abs(Y)%W.length;O=W[x]||W[0]}else O=DJ(Q.targetRegion,W,Q.shardLocations||{},J);break;case"random":O=W[Math.floor(Math.random()*W.length)]||W[0];break;default:O=W[0];break}return await V.setShardMapping(J,O),O}async function vJ(J,Z="write"){let Q=A(),V=await BJ(J,Z),$=Q.shards[V];if(!$)throw new F(`Shard ${V} not found in configuration`,"SHARD_NOT_FOUND");return $}async function EJ(J,Z){let{createSchema:Q}=await Promise.resolve().then(() => (f(),h));await Q(J,Z)}async function p(J,Z){let Q=TJ(Z);return(await vJ(J,Q)).prepare(Z)}async function RJ(J,Z,Q=[]){let $=await(await p(J,Z)).bind(...Q).run();if(!$.success)throw new F(`Query failed: ${$.error||"Unknown error"}`,"QUERY_FAILED");return $}async function _J(J,Z,Q=[]){let $=await(await p(J,Z)).bind(...Q).all();if(!$.success)throw new F(`Query failed: ${$.error||"Unknown error"}`,"QUERY_FAILED");return $}async function qJ(J,Z,Q=[]){return await(await p(J,Z)).bind(...Q).first()}async function IJ(J,Z,Q){let V=A();if(!V.shards[Z])throw new F(`Shard ${Z} not found in configuration`,"SHARD_NOT_FOUND");let $=new _(V.kv,{hashShardMappings:V.hashShardMappings}),W=await $.getShardMapping(J);if(!W)throw new F(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");if(W.shard!==Z){let{migrateRecord:O}=await Promise.resolve().then(() => (f(),h)),j=V.shards[W.shard],U=V.shards[Z];if(!j||!U)throw new F("Source or target shard not available","SHARD_UNAVAILABLE");await O(j,U,J,Q)}await $.updateShardMapping(J,Z)}async function PJ(){let J=A();if(J.coordinator)try{let Z=J.coordinator.idFromName("default"),V=await J.coordinator.get(Z).fetch("http://coordinator/shards");if(V.ok)return await V.json()}catch(Z){console.warn("Failed to get shards from coordinator:",Z)}return Object.keys(J.shards)}async function CJ(){let J=A();if(J.coordinator)try{let V=J.coordinator.idFromName("default"),W=await J.coordinator.get(V).fetch("http://coordinator/stats");if(W.ok)return await W.json()}catch(V){console.warn("Failed to get stats from coordinator:",V)}let Q=await new _(J.kv,{hashShardMappings:J.hashShardMappings}).getShardKeyCounts();return Object.entries(J.shards).map(([V,$])=>({binding:V,count:Q[V]||0}))}async function kJ(J,Z,Q=[]){let $=A().shards[J];if(!$)throw new F(`Shard ${J} not found`,"SHARD_NOT_FOUND");let W=await $.prepare(Z).bind(...Q).run();if(!W.success)throw new F(`Query failed: ${W.error||"Unknown error"}`,"QUERY_FAILED");return W}async function MJ(J,Z,Q=[]){let $=A().shards[J];if(!$)throw new F(`Shard ${J} not found`,"SHARD_NOT_FOUND");return await $.prepare(Z).bind(...Q).all()}async function SJ(J,Z,Q=[]){let $=A().shards[J];if(!$)throw new F(`Shard ${J} not found`,"SHARD_NOT_FOUND");return await $.prepare(Z).bind(...Q).first()}async function NJ(J,Z=[],Q=50){let V=A(),$=[];for(let[O,j]of Object.entries(V.shards))try{let U=j.prepare(J).bind(...Z).all().catch((z)=>{return console.error(`Error executing query on shard ${O}:`,z),{success:!1,results:[],meta:{count:0,duration:0}}});$.push(U)}catch(U){console.error(`Error running on shard ${O}:`,U)}let W=[];for(let O=0;O<$.length;O+=Q)W.push(...await Promise.all($.slice(O,O+Q)));return W}async function fJ(J,Z=[],Q=50){let V=A(),$=[];for(let[O,j]of Object.entries(V.shards))try{let U=j.prepare(J).bind(...Z).all().catch((z)=>{return console.error(`Error executing query on shard ${O}:`,z),{success:!1,results:[],meta:{count:0,duration:0}}});$.push(U)}catch(U){console.error(`Error running on shard ${O}:`,U)}let W=[];for(let O=0;O<$.length;O+=Q)W.push(...await Promise.all($.slice(O,O+Q)));return W}async function bJ(J,Z=[],Q=50){let V=A(),$=[];for(let[O,j]of Object.entries(V.shards))try{let U=j.prepare(J).bind(...Z).first().catch((z)=>{return console.error(`Error executing query on shard ${O}:`,z),null});$.push(U)}catch(U){console.error(`Error running on shard ${O}:`,U)}let W=[];for(let O=0;O<$.length;O+=Q)W.push(...await Promise.all($.slice(O,O+Q)));return W}async function uJ(){let J=A();if(await new _(J.kv,{hashShardMappings:J.hashShardMappings}).clearAllMappings(),J.coordinator)try{let Q=J.coordinator.idFromName("default");await J.coordinator.get(Q).fetch("http://coordinator/flush",{method:"POST"})}catch(Q){console.warn("Failed to flush coordinator:",Q)}}k();class t{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 Q=new URL(J.url).pathname,V=J.method;try{switch(`${V} ${Q}`){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($){return console.error("ShardCoordinator error:",$),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:Z}=await J.json();if(!Z||typeof Z!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Q=await this.getState();if(!Q.knownShards.includes(Z))Q.knownShards.push(Z),Q.shardStats[Z]={binding:Z,count:0,lastUpdated:Date.now()},await this.saveState(Q);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleRemoveShard(J){let{shard:Z}=await J.json();if(!Z||typeof Z!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Q=await this.getState(),V=Q.knownShards.indexOf(Z);if(V>-1){if(Q.knownShards.splice(V,1),delete Q.shardStats[Z],Q.roundRobinIndex>=Q.knownShards.length)Q.roundRobinIndex=0;await this.saveState(Q)}return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleGetStats(){let J=await this.getState(),Z=Object.values(J.shardStats);return new Response(JSON.stringify(Z),{headers:{"Content-Type":"application/json"}})}async handleUpdateStats(J){let{shard:Z,count:Q}=await J.json();if(!Z||typeof Z!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});if(Q===void 0||typeof Q!=="number")return new Response(JSON.stringify({error:"Missing or invalid count parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let V=await this.getState();if(V.shardStats[Z])V.shardStats[Z].count=Q,V.shardStats[Z].lastUpdated=Date.now(),await this.saveState(V);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleAllocateShard(J){let{primaryKey:Z,strategy:Q,operationType:V}=await J.json();if(!Z||typeof Z!=="string")return new Response(JSON.stringify({error:"Missing or invalid primaryKey parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let $=await this.getState();if($.knownShards.length===0)return new Response(JSON.stringify({error:"No shards available"}),{status:400,headers:{"Content-Type":"application/json"}});let W=this.resolveStrategy($.strategy,Q,V||"write"),O=this.selectShard(Z,$,W);if(W==="round-robin")$.roundRobinIndex=($.roundRobinIndex+1)%$.knownShards.length,await this.saveState($);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(J,Z,Q="write"){if(Z)return Z;if(typeof J==="string")return J;return J[Q]}selectShard(J,Z,Q){let V=Z.knownShards;if(V.length===0)throw new F("No shards available","NO_SHARDS");switch(Q){case"round-robin":return V[Z.roundRobinIndex]??V[0];case"random":return V[Math.floor(Math.random()*V.length)];case"hash":let $=0;for(let U=0;U<J.length;U++){let z=J.charCodeAt(U);$=($<<5)-$+z,$=$&$}let W=Math.abs($)%V.length;return V[W];case"location":let O=0;for(let U=0;U<J.length;U++){let z=J.charCodeAt(U);O=(O<<5)-O+z,O=O&O}let j=Math.abs(O)%V.length;return V[j];default:return V[0]}}async incrementShardCount(J){let Z=await this.getState();if(Z.shardStats[J])Z.shardStats[J].count++,Z.shardStats[J].lastUpdated=Date.now(),await this.saveState(Z)}async decrementShardCount(J){let Z=await this.getState();if(Z.shardStats[J]&&Z.shardStats[J].count>0)Z.shardStats[J].count--,Z.shardStats[J].lastUpdated=Date.now(),await this.saveState(Z)}}if(typeof global!=="undefined"){class J{data=new Map;async get(V){return this.data.get(V)}async put(V,$){this.data.set(V,$)}async delete(V){return this.data.delete(V)}async deleteAll(){this.data.clear()}async list(V){if(!V?.prefix)return new Map(this.data);let $=new Map;for(let[W,O]of this.data.entries())if(W.startsWith(V.prefix))$.set(W,O);return $}}class Z{storage;constructor(){this.storage=new J}}class Q{coordinator;mockState;constructor(){this.mockState=new Z,this.coordinator=new t(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(),O=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!==O.shard,"Round-robin should alternate shards");let U=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"consistent-key",strategy:"hash"})}))).json(),Y=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"consistent-key",strategy:"hash"})}))).json();console.assert(U.shard===Y.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 V=await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"test-key"})}));console.assert(V.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 V=await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"})),$=await V.json(),W=$.find((j)=>j.binding==="db-count-test");console.assert(W?.count===2,"Count should be 2 after two increments"),await this.coordinator.decrementShardCount("db-count-test"),V=await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"})),$=await V.json();let O=$.find((j)=>j.binding==="db-count-test");console.assert(O?.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(V){return console.error("❌ ShardCoordinator tests failed:",V),!1}}}globalThis.testShardCoordinator=()=>new Q}k();N();f();export{c as validateTableForSharding,o as schemaExists,kJ as runShard,NJ as runAllShards,RJ as run,XJ as resetConfig,IJ as reassignShard,p as prepare,JJ as migrateRecord,M as listTables,PJ as listKnownShards,$J as integrateExistingDatabase,UJ as initializeAsync,GJ as initialize,CJ as getShardStats,AJ as getClosestRegionFromIP,uJ as flush,SJ as firstShard,bJ as firstAllShards,qJ as first,e as dropSchema,g as discoverExistingRecordsWithColumns,K as discoverExistingPrimaryKeys,a as createSchemaAcrossShards,EJ as createSchema,ZJ as createMappingsForExistingKeys,LJ as collegedb,OJ as clearShardMigrationCache,WJ as clearMigrationCache,VJ as checkMigrationNeeded,QJ as autoDetectAndMigrate,MJ as allShard,fJ as allAllShards,_J as all,t as ShardCoordinator,_ as KVShardMapper,F as CollegeDBError};
|
|
16
|
+
`).run()}if(S.set(_,!0),q&&X.debug)console.log(`Auto-migration completed for shard ${J}: ${A} records from ${T} tables`)}catch(Q){L.push(`Auto-migration error: ${Q}`)}return{migrationNeeded:z,migrationPerformed:q,recordsMigrated:A,tablesProcessed:T,issues:L}}async function EV(V,J,X){let Z=`${J}_migration_check`;if(S.has(Z))return!1;try{let Y=await b(V);if(Y.includes("shard_mappings"))return S.set(Z,!0),!1;let{KVShardMapper:H}=await Promise.resolve().then(() => (g(),e)),$=new H(X.kv,{hashShardMappings:X.hashShardMappings,mappingCacheTtlMs:X.mappingCacheTtlMs,knownShardsCacheTtlMs:X.knownShardsCacheTtlMs}),W=Y.filter((U)=>U!=="shard_mappings"&&!U.startsWith("sqlite_")&&U!=="sqlite_sequence");for(let U of W.slice(0,3))try{if(((await V.prepare(`SELECT COUNT(*) as count FROM ${U} LIMIT 1`).first())?.count||0)>0){let L=await V.prepare(`SELECT id FROM ${U} LIMIT 1`).first();if(L){let A=String(L.id);if(!await $.getShardMapping(A))return!0}}}catch{continue}return!1}catch{return!1}}function RV(){S.clear()}function zV(V){let J=`${V}_migration_check`;S.delete(J)}var S,VV;var m=a(()=>{C();S=new Map,VV=new Map});C();g();var y=null,u=null,h=new Map;function f(V){if(!u)u=new k(V.kv,{hashShardMappings:V.hashShardMappings,mappingCacheTtlMs:V.mappingCacheTtlMs,knownShardsCacheTtlMs:V.knownShardsCacheTtlMs});return u}function hV(V){y=V,u=new k(V.kv,{hashShardMappings:V.hashShardMappings,mappingCacheTtlMs:V.mappingCacheTtlMs,knownShardsCacheTtlMs:V.knownShardsCacheTtlMs}),h.clear();try{let J=f(V);Promise.resolve().then(async()=>{let X=await J.getKnownShards(),Z=Array.from(new Set([...X,...Object.keys(V.shards)]));await J.setKnownShards(Z)}).catch(()=>{return})}catch{}if(V.shards&&Object.keys(V.shards).length>0&&!V.disableAutoMigration)xV(V).catch((J)=>{console.warn("Background auto-migration failed:",J)})}async function DV(V){y=V,u=new k(V.kv,{hashShardMappings:V.hashShardMappings,mappingCacheTtlMs:V.mappingCacheTtlMs,knownShardsCacheTtlMs:V.knownShardsCacheTtlMs}),h.clear();try{let J=f(V),X=await J.getKnownShards(),Z=Array.from(new Set([...X,...Object.keys(V.shards)]));await J.setKnownShards(Z)}catch{}if(V.shards&&Object.keys(V.shards).length>0&&!V.disableAutoMigration)try{await xV(V)}catch(J){console.warn("Auto migration failed:",J)}}async function gV(V,J){return await DV(V),await J()}async function xV(V){try{let{autoDetectAndMigrate:J}=await Promise.resolve().then(() => (m(),t)),X=Object.keys(V.shards);if(V.debug)console.log(`\uD83D\uDD0D Checking ${X.length} shards for existing data...`);let Z=X.map(async(H)=>{let $=V.shards[H];if(!$)return null;try{let W=await J($,H,V,{maxRecordsToCheck:1000});return{shardName:H,...W}}catch(W){return console.warn(`Auto-migration failed for shard ${H}:`,W),null}}),G=(await Promise.all(Z)).filter((H)=>H?.migrationPerformed);if(V.debug)if(G.length>0){let H=G.reduce(($,W)=>$+(W?.recordsMigrated||0),0);console.log(`\uD83C\uDF89 Auto-migration completed! Migrated ${H} records across ${G.length} shards`),G.forEach(($)=>{if($)console.log(` ✅ ${$.shardName}: ${$.recordsMigrated} records from ${$.tablesProcessed} tables`)})}else console.log("✅ All shards ready - no migration needed")}catch(J){console.warn("Background auto-migration setup failed:",J)}}function mV(){y=null,u=null,h.clear()}function x(){if(!y)throw new O("CollegeDB not initialized. Call initialize() first.","NOT_INITIALIZED");return y}function pV(V){let J=V.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 yV(V,J){let X=V.strategy||"hash";if(typeof X==="string")return X;let Z=X;return Z[J]||Z.write||Z.read||"hash"}function cV(V,J){if(V===J)return 0;let X={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=X[V],Y=X[J],G=Z.lat-Y.lat,H=Z.lon-Y.lon;return Math.sqrt(G*G+H*H)}function dV(V){let J=V.cf;if(!J||!J.country)return"wnam";let{country:X,continent:Z}=J;if(["US","CA","MX"].includes(X)){let Y=J.region||J.regionCode||"",G=J.timezone||"";if(Y.includes("CA")||Y.includes("WA")||Y.includes("OR")||Y.includes("NV")||Y.includes("AZ")||Y.includes("UT")||G.includes("Pacific")||G.includes("America/Los_Angeles"))return"wnam";return"enam"}if(["GL","PM","BM"].includes(X))return"enam";if(["GB","IE","FR","ES","PT","NL","BE","LU","CH","AT","IT"].includes(X))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(X))return"eeur";if(X==="RU")return"eeur";if(["JP","KR","CN","HK","TW","MO","MN","KP"].includes(X))return"apac";if(["TH","VN","SG","MY","ID","PH","BN","KH","LA","MM","TL","IN","PK","BD","LK","NP","BT","MV","AF"].includes(X))return"apac";if(["AU","NZ","PG","FJ","NC","VU","SB","WS","TO","KI","NR","PW","FM","MH","TV"].includes(X))return"oc";if(["AE","SA","QA","KW","BH","OM","YE","IQ","IR","SY","LB","JO","IL","PS","TR","CY"].includes(X))return"me";if(Z==="AF"||["EG","LY","TN","DZ","MA","SD","SS","ET","ER","DJ","SO"].includes(X))return"af";if(["KZ","UZ","TM","TJ","KG"].includes(X))return"eeur";if(Z==="SA"||["BR","AR","CL","PE","CO","VE","EC","BO","PY","UY","GY","SR","GF"].includes(X))return"enam";if(["GT","BZ","SV","HN","NI","CR","PA","CU","JM","HT","DO","PR","TT","BB","GD","VC","LC","DM","AG","KN"].includes(X))return"enam";return"wnam"}function lV(V){if(typeof V==="string")return V;return V.region||"wnam"}async function wV(V){try{let[J,X]=await Promise.all([V.prepare("PRAGMA page_count").first(),V.prepare("PRAGMA page_size").first()]);if(!J?.page_count||!X?.page_size)throw new O("Failed to retrieve database size information","SIZE_QUERY_FAILED");return J.page_count*X.page_size}catch(J){throw new O(`Failed to get database size: ${J instanceof Error?J.message:"Unknown error"}`,"SIZE_QUERY_FAILED")}}async function nV(V,J){let X=Math.max(0,J.sizeCacheTtlMs??30000),Z=h.get(V);if(Z&&Z.expiresAt>=Date.now())return Z.size;let Y=J.shards[V];if(!Y)throw new O(`Shard ${V} not found in configuration`,"SHARD_NOT_FOUND");let G=await wV(Y);if(X>0)h.set(V,{size:G,expiresAt:Date.now()+X});return G}async function oV(V,J){if(typeof J.maxDatabaseSize!=="number"||!Number.isFinite(J.maxDatabaseSize)||J.maxDatabaseSize<=0)return V;let X=J.maxDatabaseSize,Y=(await Promise.allSettled(V.map(async(G)=>{let H=await nV(G,J);return{shard:G,size:H,withinLimit:H<X}}))).filter((G)=>G.status==="fulfilled"&&G.value.withinLimit).map((G)=>G.value.shard);if(Y.length===0){if(J.debug)console.warn("All shards exceed maxDatabaseSize limit. Allowing allocation to prevent failure.");return V}if(J.debug&&Y.length<V.length){let G=V.filter((H)=>!Y.includes(H));console.log(`Excluded ${G.length} shards due to size limits: ${G.join(", ")}`)}return Y}function tV(V,J,X,Z){let Y=J.filter((F)=>X[F]);if(Y.length===0){let F=0;for(let L=0;L<Z.length;L++){let A=Z.charCodeAt(L);F=(F<<5)-F+A,F=F&F}let _=Math.abs(F)%J.length;return J[_]}let G=Y.map((F)=>{let _=X[F],L=cV(V,lV(_)),A=typeof _==="object"?_.priority||1:1,T=L-A*0.1;return{shard:F,score:T,distance:L,priority:A}});G.sort((F,_)=>F.score-_.score);let H=G[0].score,$=G.filter((F)=>Math.abs(F.score-H)<0.01);if($.length===1)return $[0].shard;let W=0;for(let F=0;F<Z.length;F++){let _=Z.charCodeAt(F);W=(W<<5)-W+_,W=W&W}let U=Math.abs(W)%$.length;return $[U].shard}function p(V,J,X,Z){switch(V){case"hash":{let Y=0;for(let H=0;H<J.length;H++){let $=J.charCodeAt(H);Y=(Y<<5)-Y+$,Y=Y&Y}let G=Math.abs(Y)%X.length;return X[G]||X[0]}case"location":{if(!Z.targetRegion)return p("hash",J,X,Z);return tV(Z.targetRegion,X,Z.shardLocations||{},J)}case"random":return X[Math.floor(Math.random()*X.length)]||X[0];default:return p("hash",J,X,Z)}}async function iV(V,J="write"){let X=x(),Z=f(X),Y=await Z.getShardMapping(V);if(Y)return Y.shard;let G=Object.keys(X.shards);if(G.length===0)throw new O("No shards configured","NO_SHARDS");let H=await oV(G,X),$,W=yV(X,J);if(X.coordinator)try{let U=X.coordinator.idFromName("default"),_=await X.coordinator.get(U).fetch("http://coordinator/allocate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({primaryKey:V,strategy:W,operationType:J,targetRegion:X.targetRegion,shardLocations:X.shardLocations,availableShards:H})});if(_.ok)$=(await _.json()).shard;else $=p(W,V,H,X)}catch(U){console.warn("Coordinator allocation failed, falling back to local strategy:",U),$=p(W,V,H,X)}else $=p(W,V,H,X);return await Z.setShardMapping(V,$),$}async function sV(V,J="write"){let X=x(),Z=await iV(V,J),Y=X.shards[Z];if(!Y)throw new O(`Shard ${Z} not found in configuration`,"SHARD_NOT_FOUND");return Y}async function rV(V,J){let{createSchema:X}=await Promise.resolve().then(() => (m(),t));await X(V,J)}async function i(V,J){let X=pV(J);return(await sV(V,X)).prepare(J)}async function aV(V,J,X=[]){let Y=await(await i(V,J)).bind(...X).run();if(!Y.success)throw new O(`Query failed: ${Y.error||"Unknown error"}`,"QUERY_FAILED");return Y}async function eV(V,J,X=[]){let Y=await(await i(V,J)).bind(...X).all();if(!Y.success)throw new O(`Query failed: ${Y.error||"Unknown error"}`,"QUERY_FAILED");return Y}async function VJ(V,J,X=[]){return await(await i(V,J)).bind(...X).first()}async function JJ(V,J,X){let Z=x();if(!Z.shards[J])throw new O(`Shard ${J} not found in configuration`,"SHARD_NOT_FOUND");let Y=f(Z),G=await Y.getShardMapping(V);if(!G)throw new O(`No existing mapping found for primary key: ${V}`,"MAPPING_NOT_FOUND");if(G.shard!==J){let{migrateRecord:H}=await Promise.resolve().then(() => (m(),t)),$=Z.shards[G.shard],W=Z.shards[J];if(!$||!W)throw new O("Source or target shard not available","SHARD_UNAVAILABLE");await H($,W,V,X)}await Y.updateShardMapping(V,J)}async function XJ(){let V=x();if(V.coordinator)try{let J=V.coordinator.idFromName("default"),Z=await V.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 X=await f(V).getKnownShards(),Z=new Set([...Object.keys(V.shards),...X]);return Array.from(Z)}catch{return Object.keys(V.shards)}}async function YJ(){let V=x();if(V.coordinator)try{let Y=V.coordinator.idFromName("default"),H=await V.coordinator.get(Y).fetch("http://coordinator/stats");if(H.ok)return await H.json()}catch(Y){console.warn("Failed to get stats from coordinator:",Y)}let J=f(V),X=await J.getShardKeyCounts(),Z=Object.keys(V.shards);try{let Y=await J.getKnownShards();Z=Array.from(new Set([...Z,...Y]))}catch{}return Z.map((Y)=>({binding:Y,count:X[Y]||0}))}async function ZJ(V,J,X=[]){let Y=x().shards[V];if(!Y)throw new O(`Shard ${V} not found`,"SHARD_NOT_FOUND");let G=await Y.prepare(J).bind(...X).run();if(!G.success)throw new O(`Query failed: ${G.error||"Unknown error"}`,"QUERY_FAILED");return G}async function GJ(V,J,X=[]){let Y=x().shards[V];if(!Y)throw new O(`Shard ${V} not found`,"SHARD_NOT_FOUND");return await Y.prepare(J).bind(...X).all()}async function HJ(V,J,X=[]){let Y=x().shards[V];if(!Y)throw new O(`Shard ${V} not found`,"SHARD_NOT_FOUND");return await Y.prepare(J).bind(...X).first()}async function $J(V,J=[],X=50){let Z=x(),Y=[];for(let[H,$]of Object.entries(Z.shards)){if(!H||!$){console.error(`Shard ${H??"<null>"} not found, skipping`);continue}Y.push(()=>$.prepare(V).bind(...J).run().catch((W)=>{return console.error(`Error executing query on shard ${H}:`,W),{success:!1,results:[],error:W instanceof Error?W.message:String(W),meta:{duration:0}}}))}let G=[];for(let H=0;H<Y.length;H+=X){let $=Y.slice(H,H+X).map((W)=>W());G.push(...await Promise.all($))}return G}async function WJ(V,J=[],X=50){let Z=x(),Y=[];for(let[H,$]of Object.entries(Z.shards)){if(!H||!$){console.error(`Shard ${H??"<null>"} not found, skipping`);continue}Y.push(()=>$.prepare(V).bind(...J).all().catch((W)=>{return console.error(`Error executing query on shard ${H}:`,W),{success:!1,results:[],error:W instanceof Error?W.message:String(W),meta:{duration:0}}}))}let G=[];for(let H=0;H<Y.length;H+=X){let $=Y.slice(H,H+X).map((W)=>W());G.push(...await Promise.all($))}return G}async function FJ(V,J=[],X=50){let Z=x(),Y=[];for(let[H,$]of Object.entries(Z.shards)){if(!H||!$){console.error(`Shard ${H??"<null>"} not found, skipping`);continue}Y.push(()=>$.prepare(V).bind(...J).first().catch((W)=>{return console.error(`Error executing query on shard ${H}:`,W),null}))}let G=[];for(let H=0;H<Y.length;H+=X){let $=Y.slice(H,H+X).map((W)=>W());G.push(...await Promise.all($))}return G}async function UJ(){let V=x();if(await f(V).clearAllMappings(),h.clear(),V.coordinator)try{let X=V.coordinator.idFromName("default");await V.coordinator.get(X).fetch("http://coordinator/flush",{method:"POST"})}catch(X){console.warn("Failed to flush coordinator:",X)}}async function OJ(V){let X=x().shards[V];if(!X)throw new O(`Shard ${V} not found`,"SHARD_NOT_FOUND");return await wV(X)}C();class YV{state;constructor(V){this.state=V}async getState(){return await this.state.storage.get("coordinator_state")||{knownShards:[],shardStats:{},strategy:"round-robin",roundRobinIndex:0}}async saveState(V){await this.state.storage.put("coordinator_state",V)}async fetch(V){let X=new URL(V.url).pathname,Z=V.method;try{switch(`${Z} ${X}`){case"GET /shards":return this.handleListShards();case"POST /shards":return this.handleAddShard(V);case"DELETE /shards":return this.handleRemoveShard(V);case"GET /stats":return this.handleGetStats();case"POST /stats":return this.handleUpdateStats(V);case"POST /allocate":return this.handleAllocateShard(V);case"POST /flush":return this.handleFlush();case"GET /health":return new Response("OK",{status:200});default:return new Response("Not Found",{status:404})}}catch(Y){return console.error("ShardCoordinator error:",Y),new Response("Internal Server Error",{status:500})}}async handleListShards(){let V=await this.getState();return new Response(JSON.stringify(V.knownShards),{headers:{"Content-Type":"application/json"}})}async handleAddShard(V){let{shard:J}=await V.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 X=await this.getState();if(!X.knownShards.includes(J))X.knownShards.push(J),X.shardStats[J]={binding:J,count:0,lastUpdated:Date.now()},await this.saveState(X);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleRemoveShard(V){let{shard:J}=await V.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 X=await this.getState(),Z=X.knownShards.indexOf(J);if(Z>-1){if(X.knownShards.splice(Z,1),delete X.shardStats[J],X.roundRobinIndex>=X.knownShards.length)X.roundRobinIndex=0;await this.saveState(X)}return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleGetStats(){let V=await this.getState(),J=Object.values(V.shardStats);return new Response(JSON.stringify(J),{headers:{"Content-Type":"application/json"}})}async handleUpdateStats(V){let{shard:J,count:X}=await V.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(X===void 0||typeof X!=="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=X,Z.shardStats[J].lastUpdated=Date.now(),await this.saveState(Z);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleAllocateShard(V){let{primaryKey:J,strategy:X,operationType:Z,availableShards:Y}=await V.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 G=await this.getState(),H=Y||G.knownShards;if(H.length===0)return new Response(JSON.stringify({error:"No shards available"}),{status:400,headers:{"Content-Type":"application/json"}});let $=this.resolveStrategy(G.strategy,X,Z||"write"),W=this.selectShard(J,G,$,H);if($==="round-robin")G.roundRobinIndex=(G.roundRobinIndex+1)%H.length,await this.saveState(G);return new Response(JSON.stringify({shard:W}),{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(V,J,X="write"){if(J)return J;if(typeof V==="string")return V;return V[X]}selectShard(V,J,X,Z){let Y=Z||J.knownShards;if(Y.length===0)throw new O("No shards available","NO_SHARDS");switch(X){case"round-robin":return Y[J.roundRobinIndex]??Y[0];case"random":return Y[Math.floor(Math.random()*Y.length)];case"hash":{let G=0;for(let $=0;$<V.length;$++){let W=V.charCodeAt($);G=(G<<5)-G+W,G=G&G}let H=Math.abs(G)%Y.length;return Y[H]}case"location":{let G=J.targetRegion,H=J.shardLocations||{},$=Y.filter((Q)=>H[Q]);if(!G||$.length===0){let Q=0;for(let R=0;R<V.length;R++){let E=V.charCodeAt(R);Q=(Q<<5)-Q+E,Q=Q&Q}let j=Math.abs(Q)%Y.length;return Y[j]}let W={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=(Q,j)=>(j in Q),F=(Q)=>U(W,Q)?Q:"wnam",_=(Q,j)=>{let R=W[F(Q)],E=W[F(j)],P=R.lat-E.lat,I=R.lon-E.lon;return Math.sqrt(P*P+I*I)},L=$.map((Q)=>{let j=H[Q],R=_(G,j.region),E=j.priority||1;return{shard:Q,score:R-E*0.1}});L.sort((Q,j)=>Q.score-j.score);let A=L[0].score,T=L.filter((Q)=>Math.abs(Q.score-A)<0.01);if(T.length===1)return T[0].shard;let z=0;for(let Q=0;Q<V.length;Q++){let j=V.charCodeAt(Q);z=(z<<5)-z+j,z=z&z}let q=Math.abs(z)%T.length;return T[q].shard}default:return Y[0]}}async incrementShardCount(V){let J=await this.getState();if(J.shardStats[V])J.shardStats[V].count++,J.shardStats[V].lastUpdated=Date.now(),await this.saveState(J)}async decrementShardCount(V){let J=await this.getState();if(J.shardStats[V]&&J.shardStats[V].count>0)J.shardStats[V].count--,J.shardStats[V].lastUpdated=Date.now(),await this.saveState(J)}}if(typeof global<"u"){class V{data=new Map;async get(Z){return this.data.get(Z)}async put(Z,Y){this.data.set(Z,Y)}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 Y=new Map;for(let[G,H]of this.data.entries())if(G.startsWith(Z.prefix))Y.set(G,H);return Y}}class J{storage;constructor(){this.storage=new V}}class X{coordinator;mockState;constructor(){this.mockState=new J,this.coordinator=new YV(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 Y=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"user-1",strategy:"round-robin"})}))).json(),H=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"user-2",strategy:"round-robin"})}))).json();console.assert(Y.shard!==H.shard,"Round-robin should alternate shards");let W=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"consistent-key",strategy:"hash"})}))).json(),F=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"consistent-key",strategy:"hash"})}))).json();console.assert(W.shard===F.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 Y=await(await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"}))).json();console.assert(Y.length===1,"Should have one shard stat"),console.assert(Y[0]?.binding==="db-stats-test","Should have correct binding name"),console.assert(Y[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 Y=await this.coordinator.fetch(new Request("http://test/invalid",{method:"GET"}));console.assert(Y.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"})),Y=await Z.json(),G=Y.find(($)=>$.binding==="db-count-test");console.assert(G?.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"})),Y=await Z.json();let H=Y.find(($)=>$.binding==="db-count-test");console.assert(H?.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 X}C();g();C();var _J=500;function qV(V,J={}){let X=J.scanCount??_J;return{async get(Z,Y="text"){let G=await V.get(Z);if(G===null)return null;if(Y!=="json")return G;try{return JSON.parse(G)}catch(H){throw new O(`Failed to parse JSON from Redis for key ${Z}: ${H instanceof Error?H.message:String(H)}`,"KV_JSON_PARSE_FAILED")}},async put(Z,Y){await V.set(Z,Y)},async delete(Z){await V.del(Z)},async list(Z){let Y=Z?.prefix??"",G=`${Y}*`,H=Z?.cursor??"0",$=Z?.limit,W=[];do{let U=await TJ(V,H,G,X);H=U.cursor;for(let F of U.keys){if(!Y||F.startsWith(Y))W.push(F);if($&&W.length>=$)break}if($&&W.length>=$)break}while(H!=="0");return{keys:W.map((U)=>({name:U})),cursor:H,list_complete:H==="0"}}}}function LJ(V,J={}){return qV(V,J)}function vV(V){return{prepare(J){return new $V(V,J)}}}function MV(V){return{prepare(J){return new WV(V,J)}}}function QJ(V){return{prepare(J){return new FV(V,J)}}}function jJ(V,J){return vV({query:async(Z,Y=[])=>{let G=J(V.connectionString);if(typeof G.connect==="function")await G.connect();try{return await G.query(Z,Y)}finally{if(typeof G.release==="function")G.release();else if(typeof G.end==="function")await G.end()}}})}function AJ(V,J){return MV({execute:async(Z,Y=[])=>{let G=J(V.connectionString);try{if(typeof G.execute==="function")return await G.execute(Z,Y);if(typeof G.query==="function")return await G.query(Z,Y);throw new O("Hyperdrive MySQL client is missing execute/query methods","MYSQL_CLIENT_INVALID")}finally{if(typeof G.end==="function")await G.end();else if(typeof G.close==="function")await G.close();else if(typeof G.destroy==="function")G.destroy()}}})}function IJ(V){if(!V||typeof V!=="object")return!1;return typeof V.prepare==="function"}function PJ(V){if(!V||typeof V!=="object")return!1;let J=V;return typeof J.get==="function"&&typeof J.put==="function"&&typeof J.delete==="function"&&typeof J.list==="function"}class $V{client;sql;bindings;constructor(V,J,X=[]){this.client=V,this.sql=J,this.bindings=X}bind(...V){return new $V(this.client,this.sql,V)}async run(){let V=Date.now(),J=HV(this.sql),X=await this.client.query(J,this.bindings);return{success:!0,results:X.rows??[],meta:M(V,{changes:typeof X.rowCount==="number"?X.rowCount:void 0,command:X.command})}}async all(){let V=Date.now(),J=HV(this.sql),X=await this.client.query(J,this.bindings);return{success:!0,results:X.rows??[],meta:M(V,{changes:typeof X.rowCount==="number"?X.rowCount:void 0,command:X.command})}}async first(){let V=HV(this.sql);return(await this.client.query(V,this.bindings)).rows?.[0]??null}}class WV{client;sql;bindings;constructor(V,J,X=[]){this.client=V,this.sql=J,this.bindings=X}bind(...V){return new WV(this.client,this.sql,V)}async run(){let V=Date.now(),J=await ZV(this.client,this.sql,this.bindings);if(Array.isArray(J))return{success:!0,results:J,meta:M(V)};let X=J;return{success:!0,results:[],meta:M(V,{changes:X.affectedRows,last_row_id:X.insertId,warningStatus:X.warningStatus})}}async all(){let V=Date.now(),J=await ZV(this.client,this.sql,this.bindings);return{success:!0,results:Array.isArray(J)?J:[],meta:M(V,{changes:!Array.isArray(J)?J.affectedRows:void 0})}}async first(){let V=await ZV(this.client,this.sql,this.bindings);if(!Array.isArray(V)||V.length===0)return null;return V[0]}}class FV{client;sql;bindings;constructor(V,J,X=[]){this.client=V,this.sql=J,this.bindings=X}bind(...V){return new FV(this.client,this.sql,V)}async run(){let V=Date.now();if(typeof this.client.execute==="function"){let Y=await this.client.execute(this.sql,this.bindings);return{success:!0,results:GV(Y),meta:M(V)}}let J=this.client.prepare?.(this.sql);if(!J||typeof J.run!=="function")throw new O("SQLite client must expose execute() or prepare().run()","SQLITE_CLIENT_INVALID");let Z=await J.run(...this.bindings)??{};return{success:!0,results:[],meta:M(V,{changes:EJ(Z.changes),last_row_id:Z.lastInsertRowid??Z.lastID})}}async all(){let V=Date.now();if(typeof this.client.execute==="function"){let Z=await this.client.execute(this.sql,this.bindings);return{success:!0,results:GV(Z),meta:M(V)}}let J=this.client.prepare?.(this.sql);if(!J||typeof J.all!=="function")throw new O("SQLite client must expose execute() or prepare().all()","SQLITE_CLIENT_INVALID");let X=await J.all(...this.bindings);return{success:!0,results:Array.isArray(X)?X:[],meta:M(V)}}async first(){if(typeof this.client.execute==="function"){let J=await this.client.execute(this.sql,this.bindings);return GV(J)[0]??null}let V=this.client.prepare?.(this.sql);if(!V)throw new O("SQLite client must expose execute() or prepare().get()","SQLITE_CLIENT_INVALID");if(typeof V.get==="function"){let J=await V.get(...this.bindings);return J===void 0||J===null?null:J}if(typeof V.all==="function"){let J=await V.all(...this.bindings);if(!Array.isArray(J)||J.length===0)return null;let X=J[0];return X===void 0||X===null?null:X}throw new O("SQLite prepare() result must expose get() or all()","SQLITE_CLIENT_INVALID")}}async function TJ(V,J,X,Z){try{let Y=await V.scan(J,{MATCH:X,COUNT:Z});return BV(Y)}catch{let Y=await V.scan(J,"MATCH",X,"COUNT",String(Z));return BV(Y)}}function BV(V){if(Array.isArray(V))return{cursor:String(V[0]??"0"),keys:Array.isArray(V[1])?V[1]:[]};return{cursor:String(V.cursor??"0"),keys:Array.isArray(V.keys)?V.keys:[]}}async function ZV(V,J,X){if(typeof V.execute==="function"){let[Z]=await V.execute(J,X);return Z}if(typeof V.query==="function"){let[Z]=await V.query(J,X);return Z}throw new O("MySQL client must expose execute() or query()","MYSQL_CLIENT_INVALID")}function GV(V){if(Array.isArray(V))return V;if(V&&typeof V==="object"){let J=V;if(Array.isArray(J.rows))return J.rows;if(Array.isArray(J.results))return J.results}return[]}function M(V,J={}){return{duration:Date.now()-V,...J}}function EJ(V){if(typeof V==="number"&&Number.isFinite(V))return V;return}var c=new Map;function HV(V){let J=c.get(V);if(J)return J;let X="",Z=0,Y=!1,G=!1,H=!1,$=!1;for(let W=0;W<V.length;W++){let U=V[W],F=W+1<V.length?V[W+1]:"";if(H){if(X+=U,U===`
|
|
17
|
+
`)H=!1;continue}if($){if(X+=U,U==="*"&&F==="/")X+="/",W++,$=!1;continue}if(!Y&&!G){if(U==="-"&&F==="-"){X+="--",W++,H=!0;continue}if(U==="/"&&F==="*"){X+="/*",W++,$=!0;continue}}if(U==="'"&&!G){Y=!Y,X+=U;continue}if(U==='"'&&!Y){G=!G,X+=U;continue}if(U==="?"&&!Y&&!G){Z++,X+=`$${Z}`;continue}X+=U}if(c.set(V,X),c.size>5000){let W=c.keys().next().value;if(W)c.delete(W)}return X}m();export{o as validateTableForSharding,XV as schemaExists,ZJ as runShard,$J as runAllShards,aV as run,mV as resetConfig,JJ as reassignShard,i as prepare,AV as migrateRecord,b as listTables,XJ as listKnownShards,IJ as isSQLDatabase,PJ as isKVStorage,PV as integrateExistingDatabase,DV as initializeAsync,hV as initialize,YJ as getShardStats,OJ as getDatabaseSizeForShard,dV as getClosestRegionFromIP,UJ as flush,HJ as firstShard,FJ as firstAllShards,VJ as first,jV as dropSchema,n as discoverExistingRecordsWithColumns,l as discoverExistingPrimaryKeys,LJ as createValkeyKVProvider,QV as createSchemaAcrossShards,rV as createSchema,QJ as createSQLiteSQLProvider,qV as createRedisKVProvider,vV as createPostgresSQLProvider,MV as createMySQLSQLProvider,IV as createMappingsForExistingKeys,jJ as createHyperdrivePostgresProvider,AJ as createHyperdriveMySQLProvider,gV as collegedb,zV as clearShardMigrationCache,RV as clearMigrationCache,EV as checkMigrationNeeded,TV as autoDetectAndMigrate,GJ as allShard,WJ as allAllShards,eV as all,YV as ShardCoordinator,k as KVShardMapper,O as CollegeDBError};
|
|
17
18
|
|
|
18
|
-
//# debugId=
|
|
19
|
+
//# debugId=72CC370844D168E064756E2164756E21
|
|
19
20
|
//# sourceMappingURL=index.js.map
|