1const CACHE_TTL_MS = 120_000; 2 3class PluginRegistry { 4 async getListings() { 5 throw new Error("not implemented"); 6 } 7 async getListing(id) { 8 const listings = await this.getListings(); 9 return listings.find((listing) => listing.id === id) ?? null; 10 } 11} 12 13export class RemotePluginRegistry extends PluginRegistry { 14 constructor(url) { 15 super(); 16 this.url = url; 17 this._cache = null; 18 } 19 20 async getListings() { 21 if (this._cache && Date.now() - this._cache.fetchedAt < CACHE_TTL_MS) { 22 return this._cache.listings; 23 } 24 const listings = await this._fetchListings(); 25 this._cache = { fetchedAt: Date.now(), listings }; 26 return listings; 27 } 28 29 async _fetchListings() { 30 const response = await fetch(this.url, { cache: "no-store" }); 31 if (!response.ok) throw new Error(`registry HTTP ${response.status}`); 32 return response.json(); 33 } 34} 35 36const LOCAL_INDEX_URL = "/plugins-local/index.json"; 37 38export class LocalPluginRegistry extends PluginRegistry { 39 async getListings() { 40 const response = await fetch(LOCAL_INDEX_URL); 41 if (!response.ok) { 42 throw new Error(`local registry HTTP ${response.status}`); 43 } 44 return response.json(); 45 } 46}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.