The Econt SDK includes a powerful caching system that allows you to download all nomenclature data (countries, cities, offices, streets, quarters) once and use it offline. This dramatically improves performance and reduces API calls.
- One-command export - Download all data with
exportAllData() - Automatic fallback - Uses cache when available, API when not
- Smart filtering - Filter cached data in-memory (no API calls)
- TTL support - Automatic cache expiration
- Zero breaking changes - Works exactly as before without cache config
- TypeScript first - Fully typed with no
anytypes
import { EcontClient } from "econt";
const client = new EcontClient({
username: "your-username",
password: "your-password",
environment: "demo",
cache: {
enabled: true,
directory: "./econt-cache",
ttl: 86400000, // 24 hours (optional)
},
});// This downloads and caches all data
// Takes ~30-60 seconds
await client.exportAllData();// These automatically use cache when available
const countries = await client.offices.getCountries();
const cities = await client.offices.getCities({ countryCode: "BGR" });
const offices = await client.offices.list({ countryCode: "BGR" });
const streets = await client.offices.getStreets(cityId);
const quarters = await client.offices.getQuarters(cityId);After running exportAllData(), your cache directory contains:
econt-cache/
βββ countries.json (~20 KB - all 236 countries)
βββ cities.json (~500 KB - all 5,492 cities)
βββ offices.json (~800 KB - all 819 offices)
βββ streets.json (~5 MB - streets keyed by cityId)
βββ quarters.json (~100 KB - quarters keyed by cityId)
βββ metadata.json (export timestamp & version)
interface CacheConfig {
enabled: boolean; // Enable/disable caching
directory: string; // Path to cache directory
ttl?: number; // Time-to-live in milliseconds (default: 86400000 = 24h)
}Development (frequent updates):
cache: {
enabled: true,
directory: './cache',
ttl: 3600000, // 1 hour
}Production (stable data):
cache: {
enabled: true,
directory: '/var/cache/econt',
ttl: 604800000, // 7 days
}No caching:
// Simply omit the cache config
// or set enabled: false
cache: {
enabled: false,
directory: './cache',
}Downloads all nomenclature data from the API and saves to cache.
await client.exportAllData();What it exports:
- All countries (236)
- All cities (~5,492)
- All offices (~819)
- All streets (mapped by city ID)
- All quarters (mapped by city ID)
Time: ~30-60 seconds depending on network speed
Returns status of all cached files.
const status = client.getCacheStatus();
console.log(status);
// {
// countries: { exists: true, age: 3600000, expired: false },
// cities: { exists: true, age: 3600000, expired: false },
// offices: { exists: true, age: 3600000, expired: false },
// streets: { exists: true, age: 3600000, expired: false },
// quarters: { exists: true, age: 3600000, expired: false },
// metadata: { exists: true, age: 3600000, expired: false }
// }Returns null if caching is not enabled.
Deletes all cached files.
client.clearCache();Throws error if caching is not enabled.
All nomenclature methods support an optional forceRefresh parameter:
// From cache (if available)
const countries = await client.offices.getCountries();
// Force API call
const fresh = await client.offices.getCountries({ forceRefresh: true });// From cache, filtered in-memory
const cities = await client.offices.getCities({ countryCode: "BGR" });
// Force API call
const fresh = await client.offices.getCities({
countryCode: "BGR",
forceRefresh: true,
});list(params?: { countryCode?: string; cityId?: number; officeCode?: string; forceRefresh?: boolean })
// From cache, filtered in-memory
const offices = await client.offices.list({ countryCode: "BGR" });
// Force API call
const fresh = await client.offices.list({
countryCode: "BGR",
forceRefresh: true,
});// From cache
const streets = await client.offices.getStreets(41); // Sofia
// Search in cache
const filtered = await client.offices.getStreets(41, {
streetName: "ΠΠΈΡΠΎΡΠ°",
});
// Force API call
const fresh = await client.offices.getStreets(41, { forceRefresh: true });// From cache
const quarters = await client.offices.getQuarters(41);
// Force API call
const fresh = await client.offices.getQuarters(41, { forceRefresh: true });// On application startup (or via cron job)
const client = new EcontClient({
username: process.env.ECONT_USERNAME,
password: process.env.ECONT_PASSWORD,
cache: { enabled: true, directory: "./cache" },
});
// One-time: Export data
await client.exportAllData();
// Throughout your app: Use cached data
app.get("/api/cities", async (req, res) => {
// Instant response from cache
const cities = await client.offices.getCities({
countryCode: "BGR",
});
res.json(cities);
});
app.get("/api/offices/:cityId", async (req, res) => {
// Instant response from cache
const offices = await client.offices.list({
cityId: parseInt(req.params.cityId),
});
res.json(offices);
});
// Weekly refresh via cron
cron.schedule("0 0 * * 0", async () => {
await client.exportAllData();
});#!/usr/bin/env node
const client = new EcontClient({
username: process.env.ECONT_USERNAME,
password: process.env.ECONT_PASSWORD,
cache: { enabled: true, directory: "~/.econt-cache" },
});
// Check if cache exists
const status = client.getCacheStatus();
if (!status?.countries.exists) {
console.log("Downloading Econt data...");
await client.exportAllData();
}
// Use cached data
const offices = await client.offices.list();
console.log(`Found ${offices.length} offices`);// Cache to /tmp (ephemeral but faster than repeated API calls)
const client = new EcontClient({
username: process.env.ECONT_USERNAME,
password: process.env.ECONT_PASSWORD,
cache: {
enabled: true,
directory: "/tmp/econt-cache",
ttl: 3600000, // 1 hour
},
});
export const handler = async (event) => {
// Will use cache if available, fetch if not
const cities = await client.offices.getCities({ countryCode: "BGR" });
return {
statusCode: 200,
body: JSON.stringify(cities),
};
};getCountries(): ~500ms (API call)
getCities(): ~2000ms (API call)
list(): ~1500ms (API call)
getCountries(): ~2ms (from cache)
getCities(): ~5ms (from cache + filter)
list(): ~3ms (from cache + filter)
Result: ~200-500x faster π
// Option A: Periodic refresh (recommended for production)
setInterval(async () => {
await client.exportAllData();
}, 7 * 24 * 60 * 60 * 1000); // Weekly
// Option B: On-demand refresh
app.post("/admin/refresh-cache", async (req, res) => {
await client.exportAllData();
res.json({ success: true });
});
// Option C: Check expiration before use
const status = client.getCacheStatus();
if (status?.countries.expired) {
await client.exportAllData();
}try {
await client.exportAllData();
} catch (error) {
console.error("Cache export failed:", error);
// App continues to work - will use API calls
}// Ensure directory is writable
const cacheDir = "./econt-cache";
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir, { recursive: true, mode: 0o755 });
}# docker-compose.yml
services:
app:
volumes:
- ./econt-cache:/app/econt-cache// Use volume path
cache: {
enabled: true,
directory: '/app/econt-cache'
}A: No. Caching only applies to nomenclatures (countries, cities, offices, streets, quarters). Shipment operations always use the API.
A: The cache has a TTL (time-to-live). After expiration, the SDK automatically fetches fresh data from the API.
A: Yes, but you need to export the data elsewhere first and copy the cache directory to your read-only environment.
A: Approximately 6-7 MB for all data.
A: Currently, exportAllData() exports everything. You can manually cache specific data if needed, but the complete export is recommended.
A: The SDK version is stored in metadata.json. Clear the cache after SDK upgrades: client.clearCache()
A: Yes! Multiple processes can read from the same cache directory. However, only one process should call exportAllData() at a time.
// Check if caching is enabled
const status = client.getCacheStatus();
if (status === null) {
console.log("Caching is not enabled");
}# Fix cache directory permissions
chmod -R 755 ./econt-cache// Force refresh all data
await client.exportAllData();
// Or clear and re-export
client.clearCache();
await client.exportAllData();// Clear cache to free space
client.clearCache();See examples/cache-usage.ts for a complete working example.
# Run the example
npm install
npm run build
node examples/cache-usage.tsThe caching feature provides:
β
Dramatic performance improvements (~200-500x faster)
β
Reduced API costs (fewer calls = lower costs)
β
Offline capability (work without constant API access)
β
Zero code changes (transparent caching)
β
Smart filtering (in-memory operations)
β
Automatic fallback (uses API if cache unavailable)
Happy caching! π