2 Commits

Author SHA1 Message Date
jaandrle 97983aff87 Adds api 2026-06-11 15:07:51 +02:00
jaandrle c000517fd1 🔤 Adds plan 2026-06-11 15:07:17 +02:00
5 changed files with 112 additions and 1 deletions
+39
View File
@@ -0,0 +1,39 @@
# Basic Episodes Fetch
## Overview
This plan focuses on adding a minimal **episodesfetch** feature that pulls podcast episodes from the CommaFeed backend
using environment variables for configuration.
The plan is derived from:
- `docs/dev/README.md` (API endpoints, authentication)
- `src/` structure and existing route system
- Build scripts in `bs/` only linting is required at this stage.
## Tasks
1. **API client** (DONE)
- Adds `src/api` folder to the project structure (update also @src/README.md).
- Implement a lightweight wrapper around `fetch` in `src/api/fetchAPI.ts`.
- Build `authHeader()` that returns the BasicAuth header using for now hardcoded vars.
1. **Episode service** (DONE)
- Add `src/api/episodes.ts` with `getEpisodes(feedId)` and `getEpisode(id)`.
- Add data types
- Use `/rest/feed/entries?feed_id=${feedId}` endpoint.
1. **Page update** (TODO)
- Add fetching all episodes
- Update `<app-episodes>` to reflect loading state(s).
- Add episode list item component.
- Update `<app-episodes>` to render the episode list received from the route context.
1. **Testing** (TODO)
- Add unit tests for `api/*.ts` using project test setup.
- Add unit test for created component(s)
1. **Linting** (TODO)
- Ensure all new files satisfy the lint rule defined in `bs/dev/lint`.
## Expected Output
- Visiting `/episodes/` will display a list of episodes fetched from CommaFeed.
- Episodes are identified by their `id` and displayed with title, publish date, and an audio link if available.
- Authentication uses the env variables; no credentials are hardcoded in source.
---
> **Note**: This plan intentionally keeps external dependencies minimal. It can be extended later for pagination, caching, or offline support.
+1
View File
@@ -2,3 +2,4 @@
- [x] initial setup (`bs`, app structure, …) - [x] initial setup (`bs`, app structure, …)
- [x] adds routing support - [x] adds routing support
- [ ] [episodes basic fetch](./plans/plan-basic-episodes.md)
+36
View File
@@ -0,0 +1,36 @@
import { fetchAPI } from "./fetchAPI.js";
export interface Episode {
id: string;
title: string;
published: string; // ISO string or similar
audio_url?: string;
description?: string;
}
export interface FeedEntriesResponse {
entries: Episode[];
}
/**
* Fetches all entries for a given feed.
* @param feedId - The ID of the feed.
*/
export async function getEpisodes(feedId: string= "all"): Promise<Episode[]> {
const response = await fetchAPI(`feed/entries?feed_id=${feedId}`);
if (!response.ok)
throw new Error(`Failed to fetch episodes: ${response.statusText}`);
const data = await response.json() as FeedEntriesResponse;
return data.entries || [];
}
/**
* Fetches a single episode by its ID.
* @param id - The ID of the episode.
*/
export async function getEpisode(id: string): Promise<Episode> {
const response = await fetchAPI(`feed/entry/${id}/`);
if (!response.ok)
throw new Error(`Failed to fetch episode: ${response.statusText}`);
return await response.json() as Episode;
}
+34
View File
@@ -0,0 +1,34 @@
const url_server = "https://rss.jaandrle.cz";
const url_base = `${url_server}/rest`;
// @ts-expect-error S7016
import { users } from "ENV";
const [ username, password ] = users[0].split(':');
console.log(import.meta);
/**
* Generates the Basic Authentication header.
*/
export function authHeader(): string {
const credentials = btoa(`${username}:${password}`);
return `Basic ${credentials}`;
}
/**
* A lightweight wrapper around fetch for the CommaFeed API.
* @param endpoint - The API endpoint (e.g., '/rest/feed/')
* @param options - Fetch options
*/
export async function fetchAPI(endpoint: string, options: RequestInit = {}): Promise<Response> {
const url = `${url_base}/${endpoint}`;
const auth = authHeader();
const headers = new Headers(options.headers);
headers.set('Authorization', auth);
return fetch(url, {
...options,
headers,
});
}
+2 -1
View File
@@ -34,7 +34,8 @@
"types": ["mocha"], "types": ["mocha"],
"lib": ["es2021", "dom", "DOM.Iterable"], "lib": ["es2021", "dom", "DOM.Iterable"],
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"],
"ENV": ["./.env.js"]
} }
}, },
"include": ["**/*.ts"] "include": ["**/*.ts"]