2025-03-20 21:48:06 +00:00

134 lines
3.8 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): 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 = {
...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,
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) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
.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++;
const token: ApiToken = {
...tokenData,
id,
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): Promise<ApiToken | undefined> {
const existingToken = this.tokensStore.get(id);
if (!existingToken) return undefined;
const updatedToken = { ...existingToken, token };
this.tokensStore.set(id, updatedToken);
return updatedToken;
}
}
export const storage = new MemStorage();