podscan 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +484 -0
- package/dist/index.cjs +630 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +849 -0
- package/dist/index.d.ts +849 -0
- package/dist/index.js +593 -0
- package/dist/index.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/http.ts","../src/paginator.ts","../src/resources/episodes.ts","../src/resources/podcasts.ts","../src/resources/alerts.ts","../src/resources/topics.ts","../src/resources/entities.ts","../src/resources/lists.ts","../src/resources/publishers.ts","../src/client.ts","../src/periods.ts"],"sourcesContent":["export { PodscanClient, type PodscanClientOptions } from './client.js';\nexport { PodscanError, type RateLimitInfo } from './http.js';\n\n// Convenience helpers\nexport { periods } from './periods.js';\nexport { Paginator } from './paginator.js';\n\n// Resource classes (for advanced usage / mocking)\nexport { EpisodesResource } from './resources/episodes.js';\nexport { PodcastsResource } from './resources/podcasts.js';\nexport { AlertsResource } from './resources/alerts.js';\nexport { TopicsResource } from './resources/topics.js';\nexport { EntitiesResource } from './resources/entities.js';\nexport { ListsResource } from './resources/lists.js';\nexport { PublishersResource } from './resources/publishers.js';\n\n// All types\nexport type {\n // Common\n Pagination,\n Quota,\n Sentiment,\n SortDirection,\n SearchHighlight,\n DateRange,\n Checkpoint,\n\n // Domain objects\n PodcastRef,\n Podcast,\n Episode,\n Category,\n Publisher,\n EpisodeMetadata,\n HostInfo,\n GuestInfo,\n SponsorInfo,\n FirstOccurrence,\n TopicSummary,\n TopicOccurrence,\n TopicMomentum,\n Topic,\n TopicEpisodeOccurrence,\n TrendingTopic,\n Entity,\n EntityAppearanceCounts,\n EntityAppearance,\n Alert,\n Mention,\n ListSummary,\n ListItem,\n\n // Episodes\n SearchEpisodesParams,\n SearchEpisodesResponse,\n GetEpisodeParams,\n GetEpisodeResponse,\n GetRecentEpisodesParams,\n GetRecentEpisodesResponse,\n GetPodcastEpisodesParams,\n GetPodcastEpisodesResponse,\n\n // Podcasts\n SearchPodcastsParams,\n SearchPodcastsResponse,\n GetPodcastParams,\n GetPodcastResponse,\n\n // Entities\n SearchEntitiesParams,\n SearchEntitiesResponse,\n GetEntityParams,\n GetEntityResponse,\n GetEntityAppearancesParams,\n GetEntityAppearancesResponse,\n\n // Topics\n SearchTopicsParams,\n SearchTopicsResponse,\n GetTopicParams,\n GetTopicResponse,\n GetTopicEpisodesParams,\n GetTopicEpisodesResponse,\n GetTrendingTopicsParams,\n GetTrendingTopicsResponse,\n\n // Alerts\n ListAlertsParams,\n ListAlertsResponse,\n GetAlertMentionsParams,\n GetAlertMentionsResponse,\n CreateAlertParams,\n CreateAlertResponse,\n\n // Lists\n ListUserListsParams,\n ListUserListsResponse,\n GetListItemsParams,\n GetListItemsResponse,\n AddToListParams,\n AddToListResponse,\n\n // Publishers\n GetPublisherParams,\n GetPublisherResponse,\n} from './types.js';\n","export interface HttpClientOptions {\n apiKey: string;\n baseUrl?: string;\n timeout?: number;\n}\n\nexport interface RateLimitInfo {\n limit: number;\n remaining: number;\n used: number;\n resetsAt: string | null;\n}\n\nexport interface PodscanErrorDetails {\n code: string;\n message: string;\n status: number;\n details?: Record<string, unknown>;\n}\n\nexport class PodscanError extends Error {\n readonly code: string;\n readonly status: number;\n readonly details?: Record<string, unknown>;\n\n constructor({ code, message, status, details }: PodscanErrorDetails) {\n super(message);\n this.name = 'PodscanError';\n this.code = code;\n this.status = status;\n this.details = details;\n }\n}\n\nexport class HttpClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n rateLimit: RateLimitInfo | null = null;\n\n constructor(options: HttpClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? 'https://podscan.fm/api/v1';\n this.timeout = options.timeout ?? 30_000;\n }\n\n async get<T>(path: string, params?: object): Promise<T> {\n const url = this.buildUrl(path, params as Record<string, unknown> | undefined);\n return this.request<T>(url, { method: 'GET' });\n }\n\n async post<T>(path: string, body?: object): Promise<T> {\n const url = this.buildUrl(path);\n return this.request<T>(url, {\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n private buildUrl(path: string, params?: Record<string, unknown>): string {\n const url = new URL(`${this.baseUrl}${path}`);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n const serialized =\n typeof value === 'object'\n ? JSON.stringify(value)\n : String(value as string | number | boolean);\n url.searchParams.set(key, serialized);\n }\n }\n }\n\n return url.toString();\n }\n\n private async request<T>(url: string, init: RequestInit): Promise<T> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, this.timeout);\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n });\n\n this.parseRateLimitHeaders(response.headers);\n\n if (!response.ok) {\n const errorBody = (await response.json().catch(() => null)) as Record<\n string,\n unknown\n > | null;\n throw new PodscanError({\n code: typeof errorBody?.code === 'string' ? errorBody.code : 'api_error',\n message:\n typeof errorBody?.message === 'string'\n ? errorBody.message\n : `HTTP ${String(response.status)}: ${response.statusText}`,\n status: response.status,\n details: errorBody?.details as Record<string, unknown> | undefined,\n });\n }\n\n return (await response.json()) as T;\n } catch (error: unknown) {\n if (error instanceof PodscanError) throw error;\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new PodscanError({\n code: 'timeout',\n message: `Request timed out after ${String(this.timeout)}ms`,\n status: 0,\n });\n }\n\n throw new PodscanError({\n code: 'network_error',\n message: error instanceof Error ? error.message : 'Unknown network error',\n status: 0,\n });\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private parseRateLimitHeaders(headers: Headers): void {\n const limit = headers.get('x-ratelimit-limit');\n const remaining = headers.get('x-ratelimit-remaining');\n const used = headers.get('x-ratelimit-used');\n const resetsAt = headers.get('x-ratelimit-reset');\n\n if (limit ?? remaining) {\n this.rateLimit = {\n limit: limit ? parseInt(limit, 10) : 0,\n remaining: remaining ? parseInt(remaining, 10) : 0,\n used: used ? parseInt(used, 10) : 0,\n resetsAt: resetsAt ?? null,\n };\n }\n }\n}\n","import type { Checkpoint, Pagination } from './types.js';\n\n/**\n * A function that fetches one page of results.\n * The paginator calls it with incrementing page numbers.\n */\nexport type PageFetcher<T> = (page: number) => Promise<{\n items: T[];\n pagination: Pagination;\n}>;\n\n/**\n * Extracts the `posted_at` or `created_at` timestamp from an item, if present.\n * Used internally for checkpoint tracking.\n */\nfunction extractTimestamp(item: unknown): string | null {\n if (item && typeof item === 'object') {\n const record = item as Record<string, unknown>;\n if (typeof record.posted_at === 'string') return record.posted_at;\n if (typeof record.created_at === 'string') return record.created_at;\n }\n return null;\n}\n\n/**\n * Extracts an ID field from an item (tries common patterns).\n */\nfunction extractId(item: unknown): string | null {\n if (item && typeof item === 'object') {\n const record = item as Record<string, unknown>;\n for (const key of [\n 'episode_id',\n 'podcast_id',\n 'topic_id',\n 'entity_id',\n 'alert_id',\n 'mention_id',\n ]) {\n if (typeof record[key] === 'string') return record[key];\n }\n }\n return null;\n}\n\n/**\n * An async-iterable paginator that walks through all pages of a paginated\n * API response, yielding individual items.\n *\n * ```ts\n * const paginator = new Paginator(async (page) => {\n * const res = await client.episodes.search({ query: 'AI', page, per_page: 50 });\n * return { items: res.episodes, pagination: res.pagination };\n * });\n *\n * for await (const episode of paginator) {\n * console.log(episode.episode_title);\n * }\n *\n * console.log(paginator.checkpoint());\n * ```\n */\nexport class Paginator<T> implements AsyncIterable<T> {\n private readonly fetcher: PageFetcher<T>;\n private _totalSeen = 0;\n private _lastSeenAt: string | null = null;\n private _lastSeenId: string | null = null;\n\n constructor(fetcher: PageFetcher<T>) {\n this.fetcher = fetcher;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n let currentPage = 1;\n let lastPage = 1;\n\n do {\n const result = await this.fetcher(currentPage);\n lastPage = result.pagination.last_page;\n\n for (const item of result.items) {\n this._totalSeen++;\n const ts = extractTimestamp(item);\n const id = extractId(item);\n if (ts) this._lastSeenAt = ts;\n if (id) this._lastSeenId = id;\n yield item;\n }\n\n currentPage++;\n } while (currentPage <= lastPage);\n }\n\n /**\n * Returns a checkpoint representing the sync position after iteration.\n * Save this and pass `checkpoint.lastSeenAt` as `since` on the next run\n * to only fetch new items.\n */\n checkpoint(): Checkpoint {\n return {\n lastSeenAt: this._lastSeenAt ?? '',\n lastSeenId: this._lastSeenId ?? '',\n totalSeen: this._totalSeen,\n };\n }\n\n /** Total number of items yielded so far. */\n get totalSeen(): number {\n return this._totalSeen;\n }\n}\n","import type { HttpClient } from '../http.js';\nimport { Paginator } from '../paginator.js';\nimport type {\n Episode,\n SearchEpisodesParams,\n SearchEpisodesResponse,\n GetEpisodeParams,\n GetEpisodeResponse,\n GetRecentEpisodesParams,\n GetRecentEpisodesResponse,\n GetPodcastEpisodesParams,\n GetPodcastEpisodesResponse,\n} from '../types.js';\n\nexport class EpisodesResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Full-text search across podcast episode transcripts, titles, and descriptions.\n */\n async search(params: SearchEpisodesParams): Promise<SearchEpisodesResponse> {\n return this.http.get<SearchEpisodesResponse>('/episodes/search', params);\n }\n\n /**\n * Auto-paginating search that yields every matching episode across all pages.\n *\n * ```ts\n * for await (const episode of client.episodes.searchAll({ query: 'AI', ...periods.thisWeek() })) {\n * console.log(episode.episode_title);\n * }\n * ```\n */\n searchAll(params: Omit<SearchEpisodesParams, 'page'>): Paginator<Episode> {\n return new Paginator(async (page) => {\n const res = await this.search({ ...params, page });\n return { items: res.episodes, pagination: res.pagination };\n });\n }\n\n /**\n * Get detailed information about a specific episode.\n */\n async get(params: GetEpisodeParams): Promise<GetEpisodeResponse> {\n const { episode_id, ...query } = params;\n return this.http.get<GetEpisodeResponse>(`/episodes/${episode_id}`, query);\n }\n\n /**\n * Get the most recently published podcast episodes.\n */\n async getRecent(params?: GetRecentEpisodesParams): Promise<GetRecentEpisodesResponse> {\n return this.http.get<GetRecentEpisodesResponse>('/episodes/recent', params);\n }\n\n /**\n * List all episodes for a specific podcast.\n */\n async getByPodcast(params: GetPodcastEpisodesParams): Promise<GetPodcastEpisodesResponse> {\n const { podcast_id, ...query } = params;\n return this.http.get<GetPodcastEpisodesResponse>(`/podcasts/${podcast_id}/episodes`, query);\n }\n\n /**\n * Auto-paginating version of `getByPodcast()` that yields every episode.\n *\n * ```ts\n * for await (const ep of client.episodes.getByPodcastAll({\n * podcast_id: 'pd_abc',\n * ...periods.thisMonth(),\n * })) {\n * console.log(ep.episode_title);\n * }\n * ```\n */\n getByPodcastAll(params: Omit<GetPodcastEpisodesParams, 'page'>): Paginator<Episode> {\n return new Paginator(async (page) => {\n const res = await this.getByPodcast({ ...params, page });\n return { items: res.episodes, pagination: res.pagination };\n });\n }\n}\n","import type { HttpClient } from '../http.js';\nimport { Paginator } from '../paginator.js';\nimport type {\n Podcast,\n SearchPodcastsParams,\n SearchPodcastsResponse,\n GetPodcastParams,\n GetPodcastResponse,\n} from '../types.js';\n\nexport class PodcastsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Search podcasts by name, topic, or characteristics.\n */\n async search(params: SearchPodcastsParams): Promise<SearchPodcastsResponse> {\n return this.http.get<SearchPodcastsResponse>('/podcasts/search', params);\n }\n\n /**\n * Auto-paginating search that yields every matching podcast across all pages.\n */\n searchAll(params: Omit<SearchPodcastsParams, 'page'>): Paginator<Podcast> {\n return new Paginator(async (page) => {\n const res = await this.search({ ...params, page });\n return { items: res.podcasts, pagination: res.pagination };\n });\n }\n\n /**\n * Get detailed information about a specific podcast.\n */\n async get(params: GetPodcastParams): Promise<GetPodcastResponse> {\n const { podcast_id, ...query } = params;\n return this.http.get<GetPodcastResponse>(`/podcasts/${podcast_id}`, query);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type {\n ListAlertsParams,\n ListAlertsResponse,\n GetAlertMentionsParams,\n GetAlertMentionsResponse,\n CreateAlertParams,\n CreateAlertResponse,\n} from '../types.js';\n\nexport class AlertsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * List your team's content monitoring alerts.\n */\n async list(params?: ListAlertsParams): Promise<ListAlertsResponse> {\n return this.http.get<ListAlertsResponse>('/alerts', params);\n }\n\n /**\n * Get mentions found by a specific alert.\n */\n async getMentions(params: GetAlertMentionsParams): Promise<GetAlertMentionsResponse> {\n const { alert_id, ...query } = params;\n return this.http.get<GetAlertMentionsResponse>(`/alerts/${alert_id}/mentions`, query);\n }\n\n /**\n * Create a new content monitoring alert.\n */\n async create(params: CreateAlertParams): Promise<CreateAlertResponse> {\n return this.http.post<CreateAlertResponse>('/alerts', params);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport { Paginator } from '../paginator.js';\nimport type {\n Episode,\n TopicSummary,\n SearchTopicsParams,\n SearchTopicsResponse,\n GetTopicParams,\n GetTopicResponse,\n GetTopicEpisodesParams,\n GetTopicEpisodesResponse,\n GetTrendingTopicsParams,\n GetTrendingTopicsResponse,\n} from '../types.js';\n\nexport class TopicsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Discover topics and subjects discussed across podcasts.\n */\n async search(params: SearchTopicsParams): Promise<SearchTopicsResponse> {\n return this.http.get<SearchTopicsResponse>('/topics/search', params);\n }\n\n /**\n * Auto-paginating search that yields every matching topic across all pages.\n */\n searchAll(params: Omit<SearchTopicsParams, 'page'>): Paginator<TopicSummary> {\n return new Paginator(async (page) => {\n const res = await this.search({ ...params, page });\n return { items: res.topics, pagination: res.pagination };\n });\n }\n\n /**\n * Get detailed information about a specific topic.\n */\n async get(params: GetTopicParams): Promise<GetTopicResponse> {\n const { topic_id, ...query } = params;\n return this.http.get<GetTopicResponse>(`/topics/${topic_id}`, query);\n }\n\n /**\n * Get episodes where a specific topic was mentioned.\n */\n async getEpisodes(params: GetTopicEpisodesParams): Promise<GetTopicEpisodesResponse> {\n const { topic_id, ...query } = params;\n return this.http.get<GetTopicEpisodesResponse>(`/topics/${topic_id}/episodes`, query);\n }\n\n /**\n * Auto-paginating version of `getEpisodes()` that yields every episode for a topic.\n */\n getEpisodesAll(params: Omit<GetTopicEpisodesParams, 'page'>): Paginator<Episode> {\n return new Paginator(async (page) => {\n const res = await this.getEpisodes({ ...params, page });\n return { items: res.episodes, pagination: res.pagination };\n });\n }\n\n /**\n * Get currently trending topics across podcasts.\n */\n async getTrending(params?: GetTrendingTopicsParams): Promise<GetTrendingTopicsResponse> {\n return this.http.get<GetTrendingTopicsResponse>('/topics/trending', params);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport { Paginator } from '../paginator.js';\nimport type {\n Entity,\n SearchEntitiesParams,\n SearchEntitiesResponse,\n GetEntityParams,\n GetEntityResponse,\n GetEntityAppearancesParams,\n GetEntityAppearancesResponse,\n} from '../types.js';\n\nexport class EntitiesResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Search for people and organizations mentioned across podcasts.\n */\n async search(params: SearchEntitiesParams): Promise<SearchEntitiesResponse> {\n return this.http.get<SearchEntitiesResponse>('/entities/search', params);\n }\n\n /**\n * Auto-paginating search that yields every matching entity across all pages.\n */\n searchAll(params: Omit<SearchEntitiesParams, 'page'>): Paginator<Entity> {\n return new Paginator(async (page) => {\n const res = await this.search({ ...params, page });\n return { items: res.entities, pagination: res.pagination };\n });\n }\n\n /**\n * Get detailed information about a person or organization.\n */\n async get(params: GetEntityParams): Promise<GetEntityResponse> {\n const { entity_id, ...query } = params;\n return this.http.get<GetEntityResponse>(`/entities/${entity_id}`, query);\n }\n\n /**\n * Get all podcast appearances for a specific entity.\n */\n async getAppearances(params: GetEntityAppearancesParams): Promise<GetEntityAppearancesResponse> {\n const { entity_id, ...query } = params;\n return this.http.get<GetEntityAppearancesResponse>(`/entities/${entity_id}/appearances`, query);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type {\n ListUserListsParams,\n ListUserListsResponse,\n GetListItemsParams,\n GetListItemsResponse,\n AddToListParams,\n AddToListResponse,\n} from '../types.js';\n\nexport class ListsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Get all lists/collections for your team.\n */\n async list(params?: ListUserListsParams): Promise<ListUserListsResponse> {\n return this.http.get<ListUserListsResponse>('/lists', params);\n }\n\n /**\n * Get contents of a specific list.\n */\n async getItems(params: GetListItemsParams): Promise<GetListItemsResponse> {\n const { list_id, ...query } = params;\n return this.http.get<GetListItemsResponse>(`/lists/${list_id}/items`, query);\n }\n\n /**\n * Add items to a list. Accepts mixed item types (podcasts, episodes, entities, topics).\n */\n async addItems(params: AddToListParams): Promise<AddToListResponse> {\n const { list_id, ...body } = params;\n return this.http.post<AddToListResponse>(`/lists/${list_id}/items`, body);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { GetPublisherParams, GetPublisherResponse } from '../types.js';\n\nexport class PublishersResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Get publisher information with their podcast portfolio.\n */\n async get(params: GetPublisherParams): Promise<GetPublisherResponse> {\n const { publisher_id, ...query } = params;\n return this.http.get<GetPublisherResponse>(`/publishers/${publisher_id}`, query);\n }\n}\n","import { HttpClient } from './http.js';\nimport { EpisodesResource } from './resources/episodes.js';\nimport { PodcastsResource } from './resources/podcasts.js';\nimport { AlertsResource } from './resources/alerts.js';\nimport { TopicsResource } from './resources/topics.js';\nimport { EntitiesResource } from './resources/entities.js';\nimport { ListsResource } from './resources/lists.js';\nimport { PublishersResource } from './resources/publishers.js';\nimport type { RateLimitInfo } from './http.js';\n\nexport interface PodscanClientOptions {\n /** Your Podscan API key (Bearer token). */\n apiKey: string;\n /** Override the base URL (default: https://podscan.fm/api/v1). */\n baseUrl?: string;\n /** Request timeout in milliseconds (default: 30000). */\n timeout?: number;\n}\n\nexport class PodscanClient {\n private readonly http: HttpClient;\n\n /** Search and retrieve podcast episodes and recent content. */\n readonly episodes: EpisodesResource;\n /** Search and retrieve podcast metadata. */\n readonly podcasts: PodcastsResource;\n /** Create and manage keyword monitoring alerts and their mentions. */\n readonly alerts: AlertsResource;\n /** Search, retrieve, and track trending topics across podcasts. */\n readonly topics: TopicsResource;\n /** Search and retrieve people and organizations mentioned in podcasts. */\n readonly entities: EntitiesResource;\n /** Manage curated collections of podcasts, episodes, entities, and topics. */\n readonly lists: ListsResource;\n /** Retrieve publisher information and podcast portfolios. */\n readonly publishers: PublishersResource;\n\n constructor(options: PodscanClientOptions) {\n this.http = new HttpClient(options);\n\n this.episodes = new EpisodesResource(this.http);\n this.podcasts = new PodcastsResource(this.http);\n this.alerts = new AlertsResource(this.http);\n this.topics = new TopicsResource(this.http);\n this.entities = new EntitiesResource(this.http);\n this.lists = new ListsResource(this.http);\n this.publishers = new PublishersResource(this.http);\n }\n\n /** Current rate-limit info from the most recent API response, or null if no request has been made. */\n get rateLimit(): RateLimitInfo | null {\n return this.http.rateLimit;\n }\n}\n","import type { DateRange } from './types.js';\n\n/**\n * Computes an ISO 8601 UTC string for a Date.\n */\nfunction toISO(d: Date): string {\n return d.toISOString();\n}\n\n/**\n * Returns midnight UTC for a given date (strips time).\n */\nfunction startOfDayUTC(d: Date): Date {\n return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));\n}\n\n/**\n * Returns the Monday 00:00 UTC of the week containing the given date.\n */\nfunction startOfWeekUTC(d: Date): Date {\n const day = d.getUTCDay();\n const diff = day === 0 ? 6 : day - 1;\n const monday = new Date(d);\n monday.setUTCDate(d.getUTCDate() - diff);\n return startOfDayUTC(monday);\n}\n\n/**\n * Returns the 1st of the month at 00:00 UTC.\n */\nfunction startOfMonthUTC(d: Date): Date {\n return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1));\n}\n\n/**\n * Time period helpers for the Podscan SDK.\n *\n * Each method returns a `{ since, before? }` object that can be spread\n * directly into any search params:\n *\n * ```ts\n * const results = await client.episodes.search({\n * query: 'AI',\n * ...periods.thisWeek(),\n * });\n * ```\n */\nexport const periods = {\n /**\n * From midnight today (UTC) until now.\n */\n today(): DateRange {\n const now = new Date();\n return {\n since: toISO(startOfDayUTC(now)),\n };\n },\n\n /**\n * From midnight yesterday (UTC) to midnight today (UTC).\n */\n yesterday(): DateRange {\n const now = new Date();\n const todayStart = startOfDayUTC(now);\n const yesterdayStart = new Date(todayStart);\n yesterdayStart.setUTCDate(yesterdayStart.getUTCDate() - 1);\n return {\n since: toISO(yesterdayStart),\n before: toISO(todayStart),\n };\n },\n\n /**\n * Rolling window: now minus 24 hours.\n */\n last24Hours(): DateRange {\n const now = new Date();\n const past = new Date(now.getTime() - 24 * 60 * 60 * 1000);\n return {\n since: toISO(past),\n };\n },\n\n /**\n * From Monday 00:00 UTC of the current week until now.\n */\n thisWeek(): DateRange {\n const now = new Date();\n return {\n since: toISO(startOfWeekUTC(now)),\n };\n },\n\n /**\n * From Monday 00:00 UTC of last week to Monday 00:00 UTC of this week.\n */\n lastWeek(): DateRange {\n const now = new Date();\n const thisMonday = startOfWeekUTC(now);\n const lastMonday = new Date(thisMonday);\n lastMonday.setUTCDate(lastMonday.getUTCDate() - 7);\n return {\n since: toISO(lastMonday),\n before: toISO(thisMonday),\n };\n },\n\n /**\n * From the 1st of the current month (UTC) until now.\n */\n thisMonth(): DateRange {\n const now = new Date();\n return {\n since: toISO(startOfMonthUTC(now)),\n };\n },\n\n /**\n * From the 1st of last month to the 1st of this month (UTC).\n */\n lastMonth(): DateRange {\n const now = new Date();\n const thisMonth = startOfMonthUTC(now);\n const lastMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() - 1, 1));\n return {\n since: toISO(lastMonth),\n before: toISO(thisMonth),\n };\n },\n\n /**\n * Rolling window: now minus N days.\n */\n lastNDays(n: number): DateRange {\n const now = new Date();\n const past = new Date(now.getTime() - n * 24 * 60 * 60 * 1000);\n return {\n since: toISO(past),\n };\n },\n\n /**\n * Rolling window: now minus N hours.\n */\n lastNHours(n: number): DateRange {\n const now = new Date();\n const past = new Date(now.getTime() - n * 60 * 60 * 1000);\n return {\n since: toISO(past),\n };\n },\n\n /**\n * Everything after a given date. Accepts an ISO string or Date object.\n */\n since(date: string | Date): DateRange {\n const d = typeof date === 'string' ? new Date(date) : date;\n return {\n since: toISO(d),\n };\n },\n};\n"],"mappings":"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","names":[]}
|