neet/refined-itsukara-link

View on GitHub
packages/@neet/vschedule-api/src/adapters/mappers/rest-presenter.ts

Summary

Maintainability
A
35 mins
Test Coverage
import { URL } from 'node:url';

import { inject, injectable } from 'inversify';

import {
  ChannelDto,
  IConfig,
  MediaAttachmentDto,
  OrganizationDto,
  PerformerDto,
  StreamDto,
} from '../../app';
import { User } from '../../domain';
import { TYPES } from '../../types';
import * as Rest from '../generated/@types';

@injectable()
export class RestPresenter {
  private readonly _origin: string;

  public constructor(
    @inject(TYPES.Config)
    config: IConfig,
  ) {
    this._origin = config.server.origin;
  }

  public presentMediaAttachment(
    mediaAttachment: MediaAttachmentDto,
  ): Rest.MediaAttachment {
    const pathname = `/rest/v1/media/${mediaAttachment.filename}`;
    const url = new URL(this._origin);
    url.pathname = pathname;

    return {
      id: mediaAttachment.id,
      url: url.toString(),
      blurDataUri: mediaAttachment.blurDataUri,
      width: mediaAttachment.width,
      height: mediaAttachment.height,
      filename: mediaAttachment.filename,
      createdAt: mediaAttachment.createdAt.toISOString(),
      updatedAt: mediaAttachment.updatedAt.toISOString(),
    };
  }

  public presentChannel(channel: ChannelDto): Rest.Channel {
    if (channel.type === 'youtube') {
      return {
        type: 'youtube',
        id: channel.id,
        name: channel.name,
        description: channel.description,
        url: `https://youtube.com/channel/${channel.youtubeChannelId}`,
      };
    }
    throw new Error('unknown type');
  }

  public presentOrganization(organization: OrganizationDto): Rest.Organization {
    return {
      id: organization.id,
      name: organization.name,
      url: organization.url === null ? null : organization.url.toString(),
      color: organization.color.hex(),
      description: organization.description,
      twitterUsername: organization.twitterUsername,
      youtubeChannelId: organization.youtubeChannelId,
      avatar:
        organization.avatar !== null
          ? this.presentMediaAttachment(organization.avatar)
          : undefined,
      channels: organization.channels.map((channel) =>
        this.presentChannel(channel),
      ),
      createdAt: organization.createdAt.toISOString(),
      updatedAt: organization.updatedAt.toISOString(),
    };
  }

  public presentPerformer(performer: PerformerDto): Rest.Performer {
    return {
      id: performer.id,
      name: performer.name,
      url: performer.url === null ? null : performer.url.toString(),
      color: performer.color.hex(),
      description: performer.description,
      twitterUsername: performer.twitterUsername,
      youtubeChannelId: performer.youtubeChannelId,
      avatar:
        performer.avatar !== null
          ? this.presentMediaAttachment(performer.avatar)
          : undefined,
      createdAt: performer.createdAt.toISOString(),
      updatedAt: performer.updatedAt.toISOString(),
      channels: performer.channels.map((channel) =>
        this.presentChannel(channel),
      ),
      organization:
        performer.organization !== null
          ? this.presentOrganization(performer.organization)
          : undefined,
    };
  }

  public presentStream(stream: StreamDto): Rest.Stream {
    return {
      id: stream.id,
      title: stream.title,
      url: stream.url.toString(),
      description: stream.description,
      createdAt: stream.createdAt.toISOString(),
      updatedAt: stream.updatedAt.toISOString(),
      startedAt: stream.startedAt.toISOString(),
      endedAt: stream.endedAt === null ? null : stream.endedAt.toISOString(),
      owner: this.presentPerformer(stream.owner),
      duration: stream.duration === null ? null : stream.duration.toISOString(),
      participants: [], // TODO
      channelId: stream.channelId,
      thumbnail:
        stream.thumbnail !== null
          ? this.presentMediaAttachment(stream.thumbnail)
          : undefined,
    };
  }

  public presentUser(user: User): Rest.User {
    return {
      id: user.id.value,
      email: user.email.value,
      createdAt: user.createdAt.toISOString(),
      updatedAt: user.updatedAt.toISOString(),
    };
  }
}