fix(podcast): Improve podcast episode validation, make Feed.itemIds protected, expand README and add tests

This commit is contained in:
2025-10-31 19:36:23 +00:00
parent e444c80769
commit 59c9ccf871
7 changed files with 1135 additions and 78 deletions

View File

@@ -1,6 +1,7 @@
import * as plugins from './plugins.js';
import * as validation from './validation.js';
import { Feed, IFeedOptions, IFeedItem } from './classes.feed.js';
import { Feed } from './classes.feed.js';
import type { IFeedOptions, IFeedItem } from './classes.feed.js';
/**
* iTunes podcast owner information
@@ -14,7 +15,7 @@ export interface IPodcastOwner {
/**
* Configuration options for creating a podcast feed
* Extends standard feed options with iTunes-specific fields
* Extends standard feed options with iTunes-specific and Podcast 2.0 fields
*/
export interface IPodcastFeedOptions extends IFeedOptions {
/** iTunes category (e.g., 'Technology', 'Comedy', 'News') */
@@ -37,6 +38,16 @@ export interface IPodcastFeedOptions extends IFeedOptions {
copyright?: string;
/** Language code (overrides default 'en') */
language?: string;
// Podcast 2.0 namespace fields
/** Globally unique identifier for the podcast (GUID) - required for Podcast 2.0 */
podcastGuid: string;
/** The medium of the podcast content (defaults to 'podcast') */
podcastMedium?: 'podcast' | 'music' | 'video' | 'film' | 'audiobook' | 'newsletter' | 'blog';
/** Whether the podcast is locked to prevent unauthorized imports (defaults to false) */
podcastLocked?: boolean;
/** Email/contact of who can unlock the podcast if locked (required if podcastLocked is true) */
podcastLockOwner?: string;
}
/**
@@ -211,9 +222,10 @@ export class PodcastFeed extends Feed {
*/
public addEpisode(episodeArg: IPodcastItem): void {
// Validate standard item fields first
// Note: itunesDuration is validated separately to allow for proper numeric validation
validation.validateRequiredFields(
episodeArg,
['title', 'timestamp', 'url', 'authorName', 'imageUrl', 'content', 'audioUrl', 'audioType', 'audioLength', 'itunesDuration'],
['title', 'timestamp', 'url', 'authorName', 'imageUrl', 'content', 'audioUrl', 'audioType', 'audioLength'],
'Podcast episode'
);
@@ -235,7 +247,10 @@ export class PodcastFeed extends Feed {
throw new Error('Audio length must be a positive number (bytes)');
}
// Validate duration
// Validate duration (must be provided and be a positive number)
if (episodeArg.itunesDuration === undefined || episodeArg.itunesDuration === null) {
throw new Error('iTunes duration is required');
}
if (typeof episodeArg.itunesDuration !== 'number' || episodeArg.itunesDuration <= 0) {
throw new Error('iTunes duration must be a positive number (seconds)');
}