Skip to content

Commit

Permalink
[bundlejs] add badge for the npm package size (#9055)
Browse files Browse the repository at this point in the history
* feat(service): add bundlejs

* refactor: implement first hit timeout pattern

* refactor: update http error message

* test(bundlejs): remove timeout

* refactor(bundlejs): move exports to query params

* refactor(bundlejs): show errors as timeout only

* test(bundlejs): add timeout and 404 mock
  • Loading branch information
crimx authored Aug 20, 2023
1 parent 8f76982 commit ad359a2
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 0 deletions.
139 changes: 139 additions & 0 deletions services/bundlejs/bundlejs-package.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import Joi from 'joi'
import { BaseJsonService } from '../index.js'

const schema = Joi.object({
size: Joi.object({
compressedSize: Joi.string().required(),
}).required(),
}).required()

const queryParamSchema = Joi.object({
exports: Joi.string(),
}).required()

const keywords = ['node', 'bundlejs']

const esbuild =
'<a href="https://github.com/evanw/esbuild" target="_blank" rel="noopener">esbuild</a>'
const denoflate =
'<a href="https://github.com/hazae41/denoflate" target="_blank" rel="noopener">denoflate</a>'
const bundlejs =
'<a href="https://bundlejs.com/" target="_blank" rel="noopener">bundlejs</a>'

const documentation = `
<p>
View ${esbuild} minified and ${denoflate} gzipped size of a package or selected exports, via ${bundlejs}.
</p>
`

export default class BundlejsPackage extends BaseJsonService {
static category = 'size'

static route = {
base: 'bundlejs/size',
pattern: ':scope(@[^/]+)?/:packageName',
queryParamSchema,
}

static examples = [
{
title: 'npm package minimized gzipped size',
pattern: ':packageName',
namedParams: {
packageName: 'react',
},
staticPreview: this.render({ size: '2.94 kB' }),
keywords,
documentation,
},
{
title: 'npm package minimized gzipped size (version)',
pattern: ':packageName',
namedParams: {
packageName: 'react@18.2.0',
},
staticPreview: this.render({ size: '2.94 kB' }),
keywords,
documentation,
},
{
title: 'npm package minimized gzipped size (scoped)',
pattern: ':scope/:packageName',
namedParams: {
scope: '@cycle',
packageName: 'rx-run',
},
staticPreview: this.render({ size: '32.3 kB' }),
keywords,
documentation,
},
{
title: 'npm package minimized gzipped size (select exports)',
pattern: ':packageName',
namedParams: {
packageName: 'value-enhancer',
},
queryParams: {
exports: 'isVal,val',
},
staticPreview: this.render({ size: '823 B' }),
keywords,
documentation,
},
{
title:
'npm package minimized gzipped size (scoped version select exports)',
pattern: ':scope/:packageName',
namedParams: {
scope: '@ngneat',
packageName: 'falso@6.4.0',
},
queryParams: {
exports: 'randEmail,randFullName',
},
staticPreview: this.render({ size: '17.8 kB' }),
keywords,
documentation,
},
]

static defaultBadgeData = { label: 'bundlejs', color: 'informational' }

static render({ size }) {
return {
label: 'minified size (gzip)',
message: size,
}
}

async fetch({ scope, packageName, exports }) {
const searchParams = {
q: `${scope ? `${scope}/` : ''}${packageName}`,
}
if (exports) {
searchParams.treeshake = `[{${exports}}]`
}
return this._requestJson({
schema,
url: 'https://deno.bundlejs.com',
options: {
searchParams,
timeout: {
request: 3500,
},
},
systemErrors: {
ETIMEDOUT: { prettyMessage: 'timeout', cacheSeconds: 10 },
},
httpErrors: {
404: 'package or version not found',
},
})
}

async handle({ scope, packageName }, { exports }) {
const json = await this.fetch({ scope, packageName, exports })
const size = json.size.compressedSize
return this.constructor.render({ size })
}
}
43 changes: 43 additions & 0 deletions services/bundlejs/bundlejs-package.tester.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { isFileSize } from '../test-validators.js'
import { createServiceTester } from '../tester.js'
export const t = await createServiceTester()

t.create('bundlejs/package (packageName)')
.get('/jquery.json')
.expectBadge({ label: 'minified size (gzip)', message: isFileSize })

t.create('bundlejs/package (version)')
.get('/react@18.2.0.json')
.expectBadge({ label: 'minified size (gzip)', message: isFileSize })

t.create('bundlejs/package (scoped)')
.get('/@cycle/rx-run.json')
.expectBadge({ label: 'minified size (gzip)', message: isFileSize })

t.create('bundlejs/package (select exports)')
.get('/value-enhancer.json?exports=isVal,val')
.expectBadge({ label: 'minified size (gzip)', message: isFileSize })

t.create('bundlejs/package (scoped version select exports)')
.get('/@ngneat/falso@6.4.0.json?exports=randEmail,randFullName')
.expectBadge({ label: 'minified size (gzip)', message: isFileSize })

t.create('bundlejs/package (not found)')
.get('/react@18.2.0.json')
.intercept(nock =>
nock('https://deno.bundlejs.com')
.get(/./)
.query({ q: 'react@18.2.0' })
.reply(404),
)
.expectBadge({ label: 'bundlejs', message: 'package or version not found' })

t.create('bundlejs/package (timeout)')
.get('/react@18.2.0.json')
.intercept(nock =>
nock('https://deno.bundlejs.com')
.get(/./)
.query({ q: 'react@18.2.0' })
.replyWithError({ code: 'ETIMEDOUT' }),
)
.expectBadge({ label: 'bundlejs', message: 'timeout' })

0 comments on commit ad359a2

Please sign in to comment.