adaptive-memory-multi-model-router 1.9.4 → 1.9.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.
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+ /**
3
+ * A3M Router - Generative Engine Optimization (GEO)
4
+ *
5
+ * Features to make the package discoverable by AI agents and LLMs:
6
+ * - Structured metadata for AI consumption
7
+ * - Intent-to-code mapping
8
+ * - AI-friendly documentation generation
9
+ * - LLM-optimized examples
10
+ */
11
+
12
+ // Intent-to-code mapping for AI agents
13
+ const INTENT_MAP = {
14
+ // Routing intents
15
+ 'route llm query': {
16
+ code: `const { routeQuery } = require('adaptive-memory-multi-model-router');
17
+ const result = routeQuery("Your query here");
18
+ console.log(result.primary_model);`,
19
+ description: 'Route a query to the optimal LLM provider',
20
+ },
21
+ 'route to cheapest provider': {
22
+ code: `const { routeQuery } = require('adaptive-memory-multi-model-router');
23
+ const result = routeQuery("Your query", { budget_multiplier: 0.3 });`,
24
+ description: 'Route to cheapest capable provider',
25
+ },
26
+ 'route to best quality': {
27
+ code: `const { routeQuery } = require('adaptive-memory-multi-model-router');
28
+ const result = routeQuery("Your query", { quality_priority: true });`,
29
+ description: 'Route to highest quality provider',
30
+ },
31
+
32
+ // Batch processing intents
33
+ 'batch process prompts': {
34
+ code: `const { routeBatch } = require('adaptive-memory-multi-model-router');
35
+ const queries = ["Q1", "Q2", "Q3"];
36
+ const results = routeBatch(queries);`,
37
+ description: 'Process multiple prompts with automatic routing',
38
+ },
39
+ 'parallel llm calls': {
40
+ code: `const { routeBatch } = require('adaptive-memory-multi-model-router');
41
+ const results = routeBatch(queries, { concurrency: 5 });`,
42
+ description: 'Execute LLM calls in parallel',
43
+ },
44
+
45
+ // Cost tracking intents
46
+ 'track llm costs': {
47
+ code: `const { createA3MRouter } = require('adaptive-memory-multi-model-router');
48
+ const router = createA3MRouter();
49
+ const summary = router.costTracker.getSummary();
50
+ console.log(\`Total: \$\${summary.totalSpent}\`);`,
51
+ description: 'Track API costs across all providers',
52
+ },
53
+ 'estimate api cost': {
54
+ code: `const { estimateCost } = require('adaptive-memory-multi-model-router');
55
+ const cost = estimateCost(1000, 500, 'gpt-4o');
56
+ console.log(\`Cost: \$\${cost.toFixed(6)}\`);`,
57
+ description: 'Estimate cost before making API call',
58
+ },
59
+
60
+ // Provider management intents
61
+ 'list llm providers': {
62
+ code: `const { getAvailableProviders } = require('adaptive-memory-multi-model-router');
63
+ const providers = getAvailableProviders();
64
+ console.log(Object.keys(providers));`,
65
+ description: 'List all configured LLM providers',
66
+ },
67
+ 'add custom provider': {
68
+ code: `const { registerProvider } = require('adaptive-memory-multi-model-router');
69
+ registerProvider('my-provider', {
70
+ baseUrl: 'https://api.myprovider.com',
71
+ models: ['my-model'],
72
+ type: 'api'
73
+ });`,
74
+ description: 'Register a custom LLM provider',
75
+ },
76
+ 'check provider health': {
77
+ code: `const { providerConfig } = require('adaptive-memory-multi-model-router');
78
+ const health = await providerConfig.healthCheck('groq');
79
+ console.log(health.healthy ? '✅' : '❌');`,
80
+ description: 'Check if a provider is healthy',
81
+ },
82
+
83
+ // Caching intents
84
+ 'cache llm responses': {
85
+ code: `const { createA3MRouter } = require('adaptive-memory-multi-model-router');
86
+ const router = createA3MRouter({ cache: { ttl_seconds: 3600 } });`,
87
+ description: 'Enable response caching',
88
+ },
89
+
90
+ // Fallback intents
91
+ 'setup llm fallback': {
92
+ code: `const { createA3MRouter } = require('adaptive-memory-multi-model-router');
93
+ const router = createA3MRouter();
94
+ // Fallback is automatic - just use router.route()`,
95
+ description: 'Automatic fallback when providers fail',
96
+ },
97
+
98
+ // CLI intents
99
+ 'route from command line': {
100
+ code: `npx a3m-router route "Your query here"`,
101
+ description: 'Route queries via CLI',
102
+ },
103
+ 'benchmark providers': {
104
+ code: `npx a3m-router benchmark`,
105
+ description: 'Compare all configured providers',
106
+ },
107
+ };
108
+
109
+ // AI-optimized package metadata
110
+ const PACKAGE_METADATA = {
111
+ name: 'adaptive-memory-multi-model-router',
112
+ shortName: 'A3M Router',
113
+ category: 'LLM Routing & Cost Optimization',
114
+ primaryUseCases: [
115
+ 'Route LLM queries to optimal providers',
116
+ 'Reduce API costs through intelligent selection',
117
+ 'Handle provider failures with automatic fallback',
118
+ 'Process prompts in parallel batches',
119
+ 'Track spending across multiple LLM APIs',
120
+ ],
121
+ keyFeatures: [
122
+ 'Learned routing based on query analysis',
123
+ 'Cost optimization (50-80% savings)',
124
+ 'Automatic provider fallback',
125
+ 'Batch processing with rate limiting',
126
+ 'Response caching',
127
+ 'Real-time cost tracking',
128
+ 'CLI tools',
129
+ ],
130
+ supportedProviders: [
131
+ 'Groq', 'Cerebras', 'Mistral', 'OpenAI', 'Anthropic',
132
+ 'Google', 'DeepSeek', 'CommandCode', 'OpenCode',
133
+ 'Ollama', 'vLLM', 'LM Studio',
134
+ ],
135
+ alternatives: ['LiteLLM', 'OpenRouter', 'Helicone'],
136
+ differentiators: [
137
+ 'Learned routing (not just proxying)',
138
+ 'Cost-quality tradeoff optimization',
139
+ 'Generic provider system (user-configurable)',
140
+ 'Built-in fallback and retry',
141
+ 'Comprehensive CLI',
142
+ ],
143
+ };
144
+
145
+ // Keywords for AI indexing
146
+ const AI_INDEXING_KEYWORDS = [
147
+ // Primary
148
+ 'llm routing', 'cost optimization', 'multi-provider', 'adaptive routing',
149
+ // Features
150
+ 'batch processing', 'parallel execution', 'fallback', 'retry', 'load balancing',
151
+ // Providers
152
+ 'openai', 'anthropic', 'claude', 'groq', 'cerebras', 'mistral',
153
+ // Concepts
154
+ 'routellm', 'radix-attention', 'medusa', 'token compression',
155
+ // Use cases
156
+ 'api gateway', 'llm proxy', 'model router', 'cost tracking',
157
+ // Integrations
158
+ 'github', 'slack', 'telegram', 'notion', 'discord',
159
+ // Technical
160
+ 'typescript', 'javascript', 'nodejs', 'cli', 'sdk',
161
+ ];
162
+
163
+ class GenerativeEngineOptimizer {
164
+ constructor() {
165
+ this.intentMap = INTENT_MAP;
166
+ this.metadata = PACKAGE_METADATA;
167
+ this.keywords = AI_INDEXING_KEYWORDS;
168
+ }
169
+
170
+ /**
171
+ * Get code example for a specific intent
172
+ */
173
+ getCodeForIntent(intent) {
174
+ const normalized = intent.toLowerCase().trim();
175
+
176
+ // Exact match
177
+ if (this.intentMap[normalized]) {
178
+ return this.intentMap[normalized];
179
+ }
180
+
181
+ // Partial match
182
+ for (const [key, value] of Object.entries(this.intentMap)) {
183
+ if (normalized.includes(key) || key.includes(normalized)) {
184
+ return value;
185
+ }
186
+ }
187
+
188
+ // Fuzzy match - find best similarity
189
+ let bestMatch = null;
190
+ let bestScore = 0;
191
+
192
+ for (const key of Object.keys(this.intentMap)) {
193
+ const score = this.calculateSimilarity(normalized, key);
194
+ if (score > bestScore && score > 0.3) {
195
+ bestScore = score;
196
+ bestMatch = key;
197
+ }
198
+ }
199
+
200
+ return bestMatch ? this.intentMap[bestMatch] : null;
201
+ }
202
+
203
+ /**
204
+ * Simple similarity calculation
205
+ */
206
+ calculateSimilarity(a, b) {
207
+ const aWords = a.split(/\s+/);
208
+ const bWords = b.split(/\s+/);
209
+
210
+ const intersection = aWords.filter(word => bWords.includes(word));
211
+ return intersection.length / Math.max(aWords.length, bWords.length);
212
+ }
213
+
214
+ /**
215
+ * Get all intents matching a category
216
+ */
217
+ getIntentsByCategory(category) {
218
+ const categories = {
219
+ routing: ['route llm query', 'route to cheapest provider', 'route to best quality'],
220
+ batch: ['batch process prompts', 'parallel llm calls'],
221
+ cost: ['track llm costs', 'estimate api cost'],
222
+ providers: ['list llm providers', 'add custom provider', 'check provider health'],
223
+ caching: ['cache llm responses'],
224
+ fallback: ['setup llm fallback'],
225
+ cli: ['route from command line', 'benchmark providers'],
226
+ };
227
+
228
+ const keys = categories[category] || [];
229
+ return keys.map(key => this.intentMap[key]).filter(Boolean);
230
+ }
231
+
232
+ /**
233
+ * Generate AI-optimized documentation
234
+ */
235
+ generateAIDocumentation() {
236
+ return {
237
+ metadata: this.metadata,
238
+ quickStart: this.intentMap['route llm query'],
239
+ commonIntents: Object.entries(this.intentMap).slice(0, 5).map(([intent, data]) => ({
240
+ intent,
241
+ ...data,
242
+ })),
243
+ keywords: this.keywords,
244
+ };
245
+ }
246
+
247
+ /**
248
+ * Get package metadata for AI consumption
249
+ */
250
+ getPackageMetadata() {
251
+ return {
252
+ ...this.metadata,
253
+ installation: 'npm install adaptive-memory-multi-model-router',
254
+ github: 'https://github.com/Das-rebel/adaptive-memory-multi-model-router',
255
+ npm: 'https://www.npmjs.com/package/adaptive-memory-multi-model-router',
256
+ weeklyDownloads: 872,
257
+ testCount: 33,
258
+ keywordCount: 139,
259
+ };
260
+ }
261
+
262
+ /**
263
+ * Search intents by keyword
264
+ */
265
+ searchIntents(keyword) {
266
+ const results = [];
267
+ const normalized = keyword.toLowerCase();
268
+
269
+ for (const [intent, data] of Object.entries(this.intentMap)) {
270
+ if (intent.includes(normalized) || data.description.toLowerCase().includes(normalized)) {
271
+ results.push({ intent, ...data });
272
+ }
273
+ }
274
+
275
+ return results;
276
+ }
277
+
278
+ /**
279
+ * Get comparison with alternatives
280
+ */
281
+ getComparison() {
282
+ return {
283
+ package: this.metadata.name,
284
+ alternatives: this.metadata.alternatives,
285
+ differentiators: this.metadata.differentiators,
286
+ recommendation: 'Use A3M Router for learned routing with cost optimization. Use LiteLLM for simple proxying. Use OpenRouter for hosted routing.',
287
+ };
288
+ }
289
+ }
290
+
291
+ // Convenience functions
292
+ function getCodeForIntent(intent) {
293
+ const geo = new GenerativeEngineOptimizer();
294
+ return geo.getCodeForIntent(intent);
295
+ }
296
+
297
+ function searchIntents(keyword) {
298
+ const geo = new GenerativeEngineOptimizer();
299
+ return geo.searchIntents(keyword);
300
+ }
301
+
302
+ function getPackageMetadata() {
303
+ const geo = new GenerativeEngineOptimizer();
304
+ return geo.getPackageMetadata();
305
+ }
306
+
307
+ function generateAIDocumentation() {
308
+ const geo = new GenerativeEngineOptimizer();
309
+ return geo.generateAIDocumentation();
310
+ }
311
+
312
+ module.exports = {
313
+ GenerativeEngineOptimizer,
314
+ getCodeForIntent,
315
+ searchIntents,
316
+ getPackageMetadata,
317
+ generateAIDocumentation,
318
+ INTENT_MAP,
319
+ PACKAGE_METADATA,
320
+ AI_INDEXING_KEYWORDS,
321
+ };
@@ -0,0 +1,387 @@
1
+ "use strict";
2
+ /**
3
+ * A3M Router - Geo-Location Based Routing
4
+ *
5
+ * Route LLM queries to providers based on geographic location:
6
+ * - Latency optimization (nearest provider)
7
+ * - Data sovereignty (EU data stays in EU)
8
+ * - Compliance (GDPR, CCPA)
9
+ * - Regional provider preferences
10
+ */
11
+
12
+ // Provider regions and data centers
13
+ const PROVIDER_REGIONS = {
14
+ groq: {
15
+ regions: ['us-west', 'us-east', 'eu-west'],
16
+ dataCenters: {
17
+ 'us-west': { lat: 37.7749, lon: -122.4194, location: 'San Francisco' },
18
+ 'us-east': { lat: 40.7128, lon: -74.0060, location: 'New York' },
19
+ 'eu-west': { lat: 53.3498, lon: -6.2603, location: 'Dublin' },
20
+ },
21
+ gdprCompliant: true,
22
+ soc2Compliant: true,
23
+ },
24
+ cerebras: {
25
+ regions: ['us-west', 'us-central'],
26
+ dataCenters: {
27
+ 'us-west': { lat: 37.7749, lon: -122.4194, location: 'San Francisco' },
28
+ 'us-central': { lat: 41.8781, lon: -87.6298, location: 'Chicago' },
29
+ },
30
+ gdprCompliant: false,
31
+ soc2Compliant: true,
32
+ },
33
+ mistral: {
34
+ regions: ['eu-west', 'eu-central'],
35
+ dataCenters: {
36
+ 'eu-west': { lat: 48.8566, lon: 2.3522, location: 'Paris' },
37
+ 'eu-central': { lat: 50.1109, lon: 8.6821, location: 'Frankfurt' },
38
+ },
39
+ gdprCompliant: true,
40
+ soc2Compliant: true,
41
+ },
42
+ openai: {
43
+ regions: ['us-west', 'us-east', 'eu-west', 'apac'],
44
+ dataCenters: {
45
+ 'us-west': { lat: 37.7749, lon: -122.4194, location: 'San Francisco' },
46
+ 'us-east': { lat: 40.7128, lon: -74.0060, location: 'New York' },
47
+ 'eu-west': { lat: 53.3498, lon: -6.2603, location: 'Dublin' },
48
+ 'apac': { lat: 1.3521, lon: 103.8198, location: 'Singapore' },
49
+ },
50
+ gdprCompliant: true,
51
+ soc2Compliant: true,
52
+ },
53
+ anthropic: {
54
+ regions: ['us-west', 'us-east'],
55
+ dataCenters: {
56
+ 'us-west': { lat: 37.7749, lon: -122.4194, location: 'San Francisco' },
57
+ 'us-east': { lat: 40.7128, lon: -74.0060, location: 'New York' },
58
+ },
59
+ gdprCompliant: false,
60
+ soc2Compliant: true,
61
+ },
62
+ google: {
63
+ regions: ['us-central', 'us-east', 'eu-west', 'eu-central', 'apac', 'apac-east'],
64
+ dataCenters: {
65
+ 'us-central': { lat: 41.8781, lon: -87.6298, location: 'Iowa' },
66
+ 'us-east': { lat: 33.7490, lon: -84.3880, location: 'Georgia' },
67
+ 'eu-west': { lat: 53.3498, lon: -6.2603, location: 'Dublin' },
68
+ 'eu-central': { lat: 50.4500, lon: 3.8180, location: 'Belgium' },
69
+ 'apac': { lat: 1.3521, lon: 103.8198, location: 'Singapore' },
70
+ 'apac-east': { lat: 35.6762, lon: 139.6503, location: 'Tokyo' },
71
+ },
72
+ gdprCompliant: true,
73
+ soc2Compliant: true,
74
+ },
75
+ };
76
+
77
+ // Regional compliance requirements
78
+ const COMPLIANCE_RULES = {
79
+ gdpr: {
80
+ regions: ['EU', 'EEA'],
81
+ required: ['gdprCompliant'],
82
+ dataResidency: true,
83
+ },
84
+ ccpa: {
85
+ regions: ['California'],
86
+ required: ['privacyPolicy'],
87
+ dataResidency: false,
88
+ },
89
+ hipaa: {
90
+ regions: ['US-Healthcare'],
91
+ required: ['hipaaCompliant', 'baa'],
92
+ dataResidency: true,
93
+ },
94
+ fedramp: {
95
+ regions: ['US-Government'],
96
+ required: ['fedrampAuthorized'],
97
+ dataResidency: true,
98
+ },
99
+ };
100
+
101
+ class GeoRouter {
102
+ constructor(options = {}) {
103
+ this.options = {
104
+ defaultRegion: options.defaultRegion || 'us-east',
105
+ enforceGDPR: options.enforceGDPR || false,
106
+ enforceCCPA: options.enforceCCPA || false,
107
+ dataResidency: options.dataResidency || null, // 'EU', 'US', etc.
108
+ preferLowLatency: options.preferLowLatency !== false,
109
+ maxLatencyMs: options.maxLatencyMs || 500,
110
+ ...options,
111
+ };
112
+ }
113
+
114
+ /**
115
+ * Calculate distance between two points using Haversine formula
116
+ */
117
+ calculateDistance(lat1, lon1, lat2, lon2) {
118
+ const R = 6371; // Earth's radius in km
119
+ const dLat = this.toRadians(lat2 - lat1);
120
+ const dLon = this.toRadians(lon2 - lon1);
121
+ const a =
122
+ Math.sin(dLat / 2) * Math.sin(dLat / 2) +
123
+ Math.cos(this.toRadians(lat1)) *
124
+ Math.cos(this.toRadians(lat2)) *
125
+ Math.sin(dLon / 2) *
126
+ Math.sin(dLon / 2);
127
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
128
+ return R * c;
129
+ }
130
+
131
+ toRadians(degrees) {
132
+ return (degrees * Math.PI) / 180;
133
+ }
134
+
135
+ /**
136
+ * Estimate latency based on distance
137
+ */
138
+ estimateLatency(distanceKm) {
139
+ // Rough estimate: 1ms per 100km + 50ms base
140
+ return Math.round(distanceKm / 100 + 50);
141
+ }
142
+
143
+ /**
144
+ * Get user's location from IP or explicit coordinates
145
+ */
146
+ async getUserLocation(ipAddress, explicitCoords = null) {
147
+ if (explicitCoords) {
148
+ return {
149
+ lat: explicitCoords.lat,
150
+ lon: explicitCoords.lon,
151
+ region: explicitCoords.region || this.inferRegion(explicitCoords.lat, explicitCoords.lon),
152
+ country: explicitCoords.country,
153
+ source: 'explicit',
154
+ };
155
+ }
156
+
157
+ // In production, use a geolocation service
158
+ // For now, return default
159
+ return {
160
+ lat: 40.7128,
161
+ lon: -74.006,
162
+ region: 'us-east',
163
+ country: 'US',
164
+ source: 'default',
165
+ };
166
+ }
167
+
168
+ /**
169
+ * Infer region from coordinates
170
+ */
171
+ inferRegion(lat, lon) {
172
+ // Rough region inference
173
+ if (lat > 25 && lat < 50 && lon > -130 && lon < -60) return 'us-east';
174
+ if (lat > 25 && lat < 50 && lon > -125 && lon < -115) return 'us-west';
175
+ if (lat > 35 && lat < 70 && lon > -10 && lon < 40) return 'eu-west';
176
+ if (lat > 10 && lat < 40 && lon > 100 && lon < 150) return 'apac';
177
+ return this.options.defaultRegion;
178
+ }
179
+
180
+ /**
181
+ * Check if provider meets compliance requirements
182
+ */
183
+ checkCompliance(providerId, compliance = []) {
184
+ const provider = PROVIDER_REGIONS[providerId];
185
+ if (!provider) return { compliant: false, reason: 'Unknown provider' };
186
+
187
+ const results = {
188
+ compliant: true,
189
+ checks: {},
190
+ failed: [],
191
+ };
192
+
193
+ for (const req of compliance) {
194
+ const rule = COMPLIANCE_RULES[req];
195
+ if (!rule) continue;
196
+
197
+ for (const requirement of rule.required) {
198
+ const check = this.checkRequirement(provider, requirement);
199
+ results.checks[requirement] = check;
200
+
201
+ if (!check.passed) {
202
+ results.compliant = false;
203
+ results.failed.push({ requirement, reason: check.reason });
204
+ }
205
+ }
206
+ }
207
+
208
+ return results;
209
+ }
210
+
211
+ checkRequirement(provider, requirement) {
212
+ switch (requirement) {
213
+ case 'gdprCompliant':
214
+ return {
215
+ passed: provider.gdprCompliant,
216
+ reason: provider.gdprCompliant ? null : 'Provider not GDPR compliant',
217
+ };
218
+ case 'soc2Compliant':
219
+ return {
220
+ passed: provider.soc2Compliant,
221
+ reason: provider.soc2Compliant ? null : 'Provider not SOC2 compliant',
222
+ };
223
+ default:
224
+ return { passed: true, reason: null };
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Find nearest provider data center
230
+ */
231
+ findNearestRegion(providerId, userLocation) {
232
+ const provider = PROVIDER_REGIONS[providerId];
233
+ if (!provider) return null;
234
+
235
+ let nearest = null;
236
+ let minDistance = Infinity;
237
+
238
+ for (const [region, coords] of Object.entries(provider.dataCenters)) {
239
+ const distance = this.calculateDistance(
240
+ userLocation.lat,
241
+ userLocation.lon,
242
+ coords.lat,
243
+ coords.lon
244
+ );
245
+
246
+ if (distance < minDistance) {
247
+ minDistance = distance;
248
+ nearest = {
249
+ region,
250
+ distance,
251
+ estimatedLatency: this.estimateLatency(distance),
252
+ location: coords.location,
253
+ };
254
+ }
255
+ }
256
+
257
+ return nearest;
258
+ }
259
+
260
+ /**
261
+ * Route query based on geographic location
262
+ */
263
+ async routeByLocation(query, options = {}) {
264
+ const userLocation = await this.getUserLocation(
265
+ options.ipAddress,
266
+ options.coordinates
267
+ );
268
+
269
+ const availableProviders = options.providers || Object.keys(PROVIDER_REGIONS);
270
+ const candidates = [];
271
+
272
+ for (const providerId of availableProviders) {
273
+ const provider = PROVIDER_REGIONS[providerId];
274
+ if (!provider) continue;
275
+
276
+ // Check compliance
277
+ if (options.compliance?.length > 0) {
278
+ const compliance = this.checkCompliance(providerId, options.compliance);
279
+ if (!compliance.compliant) {
280
+ continue;
281
+ }
282
+ }
283
+
284
+ // Check data residency
285
+ if (this.options.dataResidency) {
286
+ const hasRegionInResidency = provider.regions.some((r) =>
287
+ r.toLowerCase().includes(this.options.dataResidency.toLowerCase())
288
+ );
289
+ if (!hasRegionInResidency) continue;
290
+ }
291
+
292
+ // Find nearest region
293
+ const nearest = this.findNearestRegion(providerId, userLocation);
294
+ if (!nearest) continue;
295
+
296
+ // Check latency constraint
297
+ if (nearest.estimatedLatency > this.options.maxLatencyMs) {
298
+ continue;
299
+ }
300
+
301
+ candidates.push({
302
+ provider: providerId,
303
+ region: nearest.region,
304
+ distance: nearest.distance,
305
+ estimatedLatency: nearest.estimatedLatency,
306
+ location: nearest.location,
307
+ gdprCompliant: provider.gdprCompliant,
308
+ });
309
+ }
310
+
311
+ // Sort by latency
312
+ candidates.sort((a, b) => a.estimatedLatency - b.estimatedLatency);
313
+
314
+ return {
315
+ userLocation,
316
+ candidates,
317
+ recommended: candidates[0] || null,
318
+ alternatives: candidates.slice(1, 4),
319
+ };
320
+ }
321
+
322
+ /**
323
+ * Get provider regions info
324
+ */
325
+ getProviderRegions(providerId) {
326
+ return PROVIDER_REGIONS[providerId] || null;
327
+ }
328
+
329
+ /**
330
+ * List all available regions
331
+ */
332
+ listRegions() {
333
+ const regions = new Set();
334
+ for (const provider of Object.values(PROVIDER_REGIONS)) {
335
+ for (const region of provider.regions) {
336
+ regions.add(region);
337
+ }
338
+ }
339
+ return Array.from(regions).sort();
340
+ }
341
+
342
+ /**
343
+ * Get compliance status for all providers
344
+ */
345
+ getComplianceStatus() {
346
+ const status = {};
347
+ for (const [providerId, provider] of Object.entries(PROVIDER_REGIONS)) {
348
+ status[providerId] = {
349
+ gdpr: provider.gdprCompliant,
350
+ soc2: provider.soc2Compliant,
351
+ regions: provider.regions,
352
+ };
353
+ }
354
+ return status;
355
+ }
356
+ }
357
+
358
+ // Convenience functions
359
+ async function routeByLocation(query, options = {}) {
360
+ const router = new GeoRouter(options);
361
+ return router.routeByLocation(query, options);
362
+ }
363
+
364
+ function getProviderRegions(providerId) {
365
+ const router = new GeoRouter();
366
+ return router.getProviderRegions(providerId);
367
+ }
368
+
369
+ function listRegions() {
370
+ const router = new GeoRouter();
371
+ return router.listRegions();
372
+ }
373
+
374
+ function getComplianceStatus() {
375
+ const router = new GeoRouter();
376
+ return router.getComplianceStatus();
377
+ }
378
+
379
+ module.exports = {
380
+ GeoRouter,
381
+ routeByLocation,
382
+ getProviderRegions,
383
+ listRegions,
384
+ getComplianceStatus,
385
+ PROVIDER_REGIONS,
386
+ COMPLIANCE_RULES,
387
+ };