Skip to content

Commit

Permalink
feat(scripts): support publish command
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Feb 19, 2022
1 parent b35a180 commit 9911e72
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 3 deletions.
5 changes: 5 additions & 0 deletions packages/scripts/build/compile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineBuild } from '../../../build'

export = defineBuild(async (base, options) => {
options.entryPoints.push(base + '/src/bin.ts')
})
13 changes: 10 additions & 3 deletions packages/scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"lib"
],
"bin": {
"monopoly": "lib/bin.js"
"koishi-scripts": "lib/bin.js"
},
"author": "Shigma <shigma10826@gmail.com>",
"license": "MIT",
Expand All @@ -32,12 +32,19 @@
"koishi"
],
"devDependencies": {
"@types/cross-spawn": "^6.0.2"
"@types/cross-spawn": "^6.0.2",
"@types/fs-extra": "^9.0.13",
"@types/semver": "^7.3.9"
},
"dependencies": {
"@koishijs/cli": "^4.2.2",
"cac": "^6.7.12",
"cross-spawn": "^7.0.3",
"prompts": "^2.4.2"
"fs-extra": "^10.0.0",
"globby": "^11.0.4",
"latest-version": "^5.1.0",
"ora": "^5.4.1",
"prompts": "^2.4.2",
"semver": "^7.3.5"
}
}
2 changes: 2 additions & 0 deletions packages/scripts/src/bin.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#!/usr/bin/env node

import registerCreateCommand from './create'
import registerPublishCommand from './publish'
import CAC from 'cac'

const { version } = require('../package.json')

const cli = CAC('koishi-scripts').help().version(version)

registerCreateCommand(cli)
registerPublishCommand(cli)

cli.parse()

Expand Down
1 change: 1 addition & 0 deletions packages/scripts/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './utils'
62 changes: 62 additions & 0 deletions packages/scripts/src/publish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { cwd, getPackages, PackageJson, spawnAsync } from './utils'
import { gt, prerelease } from 'semver'
import { copyFile } from 'fs-extra'
import { CAC } from 'cac'
import latest from 'latest-version'
import ora from 'ora'

function getVersion(name: string, isNext = false) {
if (isNext) {
return latest(name, { version: 'next' }).catch(() => getVersion(name))
} else {
return latest(name).catch(() => '0.0.1')
}
}

function isNext(version: string) {
const parts = prerelease(version)
if (!parts) return false
return parts[0] !== 'rc'
}

function publish(folder: string, name: string, version: string, tag: string) {
console.log(`publishing ${name}@${version} ...`)
return spawnAsync([
'yarn', 'publish', folder,
'--new-version', version,
'--tag', tag,
'--access', 'public',
])
}

export default function (cli: CAC) {
cli.command('publish [...name]', 'publish packages')
.action(async (names: string[], options) => {
const entries = Object.entries(await getPackages(names))
const spinner = ora()
const bumpMap: Record<string, PackageJson> = {}

let progress = 0
spinner.start(`Loading workspaces (0/${entries.length})`)
await Promise.all(entries.map(async ([name, meta]) => {
if (!meta.private) {
const version = await getVersion(meta.name, isNext(meta.version))
if (gt(meta.version, version)) {
bumpMap[name] = meta
}
}
spinner.text = `Loading workspaces (${++progress}/${entries.length})`
}))
spinner.succeed()

for (const folder in bumpMap) {
const { name, version } = bumpMap[folder]
if (name === 'koishi') {
await copyFile(`${cwd}/README.md`, `${cwd}/${folder}/README.md`)
}
await publish(folder, name, version, isNext(version) ? 'next' : 'latest')
}

spinner.succeed('All workspaces are up to date.')
})
}
59 changes: 59 additions & 0 deletions packages/scripts/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import spawn from 'cross-spawn'
import globby from 'globby'

export const cwd = process.cwd()
export const meta: PackageJson = require(cwd + '/package.json')

export function requireSafe(id: string) {
try {
return require(id)
} catch {}
}

export async function getPackages(args: readonly string[]) {
const folders = await globby(meta.workspaces, {
cwd,
deep: 0,
onlyDirectories: true,
expandDirectories: false,
})

const packages = Object.fromEntries(folders.map((name) => {
try {
return [name, require(`${cwd}/${name}/package.json`)] as [string, PackageJson]
} catch {}
}).filter(Boolean))

if (!args.length) return packages
return Object.fromEntries(args.map((name) => {
const targets = Object.keys(packages).filter((folder) => {
const [last] = folder.split('/').reverse()
return name === last
})
if (!targets.length) {
throw new Error(`cannot find workspace "${name}"`)
} else if (targets.length > 1) {
throw new Error(`ambiguous workspace "${name}": ${targets.join(', ')}`)
}
return [targets[0], packages[targets[0]]] as const
}))
}

export type DependencyType = 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies'

export interface PackageJson extends Partial<Record<DependencyType, Record<string, string>>> {
name: string
main?: string
module?: string
description?: string
private?: boolean
version?: string
workspaces: string[]
}

export function spawnAsync(args: string[]) {
const child = spawn(args[0], args.slice(1), { cwd, stdio: 'inherit' })
return new Promise<number>((resolve) => {
child.on('close', resolve)
})
}

0 comments on commit 9911e72

Please sign in to comment.