Skip to content

Commit

Permalink
feat: add commander support to override env easily (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin authored Aug 11, 2022
1 parent 60c8d51 commit 6d61971
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/perfect-tips-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"dl-iconfont": minor
---

feat: add commander support to override env easily
5 changes: 5 additions & 0 deletions .changeset/quick-seas-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"dl-iconfont": minor
---

chore!: rename `ICONFONT_PROJECT_ID` env to `ICONFONT_PROJECT`
7 changes: 6 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ jobs:
run: yarn --frozen-lockfile

- name: Build, Lint and test
run: yarn run-p build lint typecov
run: |
yarn run-p build lint typecov
yarn dev iconfont.js
env:
EFF_NO_LINK_RULES: true
PARSER_NO_WATCH: true
ICONFONT_LOGIN: ${{ secrets.ICONFONT_LOGIN }}
ICONFONT_PASSWORD: ${{ secrets.ICONFONT_PASSWORD }}
ICONFONT_PROJECT: ${{ secrets.ICONFONT_PROJECT }}
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ npm i -g dl-iconfont

#### Environments

1. `ICONFONT_PROJECT_ID` (required)
1. `ICONFONT_PROJECT` (required)
2. `ICONFONT_LOGIN` (required)
3. `ICONFONT_PASSWORD` (required)
4. `ICONFONT_DOWNLOAD_FILE` (optional)
Expand All @@ -52,8 +52,18 @@ npm i -g dl-iconfont
#### Command

```sh
# [iconfont.js] is optional, it can be provided via env `ICONFONT_DOWNLOAD_FILE` too
dli iconfont.js
Usage: dli [options] [downloadFile]

Arguments:
downloadFile Filename path to be downloaded

Options:
-V, --version output the version number
-p, --project <string> Project ID from iconfont.cn
-l, --login <string> User login (mobile number) for iconfont.cn
-p, --password <string> User password for iconfont.cn
-h, --headless <boolean> Run in headless mode (default: true)
--help display help for command
```

### API
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"@changesets/cli": "^2.24.2",
"@types/puppeteer": "^5.4.6",
"@types/web": "^0.0.71",
"commander": "^9.4.0",
"size-limit": "^8.0.0",
"size-limit-preset-node-lib": "^0.1.0",
"tsx": "^3.8.1",
Expand All @@ -105,7 +106,7 @@
"size-limit": [
{
"path": "lib/cli.js",
"limit": "550B"
"limit": "750B"
}
],
"typeCoverage": {
Expand Down
79 changes: 60 additions & 19 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,72 @@
import './env.js'

import { download, fetchJsUrl } from './index.js'
import fs from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

import { program } from 'commander'

import { download, fetchJsUrl, FetchOptions } from './index.js'

const {
ICONFONT_PROJECT_ID,
ICONFONT_PROJECT,
ICONFONT_LOGIN,
ICONFONT_PASSWORD,
ICONFONT_DOWNLOAD_FILE,
PUPPETEER_HEADLESS,
} = process.env

const DOWNLOAD_FILE = process.argv[2] || ICONFONT_DOWNLOAD_FILE

const jsUrl = await fetchJsUrl({
projectId: ICONFONT_PROJECT_ID!,
login: ICONFONT_LOGIN!,
password: ICONFONT_PASSWORD!,
headless: !['0', 'false'].includes(PUPPETEER_HEADLESS!),
})
if (DOWNLOAD_FILE) {
console.log(
`[dl-iconfont]: downloading \`${jsUrl!}\` into \`${DOWNLOAD_FILE}\``,
await program
.version(
(
JSON.parse(
await fs.readFile(
path.resolve(fileURLToPath(import.meta.url), '../../package.json'),
'utf8',
),
) as {
version: string
}
).version,
)
.requiredOption(
'-p, --project <string>',
'Project ID from iconfont.cn',
ICONFONT_PROJECT,
)
await download(jsUrl!, DOWNLOAD_FILE)
} else {
console.log(
'[dl-iconfont] no `ICONFONT_DOWNLOAD_FILE` provided, you can use the environment variable or `dli ICONFONT_DOWNLOAD_FILE` to download the js file automatically',
.requiredOption(
'-l, --login <string>',
'User login (mobile number) for iconfont.cn',
ICONFONT_LOGIN,
)
console.log(`[dl-iconfont]: ${jsUrl!}`)
}
.requiredOption(
'-p, --password <string>',
'User password for iconfont.cn',
ICONFONT_PASSWORD,
)
.option(
'-h, --headless <boolean>',
'Run in headless mode',
!['0', 'false'].includes(PUPPETEER_HEADLESS!),
)
.argument(
'[downloadFile]',
'Filename path to be downloaded',
ICONFONT_DOWNLOAD_FILE,
)
.action(async (downloadFile: string, options: FetchOptions) => {
const jsUrl = await fetchJsUrl(options)

if (downloadFile) {
console.log(
`[dl-iconfont]: downloading \`${jsUrl!}\` into \`${downloadFile}\``,
)
await download(jsUrl!, downloadFile)
} else {
console.log(
'[dl-iconfont] no `downloadFile` provided, you can use the environment variable or `dli ICONFONT_DOWNLOAD_FILE` to download the js file automatically',
)
console.log(`[dl-iconfont]: ${jsUrl!}`)
}
})
.parseAsync(process.argv)
43 changes: 21 additions & 22 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fs from 'node:fs'
import fs from 'node:fs/promises'

import got from 'got'
import puppeteer from 'puppeteer'
Expand All @@ -7,34 +7,33 @@ const ICONFONT_URL = 'https://www.iconfont.cn/'

const VIEWPORT = { height: 1920, width: 1280 }

export interface FetchOptions {
project: string
login: string
password: string
headless?: boolean
}

export const fetchJsUrl = async ({
projectId,
project,
login,
password,
headless = true,
}: {
projectId: string
login: string
password: string
headless?: boolean
}) => {
if (!projectId || !login || !password) {
throw new Error('`projectId`, `login` and `password` must all be provided')
}: FetchOptions) => {
if (!project || !login || !password) {
throw new Error('`project`, `login` and `password` must all be provided')
}

const browser = await puppeteer.launch({ headless })
const browser = await puppeteer.launch({
headless,
defaultViewport: VIEWPORT,
})

const page = await browser.newPage()

page.setDefaultNavigationTimeout(0)
await page.goto(ICONFONT_URL, { waitUntil: 'networkidle0' })

// Resize the viewport to screenshot elements outside of the viewport
const body = await page.$('body')
const boundingBox = await body!.boundingBox()
await page.setViewport({
...VIEWPORT,
width: Math.max(VIEWPORT.width, Math.ceil(boundingBox!.width)),
height: Math.max(VIEWPORT.height, Math.ceil(boundingBox!.height)),
})
await page.goto(ICONFONT_URL, { waitUntil: 'networkidle0' })

await page.click('header .signin')

Expand All @@ -54,7 +53,7 @@ export const fetchJsUrl = async ({

// go to project
await page.goto(
`${ICONFONT_URL}manage/index?manage_type=myprojects&projectId=${projectId}`,
`${ICONFONT_URL}manage/index?manage_type=myprojects&projectId=${project}`,
{ waitUntil: 'networkidle0' },
)

Expand Down Expand Up @@ -82,5 +81,5 @@ export const download = async (url: string, file: string) => {
throw new Error('invalid url for downloading')
}
}
return fs.promises.writeFile(file, await got(url).buffer())
return fs.writeFile(file, got.stream(url))
}
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3537,7 +3537,7 @@ commander@^7.2.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==

commander@^9.2.0, commander@^9.3.0:
commander@^9.2.0, commander@^9.3.0, commander@^9.4.0:
version "9.4.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.0.tgz#bc4a40918fefe52e22450c111ecd6b7acce6f11c"
integrity sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==
Expand Down

0 comments on commit 6d61971

Please sign in to comment.