adaptive-memory-multi-model-router 1.9.4 → 2.0.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/.github/ISSUE_TEMPLATE/bug_report.md +50 -0
- package/.github/ISSUE_TEMPLATE/config.yml +11 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +37 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +44 -0
- package/.github/workflows/npm-stats-validation.yml +152 -0
- package/.github/workflows/pages.yml +37 -0
- package/CHANGELOG.md +122 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +110 -0
- package/LAUNCH-PAIN-DRIVEN.md +339 -0
- package/LAUNCH.md +575 -0
- package/POPULARITY_BOOSTERS.md +285 -0
- package/README.md +231 -300
- package/SECURITY.md +69 -0
- package/articles/CONTENT_STRUCTURE.md +292 -0
- package/articles/DEVTO_COST_GUIDE.md +473 -0
- package/articles/DEVTO_FINAL.md +416 -0
- package/articles/DEVTO_MULTI_PROVIDER.md +542 -0
- package/articles/HN_10X_BETTER.md +430 -0
- package/articles/HN_CHINESE_STYLE.md +308 -0
- package/articles/HN_FINAL.md +199 -0
- package/articles/HN_POSTED_VERSION.md +56 -0
- package/articles/HN_RESEARCH.md +364 -0
- package/articles/PAIN-DRIVEN-devto-v2.md +308 -0
- package/articles/PAIN-DRIVEN-devto-v3.md +268 -0
- package/articles/PAIN-DRIVEN-devto.md +242 -0
- package/articles/PAIN-DRIVEN-hackernews-v2.md +138 -0
- package/articles/PAIN-DRIVEN-hackernews-v3.md +151 -0
- package/articles/PAIN-DRIVEN-hackernews.md +131 -0
- package/articles/PAIN-DRIVEN-reddit-v2.md +301 -0
- package/articles/PAIN-DRIVEN-reddit-v3.md +236 -0
- package/articles/PAIN-DRIVEN-reddit.md +218 -0
- package/articles/PAIN-DRIVEN-twitter-v2.md +110 -0
- package/articles/PAIN-DRIVEN-twitter-v3.md +121 -0
- package/articles/PAIN-DRIVEN-twitter.md +120 -0
- package/articles/PORTKEY_VS_A3M.md +147 -0
- package/articles/REDDIT_FINAL.md +232 -0
- package/articles/TWITTER_FINAL.md +167 -0
- package/articles/WHY_10X_BETTER.md +261 -0
- package/articles/WHY_CHINESE_STYLE_BETTER.md +323 -0
- package/articles/ai-discoverability-llm-routing.md +210 -0
- package/articles/devto-llm-routing.md +109 -0
- package/articles/hackernews-show-hn.md +65 -0
- package/articles/hashnode-llm-cost-optimization.md +125 -0
- package/articles/medium-building-llm-router.md +205 -0
- package/articles/reddit-ml.md +86 -0
- package/articles/twitter-thread-cost-savings.md +98 -0
- package/articles/youtube-tutorial-script.md +262 -0
- package/assets/banner.svg +109 -0
- package/assets/logo.svg +68 -0
- package/assets/social-preview.svg +64 -0
- package/demo/demo-script.md +53 -0
- package/dist/analytics/costAnalytics.d.ts +77 -0
- package/dist/analytics/costAnalytics.d.ts.map +1 -0
- package/dist/analytics/costAnalytics.js +219 -0
- package/dist/analytics/costAnalytics.js.map +1 -0
- package/dist/cache/semanticCache.d.ts +62 -0
- package/dist/cache/semanticCache.d.ts.map +1 -0
- package/dist/cache/semanticCache.js +176 -0
- package/dist/cache/semanticCache.js.map +1 -0
- package/dist/cli.js +35 -0
- package/dist/geo/generativeEngineOptimization.js +321 -0
- package/dist/geo/geoRouter.js +387 -0
- package/dist/index.d.ts +4 -723
- package/dist/index.js +11 -344
- package/dist/index.js.map +1 -1
- package/dist/integrations/langchainAdapter.d.ts +146 -0
- package/dist/integrations/langchainAdapter.d.ts.map +1 -0
- package/dist/integrations/langchainAdapter.js +731 -0
- package/dist/integrations/langchainAdapter.js.map +1 -0
- package/dist/integrations/oauth.d.ts +69 -0
- package/dist/integrations/oauth.d.ts.map +1 -0
- package/dist/integrations/oauth.js +225 -21
- package/dist/integrations/oauth.js.map +1 -0
- package/dist/memory/autoFetch.d.ts +39 -0
- package/dist/memory/autoFetch.d.ts.map +1 -0
- package/dist/memory/autoFetch.js +80 -88
- package/dist/memory/autoFetch.js.map +1 -0
- package/dist/memory/memoryTree.d.ts +76 -0
- package/dist/memory/memoryTree.d.ts.map +1 -0
- package/dist/memory/memoryTree.js +185 -130
- package/dist/memory/memoryTree.js.map +1 -0
- package/dist/memory/obsidianVault.d.ts +71 -0
- package/dist/memory/obsidianVault.d.ts.map +1 -0
- package/dist/memory/obsidianVault.js +207 -22
- package/dist/memory/obsidianVault.js.map +1 -0
- package/dist/providers/providerConfig.d.ts +49 -0
- package/dist/providers/providerConfig.d.ts.map +1 -0
- package/dist/providers/providerConfig.js +806 -401
- package/dist/providers/providerConfig.js.map +1 -0
- package/dist/security/guardrails.d.ts +76 -0
- package/dist/security/guardrails.d.ts.map +1 -0
- package/dist/security/guardrails.js +479 -0
- package/dist/security/guardrails.js.map +1 -0
- package/dist/security/inputValidation.js +351 -0
- package/dist/server/dashboard.d.ts +58 -0
- package/dist/server/dashboard.d.ts.map +1 -0
- package/dist/server/dashboard.js +553 -0
- package/dist/server/dashboard.js.map +1 -0
- package/dist/server/modelMapper.d.ts +43 -0
- package/dist/server/modelMapper.d.ts.map +1 -0
- package/dist/server/modelMapper.js +154 -0
- package/dist/server/modelMapper.js.map +1 -0
- package/dist/server/proxyServer.d.ts +41 -0
- package/dist/server/proxyServer.d.ts.map +1 -0
- package/dist/server/proxyServer.js +932 -0
- package/dist/server/proxyServer.js.map +1 -0
- package/dist/skills/__tests__/skill_manager.test.d.ts +2 -0
- package/dist/skills/__tests__/skill_manager.test.d.ts.map +1 -0
- package/dist/skills/__tests__/skill_manager.test.js +268 -0
- package/dist/skills/__tests__/skill_manager.test.js.map +1 -0
- package/docs/geo/GENERATIVE_ENGINE_OPTIMIZATION.md +232 -0
- package/docs-site/index.html +347 -0
- package/llms.txt +138 -0
- package/package.json +72 -7
- package/playground/README.md +51 -0
- package/playground/codesandbox.json +12 -0
- package/playground/index.js +39 -0
- package/scripts/update-npm-badges.js +158 -0
- package/src/analytics/costAnalytics.ts +304 -0
- package/src/cache/semanticCache.ts +221 -0
- package/src/index.ts +6 -0
- package/src/integrations/langchainAdapter.ts +955 -0
- package/src/providers/providerConfig.ts +923 -0
- package/src/security/guardrails.ts +585 -0
- package/src/server/dashboard.ts +610 -0
- package/src/server/modelMapper.ts +182 -0
- package/src/server/proxyServer.ts +1105 -0
- package/src/types/langchain.d.ts +83 -0
- package/tsconfig.build.json +20 -0
|
@@ -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
|
+
};
|