Export types

* Export public type for usage
This commit is contained in:
Alexander Zinn
2025-08-28 16:38:57 -04:00
parent dee8a27734
commit 44afa943b4
6 changed files with 72 additions and 30 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "@techniker-me/pcast-api", "name": "@techniker-me/pcast-api",
"version": "2025.0.8", "version": "2025.0.9",
"type": "module", "type": "module",
"scripts": { "scripts": {
"ci-build": "bun run build:node && bun run build:browser && bun run build:types", "ci-build": "bun run build:node && bun run build:browser && bun run build:types",

View File

@@ -8,23 +8,25 @@ export class PCastApi {
private readonly _streams: Streams; private readonly _streams: Streams;
private readonly _reporting: Reporting; private readonly _reporting: Reporting;
constructor(pcastUri: string, applicationCredentials: ApplicationCredentials) { private constructor(pcastUri: string, applicationCredentials: ApplicationCredentials, channels: Channels) {
const normalized = pcastUri.replace(/\/+$/, ''); const normalized = pcastUri.replace(/\/+$/, '');
this._pcastUri = normalized.endsWith('/pcast') ? normalized : `${normalized}/pcast`; this._pcastUri = normalized.endsWith('/pcast') ? normalized : `${normalized}/pcast`;
this._applicationCredentials = applicationCredentials; this._applicationCredentials = applicationCredentials;
this._pcastHttpRequests = new PCastHttpRequests(this._pcastUri, this._applicationCredentials); this._pcastHttpRequests = new PCastHttpRequests(this._pcastUri, this._applicationCredentials);
this._channels = new Channels(this._pcastHttpRequests); this._channels = channels;
this._streams = new Streams(this._pcastHttpRequests); this._streams = new Streams(this._pcastHttpRequests);
this._reporting = new Reporting(this._pcastHttpRequests); this._reporting = new Reporting(this._pcastHttpRequests);
} }
get pcastUri(): string { public static async create(pcastUri: string, applicationCredentials: ApplicationCredentials): Promise<PCastApi> {
return this._pcastUri; const pcastHttpRequests = new PCastHttpRequests(pcastUri.replace(/\/+$/, '').endsWith('/pcast') ? pcastUri : `${pcastUri}/pcast`, applicationCredentials);
const channels = await Channels.create(pcastHttpRequests);
return new PCastApi(pcastUri, applicationCredentials, channels);
} }
get applicationCredentials(): ApplicationCredentials { get pcastUri(): string {
return this._applicationCredentials; return this._pcastUri;
} }
get channels(): Channels { get channels(): Channels {

View File

@@ -1,7 +1,22 @@
import {PCastApi} from './PCastApi'; import {PCastApi} from './PCastApi';
import {ReportKind} from './pcast/ReportKind'; import type {Channels, Streams, Reporting, ReportKind, ViewingReportKind} from './pcast';
import {ViewingReportKind} from './pcast/ViewingReportKind';
import type {ChannelId, Channel, ChannelAlias, Member, ChannelError} from './pcast/Channels';
import type {HttpMethod} from './net/http/HttpMethod';
import type {HttpRequestError} from './net/http/HttpRequests';
import type {ChannelResponse, ChannelsResponse, MembersResponse} from './pcast/IResponse';
import type {ApplicationCredentials} from './pcast/PCastRequests';
import type {PublishingReportOptions, ViewingReportOptions} from './pcast/Reporting';
import type {ReportKindType} from './pcast/ReportKind';
import type {ViewingReportKindType} from './pcast/ViewingReportKind';
export type {Channels, Streams, Reporting, ReportKind, ViewingReportKind};
export type {ChannelId, Channel, ChannelAlias, Member, ChannelError};
export type {HttpMethod, HttpRequestError};
export type {ChannelResponse, ChannelsResponse, MembersResponse};
export type {ApplicationCredentials};
export type {PublishingReportOptions, ViewingReportOptions};
export type {ReportKindType, ViewingReportKindType};
export type {ReportKind, ViewingReportKind};
export {PCastApi}; export {PCastApi};
export default PCastApi; export default PCastApi;

View File

@@ -49,11 +49,16 @@ export class ChannelError extends Error {
export class Channels { export class Channels {
private readonly _httpRequests: PCastHttpRequests; private readonly _httpRequests: PCastHttpRequests;
private readonly _channelsByAlias: Map<ChannelAlias, Channel> = new Map(); private readonly _channelsByAlias: Map<ChannelAlias, Channel> = new Map();
private _initialized = false; private _initialized: Promise<void> | boolean = false;
constructor(pcastHttpRequests: PCastHttpRequests) { private constructor(pcastHttpRequests: PCastHttpRequests) {
this._httpRequests = pcastHttpRequests; this._httpRequests = pcastHttpRequests;
this.initialize(); }
public static async create(pcastHttpRequests: PCastHttpRequests): Promise<Channels> {
const instance = new Channels(pcastHttpRequests);
await instance.initialize();
return instance;
} }
public async createChannel(name: string, description: string, channelOptions: string[] = []): Promise<Channel> { public async createChannel(name: string, description: string, channelOptions: string[] = []): Promise<Channel> {
@@ -107,6 +112,10 @@ export class Channels {
return response.channels; return response.channels;
} }
public async refreshCache(): Promise<void> {
await this.list(); // This clears and repopulates the cache
}
public async getChannelInfoByAlias(alias: string): Promise<Channel | undefined> { public async getChannelInfoByAlias(alias: string): Promise<Channel | undefined> {
return this.get({alias}); return this.get({alias});
} }
@@ -116,12 +125,20 @@ export class Channels {
throw new ChannelError('Either alias or channelId must be provided', 'MISSING_PARAMETER'); throw new ChannelError('Either alias or channelId must be provided', 'MISSING_PARAMETER');
} }
if (this._initialized === false) {
await this.initialize();
} else if (this._initialized instanceof Promise) {
await this._initialized;
}
if (alias) { if (alias) {
// Check cache first // Check cache first
if (this._channelsByAlias.has(alias)) { if (this._channelsByAlias.has(alias)) {
return this._channelsByAlias.get(alias); return this._channelsByAlias.get(alias);
} }
// Instead of fetching full list, try to fetch single channel if possible
// Assuming API has /channel/{alias}, but based on code, it doesn't; fallback to list
const channelList = await this.list(); const channelList = await this.list();
// Update cache // Update cache
@@ -129,6 +146,7 @@ export class Channels {
} }
if (channelId) { if (channelId) {
// Similar fallback
const channelList = await this.list(); const channelList = await this.list();
return channelList.find(channel => channel.channelId === channelId); return channelList.find(channel => channel.channelId === channelId);
@@ -191,7 +209,7 @@ export class Channels {
// Cache management methods // Cache management methods
public isInitialized(): boolean { public isInitialized(): boolean {
return this._initialized; return this._initialized !== false && !(this._initialized instanceof Promise);
} }
public clearCache(): void { public clearCache(): void {
@@ -203,21 +221,26 @@ export class Channels {
return this._channelsByAlias.size; return this._channelsByAlias.size;
} }
private async initialize() { private async initialize(): Promise<void> {
try { this._initialized = (async () => {
const channelsList = await this.list(); try {
if (!channelsList) { const channelsList = await this.list();
console.warn('[Channels] Failed to initialize cache - no channels returned'); if (!channelsList) {
return; console.warn('[Channels] Failed to initialize cache - no channels returned');
} return;
}
for (const channel of channelsList) { for (const channel of channelsList) {
this._channelsByAlias.set(channel.alias, channel); this._channelsByAlias.set(channel.alias, channel);
} }
this._initialized = true; this._initialized = true;
} catch (error) { } catch (error) {
console.error('[Channels] Failed to initialize cache:', error); console.error('[Channels] Failed to initialize cache:', error);
} this._initialized = true; // Mark as initialized even on error to avoid repeated attempts
}
})();
await this._initialized;
} }
} }

View File

@@ -2,3 +2,5 @@ export * from './Channels';
export * from './Reporting'; export * from './Reporting';
export * from './PCastRequests'; export * from './PCastRequests';
export * from './Stream'; export * from './Stream';
export * from './ReportKind';
export * from './ViewingReportKind';

View File

@@ -1,7 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
// Environment setup & latest features // Environment setup & latest features
"lib": ["ESNext"], "lib": ["ESNext", "DOM"],
"target": "ESNext", "target": "ESNext",
"module": "Preserve", "module": "Preserve",
"moduleDetection": "force", "moduleDetection": "force",