From 3c54b116c9875e622e28611be0f27ef3bcf94a89 Mon Sep 17 00:00:00 2001 From: Griffith Tchen Pan Date: Sat, 22 Jun 2019 10:43:59 +0100 Subject: [PATCH] fix: added packageMeta type --- src/components/Author/Author.tsx | 12 +++---- src/components/Package/Package.tsx | 7 ++-- src/components/PackageList/PackageList.tsx | 21 +++++------ src/components/Repository/Repository.tsx | 9 ++--- src/components/UpLinks/UpLinks.tsx | 2 +- src/pages/home/Home.tsx | 2 +- src/pages/version/Version.tsx | 41 ++++++++++++++-------- src/router.tsx | 7 +++- src/utils/api.ts | 4 +-- src/utils/calls.ts | 5 +-- src/utils/file-size.ts | 1 + src/utils/login.ts | 18 ++++++---- src/utils/sec-utils.ts | 2 +- src/utils/styles/mixings.ts | 4 +-- types/custom.d.ts | 7 ++-- types/packageMeta.ts | 6 ++++ 16 files changed, 83 insertions(+), 65 deletions(-) create mode 100644 types/packageMeta.ts diff --git a/src/components/Author/Author.tsx b/src/components/Author/Author.tsx index 890fbdb..e39d739 100644 --- a/src/components/Author/Author.tsx +++ b/src/components/Author/Author.tsx @@ -1,4 +1,4 @@ -import React, { Component, ReactNode } from 'react'; +import React, { Component, ReactNode, ReactElement } from 'react'; import Avatar from '@material-ui/core/Avatar'; import List from '@material-ui/core/List'; @@ -8,18 +8,18 @@ import { DetailContextConsumer } from '../../pages/version/Version'; import { Heading, AuthorListItem } from './styles'; import { isEmail } from '../../utils/url'; -class Authors extends Component { - render() { +class Authors extends Component { + public render(): ReactElement { return ( - {(context: any) => { + {context => { return context && context.packageMeta && this.renderAuthor(context.packageMeta); }} ); } - renderLinkForMail(email: string, avatarComponent: ReactNode, packageName: string, version: string) { + public renderLinkForMail(email: string, avatarComponent: ReactNode, packageName: string, version: string): ReactElement | ReactNode { if (!email || isEmail(email) === false) { return avatarComponent; } @@ -31,7 +31,7 @@ class Authors extends Component { ); } - renderAuthor = packageMeta => { + public renderAuthor = packageMeta => { const { author, name: packageName, version } = packageMeta.latest; if (!author) { diff --git a/src/components/Package/Package.tsx b/src/components/Package/Package.tsx index c01b02c..006d55f 100644 --- a/src/components/Package/Package.tsx +++ b/src/components/Package/Package.tsx @@ -23,10 +23,10 @@ interface Dist { unpackedSize: number; } -interface Props { +export interface PackageInterface { name: string; version: string; - time: string; + time?: number | string; author: Author; description?: string; keywords?: string[]; @@ -35,6 +35,7 @@ interface Props { bugs?: Bugs; dist?: Dist; } +// interface Props {} & PackageInterface; import { Author, @@ -56,7 +57,7 @@ import { } from './styles'; import { isURL } from '../../utils/url'; -const Package: React.FC = ({ +const Package: React.FC = ({ author: { name: authorName, avatar: authorAvatar }, bugs, description, diff --git a/src/components/PackageList/PackageList.tsx b/src/components/PackageList/PackageList.tsx index 7c0e387..ef281a4 100644 --- a/src/components/PackageList/PackageList.tsx +++ b/src/components/PackageList/PackageList.tsx @@ -1,25 +1,21 @@ -import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; +import React, { Fragment, ReactElement } from 'react'; import Divider from '@material-ui/core/Divider'; import Package from '../Package'; import Help from '../Help'; import { formatLicense } from '../../utils/package'; +import { PackageInterface } from '../Package/Package'; // @ts-ignore import classes from './packageList.scss'; interface Props { - packages: any; + packages: PackageInterface[]; } export default class PackageList extends React.Component { - static propTypes = { - packages: PropTypes.array, - }; - - render() { + public render(): ReactElement { return (
{this.hasPackages() ? this.renderPackages() : }
@@ -27,20 +23,19 @@ export default class PackageList extends React.Component { ); } - hasPackages() { + private hasPackages(): boolean { const { packages } = this.props; return packages.length > 0; } - renderPackages = () => { + private renderPackages = () => { return <>{this.renderList()}; }; - renderList = () => { + private renderList = () => { const { packages } = this.props; return packages.map((pkg, i) => { - const { name, version, description, time, keywords, dist, homepage, bugs } = pkg; - const author = pkg.author; + const { name, version, description, time, keywords, dist, homepage, bugs, author } = pkg; // TODO: move format license to API side. const license = formatLicense(pkg.license); return ( diff --git a/src/components/Repository/Repository.tsx b/src/components/Repository/Repository.tsx index 444d46d..bac92fe 100644 --- a/src/components/Repository/Repository.tsx +++ b/src/components/Repository/Repository.tsx @@ -13,7 +13,7 @@ import { Heading, GithubLink, RepositoryListItem } from './styles'; import git from './img/git.png'; import { isURL } from '../../utils/url'; -class Repository extends Component { +class Repository extends Component { public render(): ReactElement { return ( @@ -33,12 +33,7 @@ class Repository extends Component { } private renderRepository = packageMeta => { - const { - repository: { - // @ts-ignore - url, - } = {}, - } = packageMeta.latest; + const { repository: { url = null } = {} } = packageMeta.latest; if (!url || isURL(url) === false) { return null; diff --git a/src/components/UpLinks/UpLinks.tsx b/src/components/UpLinks/UpLinks.tsx index d11e15d..c2b261b 100644 --- a/src/components/UpLinks/UpLinks.tsx +++ b/src/components/UpLinks/UpLinks.tsx @@ -8,7 +8,7 @@ import { formatDateDistance } from '../../utils/package'; import { Heading, Spacer, ListItemText } from './styles'; -class UpLinks extends React.PureComponent { +class UpLinks extends React.PureComponent<{}> { public render(): ReactElement { return ( diff --git a/src/pages/home/Home.tsx b/src/pages/home/Home.tsx index 3a696fb..cdc08e9 100644 --- a/src/pages/home/Home.tsx +++ b/src/pages/home/Home.tsx @@ -4,7 +4,7 @@ import PackageList from '../../components/PackageList'; interface Props { isUserLoggedIn: boolean; - packages: any[]; + packages: []; } const Home: React.FC = ({ packages }) => ( diff --git a/src/pages/version/Version.tsx b/src/pages/version/Version.tsx index 4ebea1f..a1b4e58 100644 --- a/src/pages/version/Version.tsx +++ b/src/pages/version/Version.tsx @@ -3,31 +3,44 @@ import Grid from '@material-ui/core/Grid'; import Loading from '../../components/Loading/Loading'; import DetailContainer from '../../components/DetailContainer/DetailContainer'; import DetailSidebar from '../../components/DetailSidebar/DetailSidebar'; -import { callDetailPage, DetailPage } from '../../utils/calls'; +import { callDetailPage } from '../../utils/calls'; import { getRouterPackageName } from '../../utils/package'; import NotFound from '../../components/NotFound'; +import { PackageMetaInterface } from '../../../types/packageMeta'; export interface DetailContextProps { - packageMeta: any; - readMe: any; + packageMeta: PackageMetaInterface; + readMe: string; packageName: string; enableLoading: () => void; } -export const DetailContext = React.createContext(null); +export const DetailContext = React.createContext>({}); export interface VersionPageConsumerProps { - packageMeta: any; - readMe: any; - packageName: any; - enableLoading: any; + packageMeta: PackageMetaInterface; + readMe: string; + packageName: string; + enableLoading: () => void; } -export const DetailContextProvider: Provider = DetailContext.Provider; -export const DetailContextConsumer: Consumer = DetailContext.Consumer; +export const DetailContextProvider: Provider> = DetailContext.Provider; +export const DetailContextConsumer: Consumer> = DetailContext.Consumer; -class VersionPage extends Component { - constructor(props: any) { +interface PropsInterface { + match: boolean; +} + +interface StateInterface { + readMe: string; + packageName: string; + packageMeta: PackageMetaInterface | null; + isLoading: boolean; + notFound: boolean; +} + +class VersionPage extends Component { + constructor(props) { super(props); this.state = { @@ -39,7 +52,7 @@ class VersionPage extends Component { }; } - public static getDerivedStateFromProps(nextProps: any, prevState: any): any { + public static getDerivedStateFromProps(nextProps, prevState): { packageName?: string; isLoading: boolean; notFound?: boolean } | null { const { match } = nextProps; const packageName = getRouterPackageName(match); @@ -65,7 +78,7 @@ class VersionPage extends Component { } /* eslint no-unused-vars: 0 */ - public async componentDidUpdate(nextProps: any, prevState: any): Promise { + public async componentDidUpdate(nextProps, prevState: StateInterface): Promise { const { packageName } = this.state; if (packageName !== prevState.packageName) { const { readMe, packageMeta } = await callDetailPage(packageName); diff --git a/src/router.tsx b/src/router.tsx index 1a9618e..5906b28 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -12,7 +12,12 @@ const NotFound = asyncComponent(() => import('./components/NotFound')); const VersionPackage = asyncComponent(() => import('./pages/version/Version')); const HomePage = asyncComponent(() => import('./pages/home')); -class RouterApp extends Component { +interface RouterAppProps { + onLogout: () => void; + onToggleLoginModal: () => void; +} + +class RouterApp extends Component { public render(): ReactElement { return ( diff --git a/src/utils/api.ts b/src/utils/api.ts index 0f9c16e..be94201 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -6,9 +6,9 @@ import '../../types'; * @param {object} response * @returns {promise} */ -function handleResponseType(response): Promise { +function handleResponseType(response: Response): Promise<[boolean, Blob | string]> | Promise { if (response.headers) { - const contentType = response.headers.get('Content-Type'); + const contentType = response.headers.get('Content-Type') as string; if (contentType.includes('application/pdf')) { return Promise.all([response.ok, response.blob()]); } diff --git a/src/utils/calls.ts b/src/utils/calls.ts index f081bd2..f44a36d 100644 --- a/src/utils/calls.ts +++ b/src/utils/calls.ts @@ -1,8 +1,9 @@ import API from './api'; +import { PackageMetaInterface } from 'types/packageMeta'; export interface DetailPage { - readMe: any; - packageMeta: any; + readMe: string; + packageMeta: PackageMetaInterface; } export async function callDetailPage(packageName): Promise { diff --git a/src/utils/file-size.ts b/src/utils/file-size.ts index cf8ca22..c79ed35 100644 --- a/src/utils/file-size.ts +++ b/src/utils/file-size.ts @@ -1,3 +1,4 @@ +/* tslint:disable */ export default function fileSizeSI(a?: any, b?: any, c?: any, d?: any, e?: any) { return ((b = Math), (c = b.log), (d = 1e3), (e = (c(a) / c(d)) | 0), a / b.pow(d, e)).toFixed(2) + ' ' + (e ? 'kMGTPEZY'[--e] + 'B' : 'Bytes'); } diff --git a/src/utils/login.ts b/src/utils/login.ts index ac24733..df4c0e7 100644 --- a/src/utils/login.ts +++ b/src/utils/login.ts @@ -5,30 +5,34 @@ import { Base64 } from 'js-base64'; import API from './api'; import { HEADERS } from '../../lib/constants'; -export function isTokenExpire(token?: any) { +interface PayloadInterface { + exp: number; +} + +export function isTokenExpire(token?: string): boolean { if (!isString(token)) { return true; } - let [, payload]: any = token.split('.'); + const [, payload] = token.split('.'); if (!payload) { return true; } + let exp: number; try { - payload = JSON.parse(Base64.decode(payload)); + exp = JSON.parse(Base64.decode(payload)).exp; } catch (error) { - // eslint-disable-next-line - console.error('Invalid token:', error, token); + console.error('Invalid token:', error, token); return true; } - if (!payload.exp || !isNumber(payload.exp)) { + if (!exp || !isNumber(exp)) { return true; } // Report as expire before (real expire time - 30s) - const jsTimestamp = payload.exp * 1000 - 30000; + const jsTimestamp = exp * 1000 - 30000; const expired = Date.now() >= jsTimestamp; return expired; diff --git a/src/utils/sec-utils.ts b/src/utils/sec-utils.ts index c2617ee..cae1067 100644 --- a/src/utils/sec-utils.ts +++ b/src/utils/sec-utils.ts @@ -1,6 +1,6 @@ import parseXSS from 'xss'; -export function preventXSS(text: string) { +export function preventXSS(text: string): string { const encodedText = parseXSS.filterXSS(text); return encodedText; diff --git a/src/utils/styles/mixings.ts b/src/utils/styles/mixings.ts index 44ec992..a273df1 100644 --- a/src/utils/styles/mixings.ts +++ b/src/utils/styles/mixings.ts @@ -1,7 +1,7 @@ /** * CSS to represent truncated text with an ellipsis. */ -export function ellipsis(width: string | number) { +export function ellipsis(width: string | number): {} { return { display: 'inline-block', maxWidth: width, @@ -24,7 +24,7 @@ interface SpacingShortHand { const positionMap = ['Top', 'Right', 'Bottom', 'Left']; -export function spacing(property: 'padding' | 'margin', ...values: SpacingShortHand[]) { +export function spacing(property: 'padding' | 'margin', ...values: SpacingShortHand[]): {} { const [firstValue = 0, secondValue = 0, thirdValue = 0, fourthValue = 0] = values; const valuesWithDefaults = [firstValue, secondValue, thirdValue, fourthValue]; let styles = {}; diff --git a/types/custom.d.ts b/types/custom.d.ts index a7c309f..bf77f9b 100644 --- a/types/custom.d.ts +++ b/types/custom.d.ts @@ -1,10 +1,7 @@ // https://stackoverflow.com/questions/44717164/unable-to-import-svg-files-in-typescript declare module '*.svg' { - const content: any; + const content: string; export default content; } -declare module '*.png' { - const content: any; - export default content; -} +declare module '*.png'; diff --git a/types/packageMeta.ts b/types/packageMeta.ts new file mode 100644 index 0000000..17e24b6 --- /dev/null +++ b/types/packageMeta.ts @@ -0,0 +1,6 @@ +export interface PackageMetaInterface { + latest: { + name: string; + }; + _uplinks: {}; +}