justtcg-js
Version:
The official JavaScript/TypeScript SDK for the JustTCG API.
1 lines • 17.8 kB
Source Map (JSON)
{"version":3,"sources":["../src/core/http-client.ts","../src/core/response-handler.ts","../src/v1/resources/base.ts","../src/v1/resources/cards.ts","../src/v1/resources/games.ts","../src/v1/resources/sets.ts","../src/v1/index.ts","../src/index.ts"],"sourcesContent":["import { BatchLookupItem } from \"../types\";\n\nexport interface HttpClientConfig {\n apiKey: string;\n baseUrl: string;\n}\n\nexport interface QueryParams {\n [key: string]: string | string[] | number | boolean | undefined | null;\n}\n\ninterface BatchLookupItemStringified {\n /** A TCGplayer product ID. */\n tcgplayerId?: string;\n /** The TCGPlayer SKU of the specific variant. */\n tcgplayerSkuId?: string;\n /** A JustTCG card ID. */\n cardId?: string;\n /** A JustTCG variant ID. */\n variantId?: string;\n /** The Scryfall ID of the card. */\n scryfallId?: string;\n /** The MTGJSON ID of the card. */\n mtgjsonId?: string;\n /** Filer by Updated after a specific date in Unix timestamp format (seconds since epoch). */\n updated_after?: string;\n /** An array of card print types to filter by. */\n printing?: string;\n /** An array of card conditions to filter by. */\n condition?: string;\n /** Option to include price history in the response. */\n include_price_history?: string;\n /** Option to include specific timeframes for the price statistics. */\n include_statistics?: string;\n}\n\nexport class HttpClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n constructor(config: HttpClientConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl;\n }\n\n /**\n * Performs a GET request to a given path.\n * @param path The endpoint path (e.g., '/games').\n * @param params Optional query parameters.\n * @returns The JSON response from the API.\n */\n public async get<T>(path: string, params?: QueryParams): Promise<T> {\n const url = new URL(`${this.baseUrl}${path}`);\n\n // Safely append query parameters\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n });\n }\n\n const response = await fetch(url.toString(), {\n method: 'GET',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n // For now, we'll throw a generic error. We will enhance this later.\n const errorBody = await response.json();\n throw new Error(errorBody.error || 'An API error occurred');\n }\n\n return response.json() as Promise<T>;\n }\n\n /**\n * Performs a POST request to a given path.\n * @param path The endpoint path (e.g., '/cards').\n * @param body The JSON body for the request.\n * @returns The JSON response from the API.\n */\n public async post<T>(path: string, body: BatchLookupItem[]): Promise<T> {\n const url = new URL(`${this.baseUrl}${path}`);\n\n // Convert BatchLookupItem[] to BatchLookupItemStringified[]\n const stringifiedBody: BatchLookupItemStringified[] = body.map(item => {\n const stringifiedItem: BatchLookupItemStringified = {};\n if (item.tcgplayerId) stringifiedItem.tcgplayerId = item.tcgplayerId;\n if (item.tcgplayerSkuId) stringifiedItem.tcgplayerSkuId = item.tcgplayerSkuId;\n if (item.cardId) stringifiedItem.cardId = item.cardId;\n if (item.variantId) stringifiedItem.variantId = item.variantId;\n if (item.scryfallId) stringifiedItem.scryfallId = item.scryfallId;\n if (item.mtgjsonId) stringifiedItem.mtgjsonId = item.mtgjsonId;\n if (item.printing) stringifiedItem.printing = Array.isArray(item.printing) ? item.printing.join(',') : item.printing;\n if (item.condition) stringifiedItem.condition = Array.isArray(item.condition) ? item.condition.join(',') : item.condition;\n if (item.include_price_history !== undefined) stringifiedItem.include_price_history = String(item.include_price_history);\n if (item.include_statistics) stringifiedItem.include_statistics = Array.isArray(item.include_statistics) ? item.include_statistics.join(',') : item.include_statistics;\n if (item.updated_after !== undefined) stringifiedItem.updated_after = String(item.updated_after);\n return stringifiedItem;\n });\n\n console.log(stringifiedBody);\n const response = await fetch(url.toString(), {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(stringifiedBody),\n });\n\n if (!response.ok) {\n const errorBody = await response.json();\n throw new Error(errorBody.error || 'An API error occurred');\n }\n\n return response.json() as Promise<T>;\n }\n\n private getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey, // Add the API key header\n };\n }\n}\n","import { JustTCGApiResponse, PaginationMeta, UsageMeta } from '../types';\n\n/**\n * The raw shape of a successful response from the JustTCG API server.\n */\ninterface RawApiResponse<T> {\n data: T;\n meta?: {\n total: number;\n limit: number;\n offset: number;\n hasMore: boolean;\n };\n _metadata: {\n apiRequestLimit: number;\n apiRequestsUsed: number;\n apiRequestsRemaining: number;\n apiDailyLimit: number;\n apiDailyRequestsUsed: number;\n apiDailyRequestsRemaining: number;\n apiRateLimit: number;\n apiPlan: string;\n };\n error?: string;\n code?: string;\n}\n\n/**\n * Transforms a raw API response into the clean, structured format for the SDK user.\n * @param rawResponse The raw response object from the API.\n * @returns A JustTCGApiResponse object.\n */\nexport function handleResponse<T>(rawResponse: RawApiResponse<T>): JustTCGApiResponse<T> {\n const usage: UsageMeta = {\n apiRequestLimit: rawResponse._metadata.apiRequestLimit,\n apiDailyLimit: rawResponse._metadata.apiDailyLimit,\n apiRateLimit: rawResponse._metadata.apiRateLimit,\n apiRequestsUsed: rawResponse._metadata.apiRequestsUsed,\n apiDailyRequestsUsed: rawResponse._metadata.apiDailyRequestsUsed,\n apiRequestsRemaining: rawResponse._metadata.apiRequestsRemaining,\n apiDailyRequestsRemaining: rawResponse._metadata.apiDailyRequestsRemaining,\n apiPlan: rawResponse._metadata.apiPlan,\n };\n\n const pagination: PaginationMeta | undefined = rawResponse.meta\n ? {\n total: rawResponse.meta.total,\n limit: rawResponse.meta.limit,\n offset: rawResponse.meta.offset,\n hasMore: rawResponse.meta.hasMore,\n }\n : undefined;\n\n return {\n data: rawResponse.data,\n pagination,\n usage,\n ...(rawResponse.error && { error: rawResponse.error }),\n ...(rawResponse.code && { code: rawResponse.code }),\n };\n}\n","import { HttpClient, QueryParams } from '../../core/http-client';\nimport { BatchLookupItem } from '../../types';\n\nexport class BaseResource {\n protected httpClient: HttpClient;\n private pathPrefix: string;\n\n constructor(httpClient: HttpClient, pathPrefix: string) {\n this.httpClient = httpClient;\n this.pathPrefix = pathPrefix;\n }\n\n protected async _get<T>(path: string, params?: QueryParams): Promise<T> {\n // Parse 'query' parameter to the 'q' format expected by the API\n if (params && 'query' in params && typeof params.query === 'string') {\n params.q = params.query;\n delete params.query;\n }\n return this.httpClient.get<T>(`${this.pathPrefix}${path}`, params);\n }\n\n protected async _post<T>(path: string, body: BatchLookupItem[]): Promise<T> {\n return this.httpClient.post<T>(`${this.pathPrefix}${path}`, body);\n }\n}\n","import { handleResponse } from '../../core/response-handler';\nimport { BatchLookupItem, Card, GetCardsParams, JustTCGApiResponse, PaginationMeta, SearchCardsOptions, UsageMeta } from '../../types';\nimport { BaseResource } from './base';\n\ninterface RawCardsApiResponse {\n data: Card[];\n meta?: PaginationMeta;\n _metadata: UsageMeta;\n}\n\n/**\n * Provides access to the /cards API resource.\n */\nexport class CardsResource extends BaseResource {\n /**\n * Retrieves a paginated list of cards based on a flexible set of query parameters.\n * @param params Parameters for searching, filtering, and paginating cards.\n * @returns A Promise resolving to the JustTCG API response containing an array of Card objects.\n */\n public async get(params: GetCardsParams): Promise<JustTCGApiResponse<Card[]>> {\n const rawResponse = await this._get<RawCardsApiResponse>('/cards', params);\n return handleResponse(rawResponse);\n }\n\n /**\n * Retrieves a list of cards based on a batch of specific identifiers.\n * @param items An array of objects, each identifying a card to look up.\n * @returns A Promise resolving to the JustTCG API response containing an array of the requested Card objects.\n */\n public async getByBatch(items: BatchLookupItem[]): Promise<JustTCGApiResponse<Card[]>> {\n const rawResponse = await this._post<RawCardsApiResponse>('/cards', items);\n return handleResponse(rawResponse);\n }\n\n /**\n * A convenience method to search for cards by a query string.\n * This is a wrapper around the more flexible `get` method.\n * @param query A search query for the card's name.\n * @param options Optional parameters to filter or paginate the search results.\n * @returns A Promise resolving to the JustTCG API response containing an array of Card objects.\n */\n public async search(\n query: string,\n options?: SearchCardsOptions,\n ): Promise<JustTCGApiResponse<Card[]>> {\n // This helper calls our powerful 'get' method with a simplified set of options.\n const params: GetCardsParams = {\n query,\n ...options,\n };\n return this.get(params);\n }\n}\n","import { handleResponse } from '../../core/response-handler';\nimport { Game, JustTCGApiResponse, UsageMeta } from '../../types';\nimport { BaseResource } from './base';\n\n// Define the specific shape of the raw response for this endpoint\ninterface RawGamesApiResponse {\n data: Game[];\n _metadata: UsageMeta; // The games endpoint does not have pagination `meta`\n}\n\nexport class GamesResource extends BaseResource {\n /**\n * Retrieves a list of all supported games.\n * @returns A JustTCG API response containing an array of Game objects.\n */\n public async list(): Promise<JustTCGApiResponse<Game[]>> {\n // Use our new, strongly-typed interface instead of `any`\n const rawResponse = await this._get<RawGamesApiResponse>('/games');\n return handleResponse(rawResponse);\n }\n}\n","import { handleResponse } from '../../core/response-handler';\nimport { JustTCGApiResponse, PaginationMeta, Set, UsageMeta } from '../../types';\nimport { BaseResource } from './base';\n\n// Define the specific shape of the raw response for this endpoint\ninterface RawSetsApiResponse {\n data: Set[];\n meta: PaginationMeta; // The sets endpoint is paginated\n _metadata: UsageMeta;\n error?: string;\n code?: string;\n}\n\nexport class SetsResource extends BaseResource {\n /**\n * Retrieves a paginated list of sets, optionally filtered by game.\n * @param params Optional parameters to filter the list of sets.\n * @returns A JustTCG API response containing an array of Set objects.\n */\n public async list(params?: {\n /** The name of the game to filter sets by (e.g., 'Pokemon'). */\n game?: string;\n /** The maximum number of results to return. Default is 20. */\n limit?: number;\n /** The number of results to skip for pagination. */\n offset?: number;\n }): Promise<JustTCGApiResponse<Set[]>> {\n const rawResponse = await this._get<RawSetsApiResponse>('/sets', params);\n return handleResponse(rawResponse);\n }\n}\n","import { HttpClient } from '../core/http-client';\nimport { CardsResource } from './resources/cards';\nimport { GamesResource } from './resources/games';\nimport { SetsResource } from './resources/sets';\n\nexport class V1Client {\n public readonly games: GamesResource;\n public readonly sets: SetsResource;\n public readonly cards: CardsResource;\n\n constructor(httpClient: HttpClient) {\n const pathPrefix = '/v1';\n\n this.games = new GamesResource(httpClient, pathPrefix);\n this.sets = new SetsResource(httpClient, pathPrefix);\n this.cards = new CardsResource(httpClient, pathPrefix);\n }\n}\n","import { HttpClient } from './core/http-client';\nimport { V1Client } from './v1'; // Import the new V1Client\n\nconst API_BASE_URL = 'https://api.justtcg.com';\n\nexport interface JustTCGConfig {\n /**\n * Your JustTCG API key.\n * If not provided, the client will look for the `JUSTTCG_API_KEY` environment variable.\n */\n apiKey?: string;\n}\n\nexport class JustTCG {\n /** Provides access to the v1 version of the JustTCG API. */\n public readonly v1: V1Client;\n private readonly httpClient: HttpClient;\n\n /**\n * Creates an instance of the JustTCG client.\n * @param config Configuration options for the client.\n */\n constructor(config: JustTCGConfig = {}) {\n const apiKey = config.apiKey ?? process.env.JUSTTCG_API_KEY;\n\n if (!apiKey) {\n // We will replace this with a custom error later\n throw new Error('Authentication error: API key is missing.');\n }\n\n this.httpClient = new HttpClient({\n apiKey: apiKey,\n baseUrl: API_BASE_URL,\n });\n\n // Pass the httpClient instance to the V1Client\n this.v1 = new V1Client(this.httpClient);\n }\n}\n\n// Also, export our public types from the main entry point for user convenience\nexport * from './types';\n"],"mappings":"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","names":[]}