update legacy apis
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
"arrowParens": "avoid",
|
||||
"bracketSameLine": true,
|
||||
"bracketSpacing": false,
|
||||
"printWidth": 160,
|
||||
"printWidth": 180,
|
||||
"semi": true,
|
||||
"singleAttributePerLine": false,
|
||||
"singleQuote": true,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import PCastApi from '../../src/index';
|
||||
import PCastApi, {ReportKind} from '../../src/index';
|
||||
|
||||
const pcastUri = 'https://pcast-stg.phenixrts.com';
|
||||
const application = {
|
||||
@@ -6,34 +6,11 @@ const application = {
|
||||
secret: 'AMAsDzr.dIuGMZ.Zu52Dt~MQvP!DZwYg'
|
||||
};
|
||||
const pcastApi = PCastApi.create(pcastUri, application);
|
||||
const viewingReportRealTime = await pcastApi.generateViewingReport('RealTime', new Date('2025-08-02'), new Date('2025-09-01'), {});
|
||||
const publishingReport = await pcastApi.reporting.generateReport(ReportKind.Publishing, {
|
||||
start: '2025-08-02',
|
||||
end: '2025-09-01'
|
||||
});
|
||||
|
||||
console.log('pcastApi [%o]', pcastApi);
|
||||
console.log();
|
||||
console.log('ChannelsApi [%o]', pcastApi.channels);
|
||||
const channelsList = await pcastApi.channels.list();
|
||||
|
||||
// const start = hrtime.bigint();
|
||||
// const publishingReportCsv = await pcastApi.reporting.generateReport(ReportKind.Publishing, {
|
||||
// start: moment().subtract(1, 'day').toISOString(),
|
||||
// end: moment().toISOString(),
|
||||
// applicationIds: [application.id]
|
||||
// });
|
||||
// const endPublishing = hrtime.bigint();
|
||||
// console.log(publishingReportCsv);
|
||||
// console.log(`Time taken: ${Number(endPublishing - start) / 1_000_000_000} seconds`);
|
||||
|
||||
// const viewingReportCsv = await pcastApi.reporting.generateReport(ReportKind.Viewing, {
|
||||
// kind: ViewingReportKind.HLS,
|
||||
// start: moment().subtract(1, 'day').toISOString(),
|
||||
// end: moment().toISOString(),
|
||||
// applicationIds: [application.id]
|
||||
// });
|
||||
// const endViewing = hrtime.bigint();
|
||||
// console.log(`Time taken: ${Number(endViewing - endPublishing) / 1_000_000_000} seconds`);
|
||||
// // const viewingReport = await CsvParser.parse(viewingReportCsv);
|
||||
|
||||
// console.log(viewingReportCsv);
|
||||
|
||||
const channelMembers = await pcastApi.channels.getMembers(channelsList[1].channelId);
|
||||
console.log('[%o]', channelMembers);
|
||||
console.log('[%o]', channelMembers.streams);
|
||||
// console.log(viewingReportRealTime);
|
||||
console.log(publishingReport);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@techniker-me/pcast-api",
|
||||
"version": "2025.1.4",
|
||||
"version": "2025.1.5",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"ci-build": "bun run build",
|
||||
@@ -9,7 +9,7 @@
|
||||
"test:coverage": "bun test --coverage",
|
||||
"preformat": "bun install",
|
||||
"format": "prettier --write ./",
|
||||
"prelint": "bun format",
|
||||
"prelint:fix": "bun format",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"lint:fix": "eslint src/**/*.ts --fix",
|
||||
"build:node": "bun build src/index.ts --outdir dist/node --target node --format esm --production",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {Channels, Streams, type ApplicationCredentials, PCastHttpRequests, Reporting} from './apis';
|
||||
import {Channels, Streams, type ApplicationCredentials, PCastHttpRequests, Reporting, Channel, Member} from './apis';
|
||||
import {ReportKind, ViewingReportKindMapping, type ViewingReportKindType} from './apis/Reporting';
|
||||
|
||||
export class PCastApi {
|
||||
private readonly _channels: Channels;
|
||||
@@ -12,7 +13,8 @@ export class PCastApi {
|
||||
}
|
||||
|
||||
public static create(pcastUri: string, applicationCredentials: ApplicationCredentials): PCastApi {
|
||||
const pcastHttpRequests = new PCastHttpRequests(pcastUri.replace(/\/+$/, '').endsWith('/pcast') ? pcastUri : `${pcastUri}/pcast`, applicationCredentials);
|
||||
const pcastUriWithSuffix = pcastUri.replace(/\/+$/, '').endsWith('/pcast') ? pcastUri : `${pcastUri}/pcast`;
|
||||
const pcastHttpRequests = new PCastHttpRequests(pcastUriWithSuffix, applicationCredentials);
|
||||
const channels = new Channels(pcastHttpRequests);
|
||||
const streams = new Streams(pcastHttpRequests);
|
||||
const reporting = new Reporting(pcastHttpRequests);
|
||||
@@ -31,4 +33,55 @@ export class PCastApi {
|
||||
get reporting(): Reporting {
|
||||
return this._reporting;
|
||||
}
|
||||
|
||||
// ====== Legacy API =======
|
||||
// @deprecated - use pcastApi.channels.create instead
|
||||
public async createChannel(channelName: string, channelDescription: string, channelOptions: string[] = []): Promise<Channel> {
|
||||
return this._channels.create(channelName, channelDescription, channelOptions);
|
||||
}
|
||||
|
||||
// @deprecated - use pcastApi.channels.get instead
|
||||
public async getChannelInfoByAlias(alias: string): Promise<Channel | undefined> {
|
||||
return this._channels.get({alias});
|
||||
}
|
||||
|
||||
// @deprecated - use pcastApi.channels.get instead
|
||||
public async getChannelInfoByChannelId(channelId: string): Promise<Channel | undefined> {
|
||||
return this._channels.get({channelId});
|
||||
}
|
||||
|
||||
// @deprecated - use pcastApi.channels.getPublisherCount instead
|
||||
public async getChannelPublisherCount(channelId: string): Promise<number> {
|
||||
return this._channels.getPublisherCount(channelId);
|
||||
}
|
||||
|
||||
// @deprecated - use pcastApi.channels.getMembers instead
|
||||
public async getChannelMembers(channelId: string): Promise<Member[]> {
|
||||
return this._channels.getMembers(channelId);
|
||||
}
|
||||
|
||||
// @deprecated - use pcastApi.channels.getMembersByChannelAlias instead
|
||||
public async getChannelMembersByChannelAlias(alias: string): Promise<Member[]> {
|
||||
return this._channels.getMembersByChannelAlias(alias);
|
||||
}
|
||||
|
||||
// @deprecated - use pcastApi.channels.delete instead
|
||||
public async deleteChannel(channelId: string): Promise<Channel> {
|
||||
return this._channels.delete({channelId});
|
||||
}
|
||||
|
||||
// @deprecated - use pcastApi.reporting.generateReport instead
|
||||
public async generateViewingReport(
|
||||
kind: ViewingReportKindType,
|
||||
reportStartTimestamp: Date,
|
||||
reportEndTimestamp: Date,
|
||||
options: Record<string, string | string[]> = {}
|
||||
): Promise<string> {
|
||||
return this._reporting.generateReport(ReportKind.Viewing, {
|
||||
kind: ViewingReportKindMapping.convertViewingReportKindTypeToViewingReportKind(kind),
|
||||
start: reportStartTimestamp.toISOString(),
|
||||
end: reportEndTimestamp.toISOString(),
|
||||
...options
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export class Channels {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
public async createChannel(name: string, description: string, channelOptions: string[] = []): Promise<Channel> {
|
||||
public async create(name: string, description: string, channelOptions: string[] = []): Promise<Channel> {
|
||||
if (!name || name.trim().length === 0) {
|
||||
throw new ChannelError('Channel name cannot be empty', 'INVALID_NAME');
|
||||
}
|
||||
@@ -186,14 +186,42 @@ export class Channels {
|
||||
return deletedChannel;
|
||||
}
|
||||
|
||||
public clearCache(): void {
|
||||
this._channelsByAlias.clear();
|
||||
async getPublishSourceStreamId(channelId: string, retryCount: number = 3): Promise<string | null> {
|
||||
const retryCountRemaining = retryCount || 3;
|
||||
const channelMembers = await this.getMembers(channelId);
|
||||
|
||||
if (channelMembers.length === 0) {
|
||||
if (retryCountRemaining > 0) {
|
||||
return this.getPublishSourceStreamId(channelId, retryCountRemaining - 1);
|
||||
}
|
||||
|
||||
public getCacheSize(): number {
|
||||
return this._channelsByAlias.size;
|
||||
return null;
|
||||
}
|
||||
|
||||
const presenter = channelMembers.find(member => member.role === 'Presenter');
|
||||
|
||||
if (!presenter) {
|
||||
if (retryCountRemaining > 0) {
|
||||
return this.getPublishSourceStreamId(channelId, retryCountRemaining - 1);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const publishSourceStreamIdRegExp = /pcast:\/\/.*\/([^?]*)/;
|
||||
|
||||
return presenter.streams[0].uri.match(publishSourceStreamIdRegExp)?.[1] ?? null;
|
||||
}
|
||||
|
||||
// TODO(AZ): Implement this
|
||||
// public async fork(channelId: string): Promise<Channel>
|
||||
|
||||
// TODO(AZ): Implement this
|
||||
// public async killChannel(channelId: string): Promise<Channel>
|
||||
|
||||
// TODO(AZ): Implement this
|
||||
// public async publishViaUrl(mediaUriToPublish: string, token: string): Promise<Channel>
|
||||
|
||||
private async initialize(): Promise<void> {
|
||||
try {
|
||||
const channelsList = await this.list();
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import assertUnreachable from '../lang/assertUnreachable';
|
||||
import assertUnreachable from '../../lang/assertUnreachable';
|
||||
|
||||
export enum ReportKind {
|
||||
Publishing = 0,
|
||||
Viewing = 1
|
||||
Viewing = 1,
|
||||
Ingest = 2
|
||||
}
|
||||
|
||||
export type ReportKindType = 'Publishing' | 'Viewing';
|
||||
export type ReportKindType = 'Publishing' | 'Viewing' | 'IngestReport';
|
||||
|
||||
export class ReportKindMapping {
|
||||
public static convertReportKindTypeToReportKind(reportKindType: ReportKindType): ReportKind {
|
||||
@@ -14,6 +15,8 @@ export class ReportKindMapping {
|
||||
return ReportKind.Publishing;
|
||||
case 'Viewing':
|
||||
return ReportKind.Viewing;
|
||||
case 'IngestReport':
|
||||
return ReportKind.Ingest;
|
||||
|
||||
default:
|
||||
assertUnreachable(reportKindType);
|
||||
@@ -26,6 +29,8 @@ export class ReportKindMapping {
|
||||
return 'Publishing';
|
||||
case ReportKind.Viewing:
|
||||
return 'Viewing';
|
||||
case ReportKind.Ingest:
|
||||
return 'IngestReport';
|
||||
|
||||
default:
|
||||
assertUnreachable(reportKind);
|
||||
@@ -1,6 +1,6 @@
|
||||
import {HttpMethod} from '../net/http/HttpMethod';
|
||||
import type {PCastHttpRequests} from './PCastRequests';
|
||||
import assertUnreachable from '../lang/assertUnreachable';
|
||||
import {HttpMethod} from '../../net/http/HttpMethod';
|
||||
import type {PCastHttpRequests} from '../PCastRequests';
|
||||
import assertUnreachable from '../../lang/assertUnreachable';
|
||||
import {ReportKind} from './ReportKind';
|
||||
import {ViewingReportKind, ViewingReportKindMapping} from './ViewingReportKind';
|
||||
|
||||
@@ -32,6 +32,17 @@ export type ViewingReportOptions = {
|
||||
end: string;
|
||||
};
|
||||
|
||||
export type IngestBufferUnderrunOptions = {
|
||||
kind: 'BufferUnderrun'; // Are there more kinds? https://phenixrts.com/docs/sdk_ref/rest-api/reporting/#generate-an-ingest-report
|
||||
applicationIds?: string[];
|
||||
streamIds?: string[];
|
||||
channelIds?: string[];
|
||||
channelAliases?: string[];
|
||||
ingestIds?: string[];
|
||||
start: string;
|
||||
end: string;
|
||||
};
|
||||
|
||||
export class Reporting {
|
||||
private readonly _httpRequests: PCastHttpRequests;
|
||||
|
||||
@@ -39,12 +50,17 @@ export class Reporting {
|
||||
this._httpRequests = httpRequests;
|
||||
}
|
||||
|
||||
public async generateReport<ReportOptions extends PublishingReportOptions | ViewingReportOptions>(kind: ReportKind, options: ReportOptions): Promise<string> {
|
||||
public async generateReport<ReportOptions extends PublishingReportOptions | ViewingReportOptions | IngestBufferUnderrunOptions>(
|
||||
kind: ReportKind,
|
||||
options: ReportOptions
|
||||
): Promise<string> {
|
||||
switch (kind) {
|
||||
case ReportKind.Publishing:
|
||||
return this.requestPublishingReport(options as PublishingReportOptions);
|
||||
case ReportKind.Viewing:
|
||||
return this.requestViewingReport(options as ViewingReportOptions);
|
||||
case ReportKind.Ingest:
|
||||
return this.requestIngestBufferUnderrun(options as IngestBufferUnderrunOptions);
|
||||
default:
|
||||
assertUnreachable(kind);
|
||||
}
|
||||
@@ -54,12 +70,12 @@ export class Reporting {
|
||||
if (!options.start || !options.end) {
|
||||
throw new Error('[Reporting] [requestPublishingReport] requires a start and end Date');
|
||||
}
|
||||
const publishingReportOptions = {
|
||||
const publishingReport = {
|
||||
...options
|
||||
};
|
||||
|
||||
const requestPublishingOptions = {
|
||||
body: JSON.stringify({publishingReport: publishingReportOptions})
|
||||
body: JSON.stringify({publishingReport: publishingReport})
|
||||
};
|
||||
const response = await this._httpRequests.request<string>(HttpMethod.PUT, '/reporting/publishing', requestPublishingOptions);
|
||||
|
||||
@@ -67,17 +83,36 @@ export class Reporting {
|
||||
}
|
||||
|
||||
private async requestViewingReport(options: ViewingReportOptions): Promise<string> {
|
||||
const viewingReportOptions = {
|
||||
const viewingReport = {
|
||||
...options,
|
||||
tags: options.tags ?? [],
|
||||
originTags: options.originTags ?? [],
|
||||
kind: ViewingReportKindMapping.convertViewingReportKindToViewingReportKindType(options.kind)
|
||||
};
|
||||
|
||||
console.log(viewingReport);
|
||||
|
||||
const requestViewingOptions = {
|
||||
body: JSON.stringify({viewingReport: viewingReportOptions})
|
||||
body: JSON.stringify({viewingReport: viewingReport})
|
||||
};
|
||||
|
||||
const response = await this._httpRequests.request<string>(HttpMethod.PUT, '/reporting/viewing', requestViewingOptions);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async requestIngestBufferUnderrun(options: IngestBufferUnderrunOptions): Promise<string> {
|
||||
const ingestReport = {
|
||||
...options,
|
||||
kind: 'BufferUnderrun'
|
||||
};
|
||||
|
||||
const requestViewingOptions = {
|
||||
body: JSON.stringify({ingestReport})
|
||||
};
|
||||
|
||||
const response = await this._httpRequests.request<string>(HttpMethod.PUT, '/reporting/ingest', requestViewingOptions);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import assertUnreachable from '../lang/assertUnreachable';
|
||||
import assertUnreachable from '../../lang/assertUnreachable';
|
||||
|
||||
export enum ViewingReportKind {
|
||||
RealTime = 0,
|
||||
3
src/apis/Reporting/index.ts
Normal file
3
src/apis/Reporting/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './Reporting';
|
||||
export * from './ReportKind';
|
||||
export * from './ViewingReportKind';
|
||||
@@ -2,5 +2,4 @@ export * from './Channels';
|
||||
export * from './Reporting';
|
||||
export * from './PCastRequests';
|
||||
export * from './Stream';
|
||||
export * from './ReportKind';
|
||||
export * from './ViewingReportKind';
|
||||
export * from './Reporting';
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import {PCastApi} from './PCastApi';
|
||||
import type {Channels, Streams, Reporting, ReportKind, ViewingReportKind} from './apis';
|
||||
import {Channels, Streams, Reporting, PublishingReportOptions, ViewingReportOptions, ReportKindType, ViewingReportKindType, ViewingReportKind, ReportKind} from './apis';
|
||||
|
||||
import type {ChannelId, Channel, ChannelAlias, Member, ChannelError} from './apis/Channels';
|
||||
import type {HttpMethod} from './net/http/HttpMethod';
|
||||
import type {HttpRequestError} from './net/http/HttpRequests';
|
||||
import type {ChannelResponse, ChannelsResponse, MembersResponse} from './apis/IResponse';
|
||||
import type {ApplicationCredentials} from './apis/PCastRequests';
|
||||
import type {PublishingReportOptions, ViewingReportOptions} from './apis/Reporting';
|
||||
import type {ReportKindType} from './apis/ReportKind';
|
||||
import type {ViewingReportKindType} from './apis/ViewingReportKind';
|
||||
|
||||
export type {Channels, Streams, Reporting, ReportKind, ViewingReportKind};
|
||||
export type {Channels, Streams, Reporting, ViewingReportKind};
|
||||
export type {ChannelId, Channel, ChannelAlias, Member, ChannelError};
|
||||
export type {HttpMethod, HttpRequestError};
|
||||
export type {ChannelResponse, ChannelsResponse, MembersResponse};
|
||||
@@ -18,5 +15,5 @@ export type {ApplicationCredentials};
|
||||
export type {PublishingReportOptions, ViewingReportOptions};
|
||||
export type {ReportKindType, ViewingReportKindType};
|
||||
|
||||
export {PCastApi};
|
||||
export {PCastApi, ReportKind};
|
||||
export default PCastApi;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"verbatimModuleSyntax": false,
|
||||
"emitDeclarationOnly": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "./dist/types",
|
||||
|
||||
Reference in New Issue
Block a user