Skip to content

Commit

Permalink
Make package wizard more intuitive
Browse files Browse the repository at this point in the history
  • Loading branch information
jdalton committed Sep 17, 2024
1 parent 916846d commit 01b6632
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 53 deletions.
83 changes: 83 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@eslint/js": "^9.10.0",
"@inquirer/confirm": "^3.2.0",
"@inquirer/input": "^2.3.0",
"@inquirer/search": "^2.0.1",
"@inquirer/select": "^2.5.0",
"@npmcli/package-json": "^5.2.0",
"@npmcli/promise-spawn": "^8.0.0",
Expand All @@ -56,6 +57,7 @@
"@typescript-eslint/parser": "^8.5.0",
"@yarnpkg/extensions": "2.0.3",
"del-cli": "^5.1.0",
"didyoumean2": "^7.0.2",
"eslint": "^9.10.0",
"fs-extra": "^11.2.0",
"husky": "^9.1.5",
Expand Down
36 changes: 27 additions & 9 deletions scripts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const lifecycleScriptNames = new Set(
].flat()
)

const lowerToCamelCase = Object.freeze(
const lowerToCamelCase = new Map(
[
'AggregateError',
'allSettled',
Expand Down Expand Up @@ -94,27 +94,23 @@ const lowerToCamelCase = Object.freeze(
'TypedArray'
]
.sort(localCompare)
.reduce(
(o, v) => {
o[v.toLowerCase()] = v
return o
},
{ __proto__: null }
)
.map(v => [v.toLowerCase(), v])
)

const packageExtensions = [
...yarnPackageExtensions,
[
'@yarnpkg/extensions@>=1.1.0',
{
// Properties with undefined values are omitted when saved as JSON.
peerDependencies: undefined
}
],
[
'abab@>=2.0.0',
{
devDependencies: {
// Lower the Webpack from v4.x to one supported by abab's peers.
webpack: '^3.12.0'
}
}
Expand All @@ -123,6 +119,7 @@ const packageExtensions = [
'is-generator-function@>=1.0.7',
{
scripts: {
// Make the script a silent no-op.
'test:uglified': ''
}
}
Expand All @@ -134,6 +131,26 @@ const packageExtensions = [
)
)

const tsLibs = new Set([
'decorators',
'dom',
'es5',
'es6',
'es2015',
'es2016',
'es2017',
'es2018',
'es2019',
'es2020',
'es2021',
'es2022',
'es2023',
'es2024',
'esnext',
'scripthost',
'webworker'
])

module.exports = {
EMPTY_FILE,
LICENSE,
Expand All @@ -152,5 +169,6 @@ module.exports = {
ignores,
lifecycleScriptNames,
lowerToCamelCase,
packageExtensions
packageExtensions,
tsLibs
}
90 changes: 46 additions & 44 deletions scripts/make-npm-package.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,18 @@ const path = require('node:path')

const fs = require('fs-extra')
const { default: confirm } = require('@inquirer/confirm')
const { default: didYouMean, ReturnTypeEnums } = require('didyoumean2')
const { default: input } = require('@inquirer/input')
const { default: select } = require('@inquirer/select')
const { default: search } = require('@inquirer/search')
const { glob: tinyGlob } = require('tinyglobby')
const validateNpmPackageName = require('validate-npm-package-name')
const { PACKAGE_JSON } = require('./constants')
const { PACKAGE_JSON, tsLibs } = require('./constants')

const rootPath = path.resolve(__dirname, '..')
const npmPackagesPath = path.join(rootPath, 'packages/npm')
const npmTemplatesPath = path.join(__dirname, 'templates/npm')

const validEsReferences = new Set([
'dom',
'decorators',
'es5',
'es6',
'es2015',
'es2016',
'es2017',
'es2018',
'es2019',
'es2020',
'es2021',
'es2022',
'es2023',
'es2024',
'esnext',
'webworker'
])

const templates = Object.fromEntries(
[
'default',
Expand All @@ -55,11 +38,11 @@ function modifyContent(content, data = {}) {

;(async () => {
const pkgName = await input({
message: 'Enter package name',
message: 'Give the package a name',
validate: value => validateNpmPackageName(value).validForNewPackages
})
const templateChoice = await select({
message: 'Choose a package template',
message: `Choose ${pkgName}'s template`,
choices: [
{ name: 'default', value: 'default' },
{
Expand All @@ -71,49 +54,68 @@ function modifyContent(content, data = {}) {
{ name: 'node plus browser', value: 'node-plus-browser' }
]
})

const srcPath = templates[templateChoice]
const destPath = path.join(npmPackagesPath, pkgName)
await fs.copy(srcPath, destPath)

let ts_lib
if (templateChoice.startsWith('es-shim')) {
const availableTsLibs = [...tsLibs]
const maxTsLibLength = availableTsLibs.reduce(
(n, v) => Math.max(n, v.length),
0
)
if (
await confirm({
message: 'Does this require a lib reference?',
message: `Does ${pkgName} need a TypeScript lib?`,
default: false
})
) {
ts_lib = await input({
message: 'Enter lib reference (e.g. es2024)',
transformer: value => value.toLowerCase(),
validate: value => validEsReferences.has(value.toLowerCase())
ts_lib = await search({
message: 'Which one?',
source: async input => {
if (!input) return []
const truncated = input.slice(0, maxTsLibLength)
return didYouMean(truncated, availableTsLibs, {
deburr: false,
returnType: ReturnTypeEnums.ALL_SORTED_MATCHES,
threshold: 0.3
}).map(l => ({ name: l, value: l }))
}
})
}
}
const srcPath = templates[templateChoice]
const destPath = path.join(npmPackagesPath, pkgName)
const pkgJsonPath = path.join(destPath, PACKAGE_JSON)

await fs.copy(srcPath, destPath)

const actions = []
if (ts_lib) {
const tsData = {
ts_lib
}
const tsFiles = await tinyGlob(['**/*.ts'], {
absolute: true,
cwd: destPath
})
const tsData = {
ts_lib
}
for (const filepath of tsFiles) {
const content = await fs.readFile(filepath, 'utf8')
await fs.writeFile(filepath, modifyContent(content, tsData), 'utf8')
actions.push([filepath, tsData])
}
}

const pkgJsonData = {
name: pkgName,
category: 'cleanup'
}
const pkgJsonPath = path.join(destPath, PACKAGE_JSON)
const pkgJsonStr = await fs.readFile(pkgJsonPath, 'utf8')
await fs.writeFile(
pkgJsonPath,
modifyContent(pkgJsonStr, pkgJsonData),
'utf8'
actions.push([pkgJsonPath, pkgJsonData])

await Promise.all(
actions.map(
async ({ 0: filepath, 1: data }) =>
await fs.writeFile(
filepath,
modifyContent(await fs.readFile(filepath, 'utf8'), data),
'utf8'
)
)
)

console.log('All done 🎉')
})()

0 comments on commit 01b6632

Please sign in to comment.