@earth-app/collegedb 1.0.3 → 1.0.5
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 +29 -26
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +5 -5
- package/dist/migrations.d.ts +41 -2
- package/dist/migrations.d.ts.map +1 -1
- package/dist/router.d.ts +39 -0
- package/dist/router.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -531,35 +531,38 @@ for (const [table, pkColumn] of Object.entries(customIntegration)) {
|
|
|
531
531
|
|
|
532
532
|
## 📚 API Reference
|
|
533
533
|
|
|
534
|
-
| Function
|
|
535
|
-
|
|
|
536
|
-
| `collegedb(config, callback)`
|
|
537
|
-
| `initialize(config)`
|
|
538
|
-
| `createSchema(d1)`
|
|
539
|
-
| `prepare(key, sql)`
|
|
540
|
-
| `run(key, sql, bindings)`
|
|
541
|
-
| `first(key, sql, bindings)`
|
|
542
|
-
| `all(key, sql, bindings)`
|
|
543
|
-
| `runShard(shard, sql, bindings)`
|
|
544
|
-
| `allShard(shard, sql, bindings)`
|
|
545
|
-
| `firstShard(shard, sql, bindings)`
|
|
546
|
-
| `
|
|
547
|
-
| `
|
|
548
|
-
| `
|
|
549
|
-
| `
|
|
534
|
+
| Function | Description | Parameters |
|
|
535
|
+
| ------------------------------------------ | ---------------------------------------------------------------- | -------------------------- |
|
|
536
|
+
| `collegedb(config, callback)` | Initialize CollegeDB, then run a callback | `CollegeDBConfig, () => T` |
|
|
537
|
+
| `initialize(config)` | Initialize CollegeDB with configuration | `CollegeDBConfig` |
|
|
538
|
+
| `createSchema(d1)` | Create database schema on a D1 instance | `D1Database` |
|
|
539
|
+
| `prepare(key, sql)` | Prepare a SQL statement for execution | `string, string` |
|
|
540
|
+
| `run(key, sql, bindings)` | Execute a SQL query with primary key routing | `string, string, any[]` |
|
|
541
|
+
| `first(key, sql, bindings)` | Execute a SQL query and return first result | `string, string, any[]` |
|
|
542
|
+
| `all(key, sql, bindings)` | Execute a SQL query and return all results | `string, string, any[]` |
|
|
543
|
+
| `runShard(shard, sql, bindings)` | Execute a query directly on a specific shard | `string, string, any[]` |
|
|
544
|
+
| `allShard(shard, sql, bindings)` | Execute a query on specific shard, return all results | `string, string, any[]` |
|
|
545
|
+
| `firstShard(shard, sql, bindings)` | Execute a query on specific shard, return first result | `string, string, any[]` |
|
|
546
|
+
| `runAllShards(sql, bindings, batchSize)` | Execute query on all shards | `string, any[], number` |
|
|
547
|
+
| `allAllShards(sql, bindings, batchSize)` | Execute query on all shards, return all results from all shards | `string, any[], number` |
|
|
548
|
+
| `firstAllShards(sql, bindings, batchSize)` | Execute query on all shards, return first result from all shards | `string, any[], number` |
|
|
549
|
+
| `reassignShard(key, newShard)` | Move primary key to different shard | `string, string` |
|
|
550
|
+
| `listKnownShards()` | Get list of available shards | `void` |
|
|
551
|
+
| `getShardStats()` | Get statistics for all shards | `void` |
|
|
552
|
+
| `flush()` | Clear all shard mappings (development only) | `void` |
|
|
550
553
|
|
|
551
554
|
### Drop-in Replacement Functions
|
|
552
555
|
|
|
553
|
-
| Function | Description
|
|
554
|
-
| ----------------------------------------- |
|
|
555
|
-
| `autoDetectAndMigrate(d1, shard, config)` |
|
|
556
|
-
| `checkMigrationNeeded(d1, shard, config)` |
|
|
557
|
-
| `validateTableForSharding(d1, table)` | Check if table is suitable for sharding
|
|
558
|
-
| `discoverExistingPrimaryKeys(d1, table)` | Find all primary keys in existing table
|
|
559
|
-
| `integrateExistingDatabase(d1, shard)` | Complete drop-in integration of existing DB
|
|
560
|
-
| `createMappingsForExistingKeys(keys)` | Create shard mappings for existing keys
|
|
561
|
-
| `listTables(d1)` | Get list of tables in database
|
|
562
|
-
| `clearMigrationCache()` | Clear automatic migration cache
|
|
556
|
+
| Function | Description | Parameters |
|
|
557
|
+
| ----------------------------------------- | ---------------------------------------------- | ------------------------------ |
|
|
558
|
+
| `autoDetectAndMigrate(d1, shard, config)` | Automatically detect and migrate existing data | `D1Database, string, config` |
|
|
559
|
+
| `checkMigrationNeeded(d1, shard, config)` | Check if database needs migration | `D1Database, string, config` |
|
|
560
|
+
| `validateTableForSharding(d1, table)` | Check if table is suitable for sharding | `D1Database, string` |
|
|
561
|
+
| `discoverExistingPrimaryKeys(d1, table)` | Find all primary keys in existing table | `D1Database, string` |
|
|
562
|
+
| `integrateExistingDatabase(d1, shard)` | Complete drop-in integration of existing DB | `D1Database, string, mapper` |
|
|
563
|
+
| `createMappingsForExistingKeys(keys)` | Create shard mappings for existing keys | `string[], string[], strategy` |
|
|
564
|
+
| `listTables(d1)` | Get list of tables in database | `D1Database` |
|
|
565
|
+
| `clearMigrationCache()` | Clear automatic migration cache | `void` |
|
|
563
566
|
|
|
564
567
|
### Error Handling
|
|
565
568
|
|
package/dist/index.d.ts
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
* @author Gregory Mitchell
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
export { all, allShard, collegedb, createSchema, first, firstShard, flush, getClosestRegionFromIP, getShardStats, initialize, initializeAsync, listKnownShards, prepare, reassignShard, resetConfig, run, runShard } from './router.js';
|
|
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';
|
|
12
12
|
export { ShardCoordinator } from './durable.js';
|
|
13
13
|
export { CollegeDBError } from './errors.js';
|
|
14
14
|
export { KVShardMapper } from './kvmap.js';
|
|
15
|
-
export { autoDetectAndMigrate, checkMigrationNeeded, clearMigrationCache, clearShardMigrationCache, createMappingsForExistingKeys, createSchemaAcrossShards, discoverExistingPrimaryKeys, dropSchema, integrateExistingDatabase, listTables, migrateRecord, schemaExists, validateTableForSharding, type IntegrationOptions, type IntegrationResult, type ValidationResult } from './migrations.js';
|
|
15
|
+
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
16
|
export type { CollegeDBConfig, D1Region, Env, MixedShardingStrategy, OperationType, ShardCoordinatorState, ShardLocation, ShardMapping, ShardStats, ShardingStrategy } from './types.js';
|
|
17
17
|
//# 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,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,KAAK,EACL,UAAU,EACV,KAAK,EACL,sBAAsB,EACtB,aAAa,EACb,UAAU,EACV,eAAe,EACf,eAAe,EACf,OAAO,EACP,aAAa,EACb,WAAW,EACX,GAAG,EACH,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,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,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"}
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
var
|
|
1
|
+
var jJ=Object.defineProperty;var i=(J,Z)=>{for(var Q in Z)jJ(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 G;var C=y(()=>{G=class G extends Error{code;constructor(J,Z){super(J);if(this.name="CollegeDBError",this.code=Z,Error.captureStackTrace)Error.captureStackTrace(this,G)}}});var l={};i(l,{KVShardMapper:()=>E});class E{kv;hashKeys;constructor(J,Z={}){this.kv=J,this.hashKeys=Z.hashShardMappings??!0}async hashKey(J){if(!this.hashKeys)return J;let Q=new TextEncoder().encode(J),V=await crypto.subtle.digest("SHA-256",Q),$=new Uint8Array(V);return Array.from($).map((O)=>O.toString(16).padStart(2,"0")).join("")}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(`${B}${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}`,z={shard:Z,createdAt:$,updatedAt:$,originalKey:this.hashKeys?void 0:J};await this.kv.put(O,JSON.stringify(z))}else{let W=await this.hashKey(J),O=`${B}${W}`,z={shard:Z,createdAt:$,updatedAt:$,keys:this.hashKeys?[]:V};await this.kv.put(O,JSON.stringify(z));let U=V.map(async(j)=>{let Y=await this.hashKey(j),x=`${w}${Y}`,F={shard:Z,createdAt:$,updatedAt:$,originalKey:this.hashKeys?void 0:j};return this.kv.put(x,JSON.stringify(F))});await Promise.all(U)}}async updateShardMapping(J,Z){let Q=await this.getShardMapping(J);if(!Q)throw new G(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");let V=await this.hashKey(J),$=`${w}${V}`,W=`${B}${V}`,O=await this.kv.get(W,"json");if(O){let z={...O,shard:Z,updatedAt:Date.now()};await this.kv.put(W,JSON.stringify(z));let U=O.keys.map(async(j)=>{let Y=await this.hashKey(j),x=`${w}${Y}`,F={...Q,shard:Z,updatedAt:Date.now()};return this.kv.put(x,JSON.stringify(F))});await Promise.all(U)}else{let z={...Q,shard:Z,updatedAt:Date.now()};await this.kv.put($,JSON.stringify(z))}}async deleteShardMapping(J){let Z=await this.hashKey(J),Q=`${w}${Z}`,V=`${B}${Z}`,$=await this.kv.get(V,"json");if($){await this.kv.delete(V);let W=$.keys.map(async(O)=>{let z=await this.hashKey(O),U=`${w}${z}`;return this.kv.delete(U)});await Promise.all(W)}else await this.kv.delete(Q)}async getKnownShards(){return await this.kv.get(s,"json")||[]}async setKnownShards(J){if(!J||J.length===0)return;await this.kv.put(s,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:B});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:B});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:B})).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 G(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");let V=await this.hashKey(J),$=`${B}${V}`,W=await this.kv.get($,"json"),O=[J,...Z],z=Date.now();if(!W)W={shard:Q.shard,createdAt:Q.createdAt,updatedAt:z,keys:this.hashKeys?[]:O};else W={...W,updatedAt:z,keys:this.hashKeys?[]:[...new Set([...W.keys,...O])]};await this.kv.put($,JSON.stringify(W));let U=Z.map(async(j)=>{let Y=await this.hashKey(j),x=`${w}${Y}`,F={shard:Q.shard,createdAt:Q.createdAt,updatedAt:z,originalKey:this.hashKeys?void 0:j};return this.kv.put(x,JSON.stringify(F))});await Promise.all(U)}async getAllLookupKeys(J){let Z=await this.hashKey(J),Q=`${B}${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 G(`No mapping found for key: ${J}`,"MAPPING_NOT_FOUND")}}var w="shard:",B="multikey:",s="known_shards";var f=y(()=>{C()});var b={};i(b,{validateTableForSharding:()=>h,schemaExists:()=>n,migrateRecord:()=>e,listTables:()=>k,integrateExistingDatabase:()=>ZJ,dropSchema:()=>a,discoverExistingRecordsWithColumns:()=>g,discoverExistingPrimaryKeys:()=>c,createSchemaAcrossShards:()=>r,createSchema:()=>d,createMappingsForExistingKeys:()=>JJ,clearShardMigrationCache:()=>WJ,clearMigrationCache:()=>VJ,checkMigrationNeeded:()=>QJ,autoDetectAndMigrate:()=>$J});async function d(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 G(`Schema migration failed: ${$}`,"SCHEMA_MIGRATION_FAILED")}}async function r(J,Z){let Q=Object.entries(J).map(([V,$])=>{return d($,Z).catch((W)=>{throw new G(`Failed to create schema on shard ${V}: ${W.message}`,"SCHEMA_CREATION_FAILED")})});await Promise.all(Q)}async function n(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 a(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 k(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 e(J,Z,Q,V){let $=await J.prepare(`SELECT * FROM ${V} WHERE id = ?`).bind(Q).first();if(!$)throw new G(`Record with primary key ${Q} not found in source database`,"RECORD_NOT_FOUND");if(!await n(Z,V))await d(Z,V);let W=Object.keys($),O=W.map(()=>"?").join(", "),z=W.map((j)=>$[j]),U=`INSERT OR REPLACE INTO ${V} (${W.join(", ")}) VALUES (${O})`;await Z.prepare(U).bind(...z).run(),await J.prepare(`DELETE FROM ${V} WHERE id = ?`).bind(Q).run()}async function c(J,Z,Q="id"){try{return(await J.prepare(`SELECT ${Q} FROM ${Z}`).all()).results.map(($)=>String($[Q]))}catch(V){throw new G(`Failed to discover primary keys in table ${Z}: ${V}`,"DISCOVERY_FAILED")}}async function g(J,Z,Q="id"){try{let $=(await J.prepare(`PRAGMA table_info(${Z})`).all()).results.map((U)=>U.name),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 G(`Failed to discover records with columns in table ${Z}: ${V}`,"DISCOVERY_FAILED")}}async function JJ(J,Z,Q,V){let $=Z.length;for(let W=0;W<J.length;W++){let O=J[W],z;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 j=Math.abs(U)%$;z=Z[j];break;case"random":z=Z[Math.floor(Math.random()*$)];break;default:z=Z[W%$];break}await V.setShardMapping(O,z)}}async function h(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((j)=>j.name===Q&&j.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 ZJ(J,Z,Q,V={}){let{tables:$,primaryKeyColumn:W="id",strategy:O="hash",addShardMappingsTable:z=!0,dryRun:U=!1,migrateOtherColumns:j=!1}=V,Y=[],x=0,F=0,H=0;try{let S=($||await k(J)).filter((X)=>X!=="shard_mappings");for(let X of S)try{let I=await h(J,X,W);if(!I.isValid){Y.push(`Table ${X}: ${I.issues.join(", ")}`);continue}if(j){let v=await g(J,X,W);if(v.length===0){Y.push(`Table ${X} has no records to process`);continue}if(!U)for(let L of v){let R=String(L[W]),P=[];if(L.username&&typeof L.username==="string")P.push(`username:${L.username}`);if(L.email&&typeof L.email==="string")P.push(`email:${L.email}`);if(L.name&&typeof L.name==="string")P.push(`name:${L.name}`);await Q.setShardMapping(R,Z,P),H++}F+=v.length}else{let v=await c(J,X,W);if(v.length===0){Y.push(`Table ${X} has no records to process`);continue}if(!U)for(let L of v)await Q.setShardMapping(L,Z),H++;F+=v.length}x++}catch(I){Y.push(`Failed to process table ${X}: ${I}`)}if(z&&!U){if(!(await k(J)).includes("shard_mappings"))await J.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(!U)await Q.addKnownShard(Z)}catch(D){Y.push(`Integration failed: ${D}`)}return{success:Y.length===0||Y.length>0&&x>0,shardName:Z,tablesProcessed:x,totalRecords:F,mappingsCreated:H,issues:Y}}async function $J(J,Z,Q,V={}){let{primaryKeyColumn:$="id",tablesToCheck:W,skipCache:O=!1,maxRecordsToCheck:z=1000,migrateOtherColumns:U=!1}=V,j=`${Z}_migration_check`;if(!O&&q.has(j))return{migrationNeeded:!1,migrationPerformed:!1,recordsMigrated:0,tablesProcessed:0,issues:[]};let Y=[],x=0,F=0,H=!1,D=!1;try{let{KVShardMapper:S}=await Promise.resolve().then(() => (f(),l)),X=new S(Q.kv,{hashShardMappings:Q.hashShardMappings}),I=await k(J),v=W||I.filter((L)=>L!=="shard_mappings"&&!L.startsWith("sqlite_")&&L!=="sqlite_sequence");if(v.length===0)return q.set(j,!0),{migrationNeeded:!1,migrationPerformed:!1,recordsMigrated:0,tablesProcessed:0,issues:[]};for(let L of v)try{let R=await h(J,L,$);if(!R.isValid||R.recordCount===0)continue;let P=Math.min(z,R.recordCount),YJ=await J.prepare(`
|
|
8
|
+
SELECT ${$} FROM ${L}
|
|
9
|
+
ORDER BY ${$}
|
|
10
|
+
LIMIT ?`.trim()).bind(P).all(),t=0,zJ=YJ.results.slice(0,10);for(let N of zJ){let _=String(N[$]);if(!await X.getShardMapping(_))t++,H=!0}if(t>0){if(console.log(`Auto-migrating table ${L} in shard ${Z} (${R.recordCount} records)`),U){let N=await g(J,L,$),_=0;for(let T of N){let m=String(T[$]);if(!await X.getShardMapping(m)){let K=[];if(T.username&&typeof T.username==="string")K.push(`username:${T.username}`);if(T.email&&typeof T.email==="string")K.push(`email:${T.email}`);if(T.name&&typeof T.name==="string")K.push(`name:${T.name}`);await X.setShardMapping(m,Z,K),_++}}x+=_}else{let N=await c(J,L,$),_=0;for(let T of N)if(!await X.getShardMapping(T))await X.setShardMapping(T,Z),_++;x+=_}F++,D=!0,console.log(`Auto-migrated ${x} records from table ${L}`)}}catch(R){Y.push(`Auto-migration failed for table ${L}: ${R}`)}if(D){if(await X.addKnownShard(Z),!I.includes("shard_mappings"))await J.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(B.set(O,!0),X)console.log(`Auto-migration completed for shard ${Q}: ${U} records from ${x} tables`)}catch(D){j.push(`Auto-migration error: ${D}`)}return{migrationNeeded:G,migrationPerformed:X,recordsMigrated:U,tablesProcessed:x,issues:j}}async function a(J,Q,Z){let $=`${Q}_migration_check`;if(B.has($))return!1;try{let z=await _(J);if(z.includes("shard_mappings"))return B.set($,!0),!1;let{KVShardMapper:V}=await Promise.resolve().then(() => (k(),g)),Y=new V(Z.kv,{hashShardMappings:Z.hashShardMappings}),O=z.filter((j)=>j!=="shard_mappings"&&!j.startsWith("sqlite_")&&j!=="sqlite_sequence");for(let j of O.slice(0,3))try{if(((await J.prepare(`SELECT COUNT(*) as count FROM ${j} LIMIT 1`).first())?.count||0)>0){let G=await J.prepare(`SELECT id FROM ${j} LIMIT 1`).first();if(G){let X=String(G.id);if(!await Y.getShardMapping(X))return!0}}}catch{continue}return!1}catch{return!1}}function e(){B.clear()}function JJ(J){let Q=`${J}_migration_check`;B.delete(Q)}var B;var C=c(()=>{I();B=new Map});I();k();var M=null;function OJ(J){if(M=J,J.shards&&Object.keys(J.shards).length>0&&!J.disableAutoMigration)ZJ(J).catch((Q)=>{console.warn("Background auto-migration failed:",Q)})}async function QJ(J){if(M=J,J.shards&&Object.keys(J.shards).length>0&&!J.disableAutoMigration)try{await ZJ(J)}catch(Q){console.warn("Auto migration failed:",Q)}}async function UJ(J,Q){return await QJ(J),await Q()}async function ZJ(J){try{let{autoDetectAndMigrate:Q}=await Promise.resolve().then(() => (C(),S)),Z=Object.keys(J.shards);console.log(`\uD83D\uDD0D Checking ${Z.length} shards for existing data...`);let $=Z.map(async(V)=>{let Y=J.shards[V];if(!Y)return null;try{let O=await Q(Y,V,J,{maxRecordsToCheck:1000});return{shardName:V,...O}}catch(O){return console.warn(`Auto-migration failed for shard ${V}:`,O),null}}),W=(await Promise.all($)).filter((V)=>V?.migrationPerformed);if(W.length>0){let V=W.reduce((Y,O)=>Y+(O?.recordsMigrated||0),0);console.log(`\uD83C\uDF89 Auto-migration completed! Migrated ${V} records across ${W.length} shards`),W.forEach((Y)=>{if(Y)console.log(` ✅ ${Y.shardName}: ${Y.recordsMigrated} records from ${Y.tablesProcessed} tables`)})}else console.log("✅ All shards ready - no migration needed")}catch(Q){console.warn("Background auto-migration setup failed:",Q)}}function YJ(){M=null}function A(){if(!M)throw new L("CollegeDB not initialized. Call initialize() first.","NOT_INITIALIZED");return M}function jJ(J){let Q=J.trim().toUpperCase();if(Q.startsWith("SELECT")||Q.startsWith("VALUES")||Q.startsWith("TABLE")||Q.startsWith("PRAGMA")||Q.startsWith("EXPLAIN")||Q.startsWith("WITH")||Q.startsWith("SHOW"))return"read";return"write"}function xJ(J,Q){let Z=J.strategy||"hash";if(typeof Z==="string")return Z;return Z[Q]}function GJ(J,Q){if(J===Q)return 0;let Z={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[J],z=Z[Q],W=$.lat-z.lat,V=$.lon-z.lon;return Math.sqrt(W*W+V*V)}function LJ(J){let Q=J.cf;if(!Q||!Q.country)return"wnam";let{country:Z,continent:$}=Q;if(["US","CA","MX"].includes(Z)){let z=Q.region||Q.regionCode||"",W=Q.timezone||"";if(z.includes("CA")||z.includes("WA")||z.includes("OR")||z.includes("NV")||z.includes("AZ")||z.includes("UT")||W.includes("Pacific")||W.includes("America/Los_Angeles"))return"wnam";return"enam"}if(["GL","PM","BM"].includes(Z))return"enam";if(["GB","IE","FR","ES","PT","NL","BE","LU","CH","AT","IT"].includes(Z))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(Z))return"eeur";if(Z==="RU")return"eeur";if(["JP","KR","CN","HK","TW","MO","MN","KP"].includes(Z))return"apac";if(["TH","VN","SG","MY","ID","PH","BN","KH","LA","MM","TL","IN","PK","BD","LK","NP","BT","MV","AF"].includes(Z))return"apac";if(["AU","NZ","PG","FJ","NC","VU","SB","WS","TO","KI","NR","PW","FM","MH","TV"].includes(Z))return"oc";if(["AE","SA","QA","KW","BH","OM","YE","IQ","IR","SY","LB","JO","IL","PS","TR","CY"].includes(Z))return"me";if($==="AF"||["EG","LY","TN","DZ","MA","SD","SS","ET","ER","DJ","SO"].includes(Z))return"af";if(["KZ","UZ","TM","TJ","KG"].includes(Z))return"eeur";if($==="SA"||["BR","AR","CL","PE","CO","VE","EC","BO","PY","UY","GY","SR","GF"].includes(Z))return"enam";if(["GT","BZ","SV","HN","NI","CR","PA","CU","JM","HT","DO","PR","TT","BB","GD","VC","LC","DM","AG","KN"].includes(Z))return"enam";return"wnam"}function XJ(J,Q,Z,$){let z=Q.filter((U)=>Z[U]);if(z.length===0){let U=0;for(let G=0;G<$.length;G++){let X=$.charCodeAt(G);U=(U<<5)-U+X,U=U&U}let x=Math.abs(U)%Q.length;return Q[x]}let W=z.map((U)=>{let x=Z[U],G=GJ(J,x.region),X=x.priority||1,D=G-X*0.1;return{shard:U,score:D,distance:G,priority:X}});W.sort((U,x)=>U.score-x.score);let V=W[0].score,Y=W.filter((U)=>Math.abs(U.score-V)<0.01);if(Y.length===1)return Y[0].shard;let O=0;for(let U=0;U<$.length;U++){let x=$.charCodeAt(U);O=(O<<5)-O+x,O=O&O}let j=Math.abs(O)%Y.length;return Y[j].shard}async function FJ(J,Q="write"){let Z=A(),$=new q(Z.kv,{hashShardMappings:Z.hashShardMappings}),z=await $.getShardMapping(J);if(z)return z.shard;let W=Object.keys(Z.shards);if(W.length===0)throw new L("No shards configured","NO_SHARDS");for(let O of W){let j=Z.shards[O];if(!j)continue;try{let{autoDetectAndMigrate:U}=await Promise.resolve().then(() => (C(),S));if((await U(j,O,Z,{maxRecordsToCheck:100})).migrationPerformed){let G=await $.getShardMapping(J);if(G)return G.shard}}catch(U){console.warn(`Auto-migration check failed for shard ${O}:`,U)}}let V,Y=xJ(Z,Q);if(Z.coordinator)try{let O=Z.coordinator.idFromName("default"),U=await Z.coordinator.get(O).fetch("http://coordinator/allocate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({primaryKey:J,strategy:Y,operationType:Q,targetRegion:Z.targetRegion,shardLocations:Z.shardLocations})});if(U.ok)V=(await U.json()).shard;else V=W[Math.floor(Math.random()*W.length)]}catch(O){console.warn("Coordinator allocation failed, falling back to local strategy:",O),V=W[Math.floor(Math.random()*W.length)]}else switch(Y){case"hash":let O=0;for(let U=0;U<J.length;U++){let x=J.charCodeAt(U);O=(O<<5)-O+x,O=O&O}let j=Math.abs(O)%W.length;V=W[j]||W[0];break;case"location":if(!Z.targetRegion){console.warn("Location strategy requires targetRegion in config, falling back to hash");let U=0;for(let G=0;G<J.length;G++){let X=J.charCodeAt(G);U=(U<<5)-U+X,U=U&U}let x=Math.abs(U)%W.length;V=W[x]||W[0]}else V=XJ(Z.targetRegion,W,Z.shardLocations||{},J);break;case"random":V=W[Math.floor(Math.random()*W.length)]||W[0];break;default:V=W[0];break}return await $.setShardMapping(J,V),V}async function HJ(J,Q="write"){let Z=A(),$=await FJ(J,Q),z=Z.shards[$];if(!z)throw new L(`Shard ${$} not found in configuration`,"SHARD_NOT_FOUND");return z}async function wJ(J,Q){let{createSchema:Z}=await Promise.resolve().then(() => (C(),S));await Z(J,Q)}async function b(J,Q){let Z=jJ(Q);return(await HJ(J,Z)).prepare(Q)}async function TJ(J,Q,Z=[]){let z=await(await b(J,Q)).bind(...Z).run();if(!z.success)throw new L(`Query failed: ${z.error||"Unknown error"}`,"QUERY_FAILED");return z}async function AJ(J,Q,Z=[]){let z=await(await b(J,Q)).bind(...Z).all();if(!z.success)throw new L(`Query failed: ${z.error||"Unknown error"}`,"QUERY_FAILED");return z}async function DJ(J,Q,Z=[]){return await(await b(J,Q)).bind(...Z).first()}async function qJ(J,Q,Z){let $=A();if(!$.shards[Q])throw new L(`Shard ${Q} not found in configuration`,"SHARD_NOT_FOUND");let z=new q($.kv,{hashShardMappings:$.hashShardMappings}),W=await z.getShardMapping(J);if(!W)throw new L(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");if(W.shard!==Q){let{migrateRecord:V}=await Promise.resolve().then(() => (C(),S)),Y=$.shards[W.shard],O=$.shards[Q];if(!Y||!O)throw new L("Source or target shard not available","SHARD_UNAVAILABLE");await V(Y,O,J,Z)}await z.updateShardMapping(J,Q)}async function RJ(){let J=A();if(J.coordinator)try{let Q=J.coordinator.idFromName("default"),$=await J.coordinator.get(Q).fetch("http://coordinator/shards");if($.ok)return await $.json()}catch(Q){console.warn("Failed to get shards from coordinator:",Q)}return Object.keys(J.shards)}async function BJ(){let J=A();if(J.coordinator)try{let $=J.coordinator.idFromName("default"),W=await J.coordinator.get($).fetch("http://coordinator/stats");if(W.ok)return await W.json()}catch($){console.warn("Failed to get stats from coordinator:",$)}let Z=await new q(J.kv,{hashShardMappings:J.hashShardMappings}).getShardKeyCounts();return Object.entries(J.shards).map(([$,z])=>({binding:$,count:Z[$]||0}))}async function vJ(J,Q,Z=[]){let z=A().shards[J];if(!z)throw new L(`Shard ${J} not found`,"SHARD_NOT_FOUND");let W=await z.prepare(Q).bind(...Z).run();if(!W.success)throw new L(`Query failed: ${W.error||"Unknown error"}`,"QUERY_FAILED");return W}async function EJ(J,Q,Z=[]){let z=A().shards[J];if(!z)throw new L(`Shard ${J} not found`,"SHARD_NOT_FOUND");return await z.prepare(Q).bind(...Z).all()}async function IJ(J,Q,Z=[]){let z=A().shards[J];if(!z)throw new L(`Shard ${J} not found`,"SHARD_NOT_FOUND");return await z.prepare(Q).bind(...Z).first()}async function _J(){let J=A();if(await new q(J.kv,{hashShardMappings:J.hashShardMappings}).clearAllMappings(),J.coordinator)try{let Z=J.coordinator.idFromName("default");await J.coordinator.get(Z).fetch("http://coordinator/flush",{method:"POST"})}catch(Z){console.warn("Failed to flush coordinator:",Z)}}I();class p{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 Z=new URL(J.url).pathname,$=J.method;try{switch(`${$} ${Z}`){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(z){return console.error("ShardCoordinator error:",z),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:Q}=await J.json();if(!Q||typeof Q!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Z=await this.getState();if(!Z.knownShards.includes(Q))Z.knownShards.push(Q),Z.shardStats[Q]={binding:Q,count:0,lastUpdated:Date.now()},await this.saveState(Z);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleRemoveShard(J){let{shard:Q}=await J.json();if(!Q||typeof Q!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let Z=await this.getState(),$=Z.knownShards.indexOf(Q);if($>-1){if(Z.knownShards.splice($,1),delete Z.shardStats[Q],Z.roundRobinIndex>=Z.knownShards.length)Z.roundRobinIndex=0;await this.saveState(Z)}return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleGetStats(){let J=await this.getState(),Q=Object.values(J.shardStats);return new Response(JSON.stringify(Q),{headers:{"Content-Type":"application/json"}})}async handleUpdateStats(J){let{shard:Q,count:Z}=await J.json();if(!Q||typeof Q!=="string")return new Response(JSON.stringify({error:"Missing or invalid shard parameter"}),{status:400,headers:{"Content-Type":"application/json"}});if(Z===void 0||typeof Z!=="number")return new Response(JSON.stringify({error:"Missing or invalid count parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let $=await this.getState();if($.shardStats[Q])$.shardStats[Q].count=Z,$.shardStats[Q].lastUpdated=Date.now(),await this.saveState($);return new Response(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}async handleAllocateShard(J){let{primaryKey:Q,strategy:Z,operationType:$}=await J.json();if(!Q||typeof Q!=="string")return new Response(JSON.stringify({error:"Missing or invalid primaryKey parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let z=await this.getState();if(z.knownShards.length===0)return new Response(JSON.stringify({error:"No shards available"}),{status:400,headers:{"Content-Type":"application/json"}});let W=this.resolveStrategy(z.strategy,Z,$||"write"),V=this.selectShard(Q,z,W);if(W==="round-robin")z.roundRobinIndex=(z.roundRobinIndex+1)%z.knownShards.length,await this.saveState(z);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,Q,Z="write"){if(Q)return Q;if(typeof J==="string")return J;return J[Z]}selectShard(J,Q,Z){let $=Q.knownShards;if($.length===0)throw new L("No shards available","NO_SHARDS");switch(Z){case"round-robin":return $[Q.roundRobinIndex]??$[0];case"random":return $[Math.floor(Math.random()*$.length)];case"hash":let z=0;for(let O=0;O<J.length;O++){let j=J.charCodeAt(O);z=(z<<5)-z+j,z=z&z}let W=Math.abs(z)%$.length;return $[W];case"location":let V=0;for(let O=0;O<J.length;O++){let j=J.charCodeAt(O);V=(V<<5)-V+j,V=V&V}let Y=Math.abs(V)%$.length;return $[Y];default:return $[0]}}async incrementShardCount(J){let Q=await this.getState();if(Q.shardStats[J])Q.shardStats[J].count++,Q.shardStats[J].lastUpdated=Date.now(),await this.saveState(Q)}async decrementShardCount(J){let Q=await this.getState();if(Q.shardStats[J]&&Q.shardStats[J].count>0)Q.shardStats[J].count--,Q.shardStats[J].lastUpdated=Date.now(),await this.saveState(Q)}}if(typeof global!=="undefined"){class J{data=new Map;async get($){return this.data.get($)}async put($,z){this.data.set($,z)}async delete($){return this.data.delete($)}async deleteAll(){this.data.clear()}async list($){if(!$?.prefix)return new Map(this.data);let z=new Map;for(let[W,V]of this.data.entries())if(W.startsWith($.prefix))z.set(W,V);return z}}class Q{storage;constructor(){this.storage=new J}}class Z{coordinator;mockState;constructor(){this.mockState=new Q,this.coordinator=new p(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 z=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"user-1",strategy:"round-robin"})}))).json(),V=await(await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"user-2",strategy:"round-robin"})}))).json();console.assert(z.shard!==V.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(),U=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===U.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 z=await(await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"}))).json();console.assert(z.length===1,"Should have one shard stat"),console.assert(z[0]?.binding==="db-stats-test","Should have correct binding name"),console.assert(z[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 $=await this.coordinator.fetch(new Request("http://test/allocate",{method:"POST",body:JSON.stringify({primaryKey:"test-key"})}));console.assert($.status===400,"Should return 400 for no shards available");let z=await this.coordinator.fetch(new Request("http://test/invalid",{method:"GET"}));console.assert(z.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 $=await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"})),z=await $.json(),W=z.find((Y)=>Y.binding==="db-count-test");console.assert(W?.count===2,"Count should be 2 after two increments"),await this.coordinator.decrementShardCount("db-count-test"),$=await this.coordinator.fetch(new Request("http://test/stats",{method:"GET"})),z=await $.json();let V=z.find((Y)=>Y.binding==="db-count-test");console.assert(V?.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($){return console.error("❌ ShardCoordinator tests failed:",$),!1}}}globalThis.testShardCoordinator=()=>new Z}I();k();C();export{f as validateTableForSharding,m as schemaExists,vJ as runShard,TJ as run,YJ as resetConfig,qJ as reassignShard,b as prepare,t as migrateRecord,_ as listTables,RJ as listKnownShards,s as integrateExistingDatabase,QJ as initializeAsync,OJ as initialize,BJ as getShardStats,LJ as getClosestRegionFromIP,_J as flush,IJ as firstShard,DJ as first,o as dropSchema,N as discoverExistingPrimaryKeys,n as createSchemaAcrossShards,wJ as createSchema,i as createMappingsForExistingKeys,UJ as collegedb,JJ as clearShardMigrationCache,e as clearMigrationCache,a as checkMigrationNeeded,r as autoDetectAndMigrate,EJ as allShard,AJ as all,p as ShardCoordinator,q as KVShardMapper,L as CollegeDBError};
|
|
16
|
+
`).run()}if(q.set(j,!0),D)console.log(`Auto-migration completed for shard ${Z}: ${x} records from ${F} tables`)}catch(S){Y.push(`Auto-migration error: ${S}`)}return{migrationNeeded:H,migrationPerformed:D,recordsMigrated:x,tablesProcessed:F,issues:Y}}async function QJ(J,Z,Q){let V=`${Z}_migration_check`;if(q.has(V))return!1;try{let $=await k(J);if($.includes("shard_mappings"))return q.set(V,!0),!1;let{KVShardMapper:O}=await Promise.resolve().then(() => (f(),l)),z=new O(Q.kv,{hashShardMappings:Q.hashShardMappings}),U=$.filter((j)=>j!=="shard_mappings"&&!j.startsWith("sqlite_")&&j!=="sqlite_sequence");for(let j of U.slice(0,3))try{if(((await J.prepare(`SELECT COUNT(*) as count FROM ${j} LIMIT 1`).first())?.count||0)>0){let F=await J.prepare(`SELECT id FROM ${j} LIMIT 1`).first();if(F){let H=String(F.id);if(!await z.getShardMapping(H))return!0}}}catch{continue}return!1}catch{return!1}}function VJ(){q.clear()}function WJ(J){let Z=`${J}_migration_check`;q.delete(Z)}var q;var M=y(()=>{C();q=new Map});C();f();var u=null;function xJ(J){if(u=J,J.shards&&Object.keys(J.shards).length>0&&!J.disableAutoMigration)UJ(J).catch((Z)=>{console.warn("Background auto-migration failed:",Z)})}async function OJ(J){if(u=J,J.shards&&Object.keys(J.shards).length>0&&!J.disableAutoMigration)try{await UJ(J)}catch(Z){console.warn("Auto migration failed:",Z)}}async function FJ(J,Z){return await OJ(J),await Z()}async function UJ(J){try{let{autoDetectAndMigrate:Z}=await Promise.resolve().then(() => (M(),b)),Q=Object.keys(J.shards);console.log(`\uD83D\uDD0D Checking ${Q.length} shards for existing data...`);let V=Q.map(async(O)=>{let z=J.shards[O];if(!z)return null;try{let U=await Z(z,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(W.length>0){let O=W.reduce((z,U)=>z+(U?.recordsMigrated||0),0);console.log(`\uD83C\uDF89 Auto-migration completed! Migrated ${O} records across ${W.length} shards`),W.forEach((z)=>{if(z)console.log(` ✅ ${z.shardName}: ${z.recordsMigrated} records from ${z.tablesProcessed} tables`)})}else console.log("✅ All shards ready - no migration needed")}catch(Z){console.warn("Background auto-migration setup failed:",Z)}}function GJ(){u=null}function A(){if(!u)throw new G("CollegeDB not initialized. Call initialize() first.","NOT_INITIALIZED");return u}function LJ(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 XJ(J,Z){let Q=J.strategy||"hash";if(typeof Q==="string")return Q;return Q[Z]}function HJ(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 TJ(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 wJ(J,Z,Q,V){let $=Z.filter((Y)=>Q[Y]);if($.length===0){let Y=0;for(let F=0;F<V.length;F++){let H=V.charCodeAt(F);Y=(Y<<5)-Y+H,Y=Y&Y}let x=Math.abs(Y)%Z.length;return Z[x]}let W=$.map((Y)=>{let x=Q[Y],F=HJ(J,x.region),H=x.priority||1,D=F-H*0.1;return{shard:Y,score:D,distance:F,priority:H}});W.sort((Y,x)=>Y.score-x.score);let O=W[0].score,z=W.filter((Y)=>Math.abs(Y.score-O)<0.01);if(z.length===1)return z[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 j=Math.abs(U)%z.length;return z[j].shard}async function AJ(J,Z="write"){let Q=A(),V=new E(Q.kv,{hashShardMappings:Q.hashShardMappings}),$=await V.getShardMapping(J);if($)return $.shard;let W=Object.keys(Q.shards);if(W.length===0)throw new G("No shards configured","NO_SHARDS");for(let U of W){let j=Q.shards[U];if(!j)continue;try{let{autoDetectAndMigrate:Y}=await Promise.resolve().then(() => (M(),b));if((await Y(j,U,Q,{maxRecordsToCheck:100})).migrationPerformed){let F=await V.getShardMapping(J);if(F)return F.shard}}catch(Y){console.warn(`Auto-migration check failed for shard ${U}:`,Y)}}let O,z=XJ(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:z,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(z){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 j=Math.abs(U)%W.length;O=W[j]||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 F=0;F<J.length;F++){let H=J.charCodeAt(F);Y=(Y<<5)-Y+H,Y=Y&Y}let x=Math.abs(Y)%W.length;O=W[x]||W[0]}else O=wJ(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 DJ(J,Z="write"){let Q=A(),V=await AJ(J,Z),$=Q.shards[V];if(!$)throw new G(`Shard ${V} not found in configuration`,"SHARD_NOT_FOUND");return $}async function vJ(J,Z){let{createSchema:Q}=await Promise.resolve().then(() => (M(),b));await Q(J,Z)}async function p(J,Z){let Q=LJ(Z);return(await DJ(J,Q)).prepare(Z)}async function BJ(J,Z,Q=[]){let $=await(await p(J,Z)).bind(...Q).run();if(!$.success)throw new G(`Query failed: ${$.error||"Unknown error"}`,"QUERY_FAILED");return $}async function RJ(J,Z,Q=[]){let $=await(await p(J,Z)).bind(...Q).all();if(!$.success)throw new G(`Query failed: ${$.error||"Unknown error"}`,"QUERY_FAILED");return $}async function EJ(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 G(`Shard ${Z} not found in configuration`,"SHARD_NOT_FOUND");let $=new E(V.kv,{hashShardMappings:V.hashShardMappings}),W=await $.getShardMapping(J);if(!W)throw new G(`No existing mapping found for primary key: ${J}`,"MAPPING_NOT_FOUND");if(W.shard!==Z){let{migrateRecord:O}=await Promise.resolve().then(() => (M(),b)),z=V.shards[W.shard],U=V.shards[Z];if(!z||!U)throw new G("Source or target shard not available","SHARD_UNAVAILABLE");await O(z,U,J,Q)}await $.updateShardMapping(J,Z)}async function _J(){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 qJ(){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 E(J.kv,{hashShardMappings:J.hashShardMappings}).getShardKeyCounts();return Object.entries(J.shards).map(([V,$])=>({binding:V,count:Q[V]||0}))}async function PJ(J,Z,Q=[]){let $=A().shards[J];if(!$)throw new G(`Shard ${J} not found`,"SHARD_NOT_FOUND");let W=await $.prepare(Z).bind(...Q).run();if(!W.success)throw new G(`Query failed: ${W.error||"Unknown error"}`,"QUERY_FAILED");return W}async function CJ(J,Z,Q=[]){let $=A().shards[J];if(!$)throw new G(`Shard ${J} not found`,"SHARD_NOT_FOUND");return await $.prepare(Z).bind(...Q).all()}async function kJ(J,Z,Q=[]){let $=A().shards[J];if(!$)throw new G(`Shard ${J} not found`,"SHARD_NOT_FOUND");return await $.prepare(Z).bind(...Q).first()}async function MJ(J,Z=[],Q=50){let V=A(),$=[];for(let[O,z]of Object.entries(V.shards))try{let U=z.prepare(J).bind(...Z).all().catch((j)=>{return console.error(`Error executing query on shard ${O}:`,j),{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 SJ(J,Z=[],Q=50){let V=A(),$=[];for(let[O,z]of Object.entries(V.shards))try{let U=z.prepare(J).bind(...Z).all().catch((j)=>{return console.error(`Error executing query on shard ${O}:`,j),{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 NJ(J,Z=[],Q=50){let V=A(),$=[];for(let[O,z]of Object.entries(V.shards))try{let U=z.prepare(J).bind(...Z).first().catch((j)=>{return console.error(`Error executing query on shard ${O}:`,j),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 fJ(){let J=A();if(await new E(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)}}C();class o{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 G("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 j=J.charCodeAt(U);$=($<<5)-$+j,$=$&$}let W=Math.abs($)%V.length;return V[W];case"location":let O=0;for(let U=0;U<J.length;U++){let j=J.charCodeAt(U);O=(O<<5)-O+j,O=O&O}let z=Math.abs(O)%V.length;return V[z];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 o(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((z)=>z.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((z)=>z.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}C();f();M();export{h as validateTableForSharding,n as schemaExists,PJ as runShard,MJ as runAllShards,BJ as run,GJ as resetConfig,IJ as reassignShard,p as prepare,e as migrateRecord,k as listTables,_J as listKnownShards,ZJ as integrateExistingDatabase,OJ as initializeAsync,xJ as initialize,qJ as getShardStats,TJ as getClosestRegionFromIP,fJ as flush,kJ as firstShard,NJ as firstAllShards,EJ as first,a as dropSchema,g as discoverExistingRecordsWithColumns,c as discoverExistingPrimaryKeys,r as createSchemaAcrossShards,vJ as createSchema,JJ as createMappingsForExistingKeys,FJ as collegedb,WJ as clearShardMigrationCache,VJ as clearMigrationCache,QJ as checkMigrationNeeded,$J as autoDetectAndMigrate,CJ as allShard,SJ as allAllShards,RJ as all,o as ShardCoordinator,E as KVShardMapper,G as CollegeDBError};
|
|
17
17
|
|
|
18
|
-
//# debugId=
|
|
18
|
+
//# debugId=B534EAE4E4E6DE1764756E2164756E21
|
|
19
19
|
//# sourceMappingURL=index.js.map
|