
Replit-Commit-Author: Agent Replit-Commit-Session-Id: e931b5ab-041b-42e7-baf1-50017869cef6 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/e19c6a51-7e4c-4bb8-a6a6-46dc00f0ec99/e7d94eac-0455-4b75-b9dd-c4400d479872.jpg
145 lines
4.2 KiB
TypeScript
145 lines
4.2 KiB
TypeScript
import {
|
|
species, type Species, type InsertSpecies,
|
|
searches, type Search, type InsertSearch,
|
|
apiTokens, type ApiToken, type InsertApiToken
|
|
} from "@shared/schema";
|
|
|
|
export interface IStorage {
|
|
// Species methods
|
|
getSpecies(id: number): Promise<Species | undefined>;
|
|
getSpeciesByName(scientificName: string): Promise<Species | undefined>;
|
|
getAllSpecies(): Promise<Species[]>;
|
|
saveSpecies(speciesData: InsertSpecies): Promise<Species>;
|
|
|
|
// Search methods
|
|
addSearch(search: InsertSearch): Promise<Search>;
|
|
getRecentSearches(limit?: number): Promise<Search[]>;
|
|
|
|
// API Token methods
|
|
saveApiToken(token: InsertApiToken): Promise<ApiToken>;
|
|
getActiveToken(): Promise<ApiToken | undefined>;
|
|
updateToken(id: number, token: string, iucnToken?: string): Promise<ApiToken | undefined>;
|
|
}
|
|
|
|
export class MemStorage implements IStorage {
|
|
private speciesStore: Map<number, Species>;
|
|
private searchesStore: Map<number, Search>;
|
|
private tokensStore: Map<number, ApiToken>;
|
|
|
|
private speciesId: number;
|
|
private searchId: number;
|
|
private tokenId: number;
|
|
|
|
constructor() {
|
|
this.speciesStore = new Map();
|
|
this.searchesStore = new Map();
|
|
this.tokensStore = new Map();
|
|
|
|
this.speciesId = 1;
|
|
this.searchId = 1;
|
|
this.tokenId = 1;
|
|
}
|
|
|
|
// Species methods
|
|
async getSpecies(id: number): Promise<Species | undefined> {
|
|
return this.speciesStore.get(id);
|
|
}
|
|
|
|
async getSpeciesByName(scientificName: string): Promise<Species | undefined> {
|
|
return Array.from(this.speciesStore.values()).find(
|
|
(species) => species.scientificName.toLowerCase() === scientificName.toLowerCase()
|
|
);
|
|
}
|
|
|
|
async getAllSpecies(): Promise<Species[]> {
|
|
return Array.from(this.speciesStore.values()).sort(
|
|
(a, b) => new Date(b.searchedAt!).getTime() - new Date(a.searchedAt!).getTime()
|
|
);
|
|
}
|
|
|
|
async saveSpecies(speciesData: InsertSpecies): Promise<Species> {
|
|
const existing = await this.getSpeciesByName(speciesData.scientificName);
|
|
if (existing) {
|
|
// Update existing species with new data and timestamp
|
|
const updated: Species = {
|
|
...existing,
|
|
...speciesData,
|
|
searchedAt: new Date(),
|
|
};
|
|
this.speciesStore.set(existing.id, updated);
|
|
return updated;
|
|
}
|
|
|
|
const id = this.speciesId++;
|
|
const timestamp = new Date();
|
|
const species: Species = {
|
|
...(speciesData as any), // Cast to any to avoid TypeScript errors
|
|
id,
|
|
searchedAt: timestamp
|
|
};
|
|
this.speciesStore.set(id, species);
|
|
return species;
|
|
}
|
|
|
|
// Search methods
|
|
async addSearch(searchData: InsertSearch): Promise<Search> {
|
|
const id = this.searchId++;
|
|
const search: Search = {
|
|
...searchData,
|
|
id,
|
|
timestamp: new Date()
|
|
};
|
|
this.searchesStore.set(id, search);
|
|
return search;
|
|
}
|
|
|
|
async getRecentSearches(limit: number = 10): Promise<Search[]> {
|
|
return Array.from(this.searchesStore.values())
|
|
.sort((a, b) => {
|
|
const dateA = a.timestamp ? new Date(a.timestamp).getTime() : 0;
|
|
const dateB = b.timestamp ? new Date(b.timestamp).getTime() : 0;
|
|
return dateB - dateA;
|
|
})
|
|
.slice(0, limit);
|
|
}
|
|
|
|
// API Token methods
|
|
async saveApiToken(tokenData: InsertApiToken): Promise<ApiToken> {
|
|
// Deactivate all existing tokens
|
|
this.tokensStore.forEach((token) => {
|
|
token.isActive = false;
|
|
});
|
|
|
|
const id = this.tokenId++;
|
|
// Ensure all required fields are present
|
|
const token: ApiToken = {
|
|
id,
|
|
token: tokenData.token,
|
|
iucnToken: tokenData.iucnToken || null,
|
|
isActive: tokenData.isActive || true,
|
|
createdAt: new Date()
|
|
};
|
|
this.tokensStore.set(id, token);
|
|
return token;
|
|
}
|
|
|
|
async getActiveToken(): Promise<ApiToken | undefined> {
|
|
return Array.from(this.tokensStore.values()).find(token => token.isActive);
|
|
}
|
|
|
|
async updateToken(id: number, token: string, iucnToken?: string): Promise<ApiToken | undefined> {
|
|
const existingToken = this.tokensStore.get(id);
|
|
if (!existingToken) return undefined;
|
|
|
|
const updatedToken = {
|
|
...existingToken,
|
|
token,
|
|
...(iucnToken !== undefined ? { iucnToken } : {})
|
|
};
|
|
this.tokensStore.set(id, updatedToken);
|
|
return updatedToken;
|
|
}
|
|
}
|
|
|
|
export const storage = new MemStorage();
|