generated from idea2app/Next-Bootstrap-ts
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[add] Model, API & Page of Web polyfill CDN
- Loading branch information
Showing
8 changed files
with
262 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { observable } from 'mobx'; | ||
import { BaseModel, toggle } from 'mobx-restful'; | ||
import { buildURLData } from 'web-utility'; | ||
|
||
import { PolyfillHost } from '../pages/api/polyfill'; | ||
import { ownClient } from './Base'; | ||
|
||
export type JSEnvironment = 'window' | 'worker' | 'node'; | ||
|
||
export type LibraryAlias = Record<JSEnvironment, string>; | ||
|
||
export type LibraryPath = Record<JSEnvironment, string[]>; | ||
|
||
export interface Library { | ||
features: string[]; | ||
dependencies: string[]; | ||
contexts: {}; | ||
meta?: object; | ||
mustComeAfter?: string | string[]; | ||
} | ||
|
||
export interface RemoteLibrary extends Library { | ||
library: string | LibraryAlias; | ||
relativePaths: string[] | LibraryPath; | ||
} | ||
|
||
export interface LocalLibrary extends Library { | ||
version: string; | ||
localPaths: string[]; | ||
} | ||
|
||
export interface Alias { | ||
polyfills: string[]; | ||
} | ||
|
||
export type PolyfillIndex = Record< | ||
string, | ||
RemoteLibrary | LocalLibrary | Alias | ||
>; | ||
|
||
export const UserAgent: Record<string, string> = { | ||
'IE 11': | ||
'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko', | ||
'Edge 18': | ||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19042', | ||
'Safari 13.2': | ||
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1', | ||
'Opera 9.8': 'Opera/9.80 (Windows NT 6.1) Presto/2.12.388 Version/12.16', | ||
'UC 12': | ||
'Mozilla/5.0 (Linux; U; Android 8.1.0; en-US; Nexus 6P Build/OPM7.181205.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.11.1.1197 Mobile Safari/537.36', | ||
'Firefox 70': | ||
'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0', | ||
'Android 4': | ||
'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
}; | ||
|
||
export class PolyfillModel extends BaseModel { | ||
@observable | ||
accessor index: PolyfillIndex = {}; | ||
|
||
@observable | ||
accessor currentUA = ''; | ||
|
||
@observable | ||
accessor sourceCode = ''; | ||
|
||
@toggle('downloading') | ||
async getIndex() { | ||
const { body } = await ownClient.get<PolyfillIndex>( | ||
`${PolyfillHost}/index.json`, | ||
); | ||
return (this.index = body!); | ||
} | ||
|
||
@toggle('downloading') | ||
async getSourceCode(UA: string, features: string[]) { | ||
const response = await fetch( | ||
`/api/polyfill?${buildURLData({ features })}`, | ||
{ | ||
headers: { 'User-Agent': UserAgent[UA] }, | ||
}, | ||
); | ||
this.currentUA = UA; | ||
return (this.sourceCode = await response.text()); | ||
} | ||
} | ||
|
||
export default new PolyfillModel(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { HTTPClient } from 'koajax'; | ||
|
||
import { safeAPI } from './core'; | ||
|
||
export const PolyfillHost = 'https://polyfiller.kaiyuanshe.cn'; | ||
|
||
export const polyfillClient = new HTTPClient({ | ||
baseURI: PolyfillHost, | ||
responseType: 'text', | ||
}); | ||
|
||
export default safeAPI(async ({ method, url, headers, body }, response) => { | ||
delete headers.host; | ||
|
||
const { status, body: data } = await polyfillClient.request({ | ||
// @ts-ignore | ||
method, | ||
path: url!, | ||
// @ts-ignore | ||
headers, | ||
body: body || undefined, | ||
}); | ||
|
||
response.status(status); | ||
response.setHeader('Access-Control-Allow-Headers', '*'); | ||
response.send(data); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { Loading } from 'idea-react'; | ||
import { computed, observable } from 'mobx'; | ||
import { textJoin } from 'mobx-i18n'; | ||
import { observer } from 'mobx-react'; | ||
import { compose, translator } from 'next-ssr-middleware'; | ||
import { TreeNode } from 'primereact/treenode'; | ||
import { TreeSelect, TreeSelectSelectionKeysType } from 'primereact/treeselect'; | ||
import { Component } from 'react'; | ||
import { Card, Container, Dropdown, DropdownButton } from 'react-bootstrap'; | ||
|
||
import { PageHead } from '../components/PageHead'; | ||
import polyfillStore, { UserAgent } from '../models/Polyfill'; | ||
import { i18n } from '../models/Translation'; | ||
import { PolyfillHost } from './api/polyfill'; | ||
|
||
export const getServerSideProps = compose(translator(i18n)); | ||
|
||
const { t } = i18n; | ||
|
||
@observer | ||
export default class PolyfillPage extends Component { | ||
@computed | ||
get options() { | ||
return Object.entries(polyfillStore.index) | ||
.map(([key, data]) => !('polyfills' in data) && { key, label: key, data }) | ||
.filter(Boolean) as TreeNode[]; | ||
} | ||
|
||
@observable | ||
accessor selectOptions: TreeSelectSelectionKeysType = {}; | ||
|
||
@computed | ||
get features() { | ||
return Object.keys(this.selectOptions); | ||
} | ||
|
||
@computed | ||
get polyfillURL() { | ||
return `${PolyfillHost}/api/polyfill?features=${this.features}`; | ||
} | ||
|
||
componentDidMount() { | ||
polyfillStore.getIndex(); | ||
} | ||
|
||
renderContent() { | ||
const { options, selectOptions, features, polyfillURL } = this, | ||
{ currentUA, sourceCode } = polyfillStore; | ||
|
||
return ( | ||
<main className="d-flex flex-column gap-3 mb-3"> | ||
<TreeSelect | ||
placeholder="features" | ||
display="chip" | ||
filter | ||
selectionMode="checkbox" | ||
options={options} | ||
value={selectOptions} | ||
onChange={({ value }) => | ||
(this.selectOptions = value as TreeSelectSelectionKeysType) | ||
} | ||
/> | ||
<div className="d-flex justify-content-around align-items-center"> | ||
<DropdownButton title={textJoin(t('examples'), currentUA)}> | ||
{Object.entries(UserAgent).map(([name, value]) => ( | ||
<Dropdown.Item | ||
key={name} | ||
title={value} | ||
onClick={() => polyfillStore.getSourceCode(name, features)} | ||
> | ||
{name} | ||
</Dropdown.Item> | ||
))} | ||
</DropdownButton> | ||
|
||
<h1>{t('Web_polyfill_CDN')}</h1> | ||
</div> | ||
|
||
<Card body> | ||
<a target="_blank" href={polyfillURL} rel="noreferrer"> | ||
{polyfillURL} | ||
</a> | ||
<hr /> | ||
<pre> | ||
<code>{sourceCode}</code> | ||
</pre> | ||
</Card> | ||
</main> | ||
); | ||
} | ||
|
||
render() { | ||
const { downloading } = polyfillStore; | ||
|
||
return ( | ||
<Container> | ||
<PageHead title={t('Web_polyfill_CDN')}> | ||
<link | ||
rel="stylesheet" | ||
href="https://unpkg.com/primereact/resources/primereact.min.css" | ||
/> | ||
<link | ||
rel="stylesheet" | ||
href="https://unpkg.com/primereact/resources/themes/bootstrap4-light-blue/theme.css" | ||
/> | ||
</PageHead> | ||
|
||
{downloading > 0 && <Loading />} | ||
|
||
{this.renderContent()} | ||
</Container> | ||
); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
52ba904
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deploy preview for oss-toolbox ready!
✅ Preview
https://oss-toolbox-qflxu24ht-techquery.vercel.app
Built with commit 52ba904.
This pull request is being automatically deployed with vercel-action