2023-10-16 19:23:53 +03:00
|
|
|
const cp = require('child_process')
|
|
|
|
const path = require('path')
|
|
|
|
const fs = require('fs')
|
|
|
|
const glob = require('glob')
|
|
|
|
|
|
|
|
if (process.argv.length < 3) {
|
|
|
|
console.log('Usage: build-package.js <package name>')
|
|
|
|
process.exit(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
const packageDir = path.join(__dirname, '../packages', process.argv[2])
|
2023-11-02 21:23:17 +03:00
|
|
|
const outDir = path.join(packageDir, 'dist')
|
2023-10-16 19:23:53 +03:00
|
|
|
|
2023-11-02 21:23:17 +03:00
|
|
|
function exec(cmd, params) {
|
|
|
|
cp.execSync(cmd, { cwd: packageDir, stdio: 'inherit', ...params })
|
|
|
|
}
|
|
|
|
|
|
|
|
function transformFile(file, transform) {
|
|
|
|
const content = fs.readFileSync(file, 'utf8')
|
|
|
|
fs.writeFileSync(file, transform(content))
|
2023-10-16 19:23:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const buildConfig = {
|
|
|
|
buildTs: true,
|
|
|
|
buildCjs: true,
|
|
|
|
removeReferenceComments: true,
|
|
|
|
replaceSrcImports: true,
|
|
|
|
esmOnlyDirectives: false,
|
2023-11-02 21:23:17 +03:00
|
|
|
before: () => {},
|
|
|
|
final: () => {},
|
|
|
|
...(() => {
|
|
|
|
let config
|
|
|
|
|
|
|
|
try {
|
|
|
|
config = require(path.join(packageDir, 'build.config.cjs'))
|
|
|
|
} catch (e) {
|
|
|
|
return {}
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('[i] Using custom build config')
|
|
|
|
|
|
|
|
if (typeof config === 'function') {
|
|
|
|
config = config({
|
|
|
|
fs,
|
|
|
|
path,
|
|
|
|
exec,
|
|
|
|
transformFile,
|
|
|
|
packageDir,
|
|
|
|
outDir,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return config
|
|
|
|
})(),
|
2023-10-16 19:23:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function buildPackageJson() {
|
|
|
|
const pkgJson = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf-8'))
|
|
|
|
|
|
|
|
if (buildConfig.buildCjs) {
|
|
|
|
pkgJson.main = 'cjs/index.js'
|
|
|
|
pkgJson.module = 'esm/index.js'
|
|
|
|
}
|
|
|
|
|
|
|
|
const newScripts = {}
|
|
|
|
|
|
|
|
if (pkgJson.keepScripts) {
|
|
|
|
for (const script of pkgJson.keepScripts) {
|
|
|
|
newScripts[script] = pkgJson.scripts[script]
|
|
|
|
}
|
|
|
|
delete pkgJson.keepScripts
|
|
|
|
}
|
|
|
|
pkgJson.scripts = newScripts
|
|
|
|
delete pkgJson.devDependencies
|
|
|
|
delete pkgJson.private
|
|
|
|
|
|
|
|
if (pkgJson.distOnlyFields) {
|
|
|
|
Object.assign(pkgJson, pkgJson.distOnlyFields)
|
|
|
|
delete pkgJson.distOnlyFields
|
|
|
|
}
|
|
|
|
|
|
|
|
function replaceWorkspaceDependencies(field) {
|
|
|
|
if (!pkgJson[field]) return
|
|
|
|
|
|
|
|
const dependencies = pkgJson[field]
|
|
|
|
|
|
|
|
for (const name of Object.keys(dependencies)) {
|
|
|
|
const value = dependencies[name]
|
|
|
|
|
|
|
|
if (value.startsWith('workspace:')) {
|
2023-11-08 17:28:45 +03:00
|
|
|
if (value !== 'workspace:^' && value !== 'workspace:*') {
|
2023-10-31 21:17:39 +03:00
|
|
|
throw new Error(
|
2023-11-08 17:28:45 +03:00
|
|
|
`Cannot replace workspace dependency ${name} with ${value} - only workspace:^ and * are supported`,
|
2023-10-31 21:17:39 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
if (!name.startsWith('@mtcute/')) {
|
|
|
|
throw new Error(`Cannot replace workspace dependency ${name} - only @mtcute/* is supported`)
|
|
|
|
}
|
|
|
|
|
2023-11-08 17:28:45 +03:00
|
|
|
// note: pnpm replaces workspace:* with the current version, unlike this script
|
|
|
|
const depVersion =
|
|
|
|
value === 'workspace:*' ?
|
|
|
|
'*' :
|
|
|
|
require(path.join(packageDir, '..', name.slice(8), 'package.json')).version
|
2023-10-31 21:17:39 +03:00
|
|
|
dependencies[name] = `^${depVersion}`
|
2023-10-16 19:23:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
replaceWorkspaceDependencies('dependencies')
|
|
|
|
replaceWorkspaceDependencies('devDependencies')
|
|
|
|
replaceWorkspaceDependencies('peerDependencies')
|
|
|
|
replaceWorkspaceDependencies('optionalDependencies')
|
|
|
|
|
|
|
|
delete pkgJson.typedoc
|
|
|
|
|
2023-11-29 20:31:18 +03:00
|
|
|
function maybeFixPath(p, repl) {
|
|
|
|
if (!p) return p
|
|
|
|
|
|
|
|
if (p.startsWith('./src/')) {
|
|
|
|
return repl + p.slice(6)
|
|
|
|
}
|
|
|
|
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pkgJson.browser) {
|
|
|
|
for (const key of Object.keys(pkgJson.browser)) {
|
|
|
|
if (!key.startsWith('./src/')) continue
|
|
|
|
|
|
|
|
const path = key.slice(6)
|
|
|
|
pkgJson.browser[`./esm/${path}`] = maybeFixPath(pkgJson.browser[key], './esm/')
|
|
|
|
|
|
|
|
if (buildConfig.buildCjs) {
|
|
|
|
pkgJson.browser[`./cjs/${path}`] = maybeFixPath(pkgJson.browser[key], './cjs/')
|
|
|
|
}
|
|
|
|
|
|
|
|
delete pkgJson.browser[key]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
fs.writeFileSync(path.join(packageDir, 'dist/package.json'), JSON.stringify(pkgJson, null, 2))
|
|
|
|
}
|
|
|
|
|
|
|
|
// clean
|
|
|
|
fs.rmSync(path.join(outDir), { recursive: true, force: true })
|
|
|
|
fs.mkdirSync(path.join(outDir), { recursive: true })
|
|
|
|
|
2023-11-02 21:23:17 +03:00
|
|
|
buildConfig.before()
|
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
if (buildConfig.buildTs) {
|
|
|
|
console.log('[i] Building typescript...')
|
2023-11-09 00:20:43 +03:00
|
|
|
|
|
|
|
fs.cpSync(path.join(packageDir, 'tsconfig.json'), path.join(packageDir, 'tsconfig.backup.json'))
|
|
|
|
|
|
|
|
let tsconfig = fs.readFileSync(path.join(packageDir, 'tsconfig.backup.json'), 'utf-8')
|
|
|
|
// what the fuck
|
2023-11-13 13:24:42 +03:00
|
|
|
tsconfig = tsconfig.replace(/(?<="extends": "\.\.\/\.\.\/)tsconfig\.json(?=",)/, '.config/tsconfig.build.json')
|
2023-11-09 00:20:43 +03:00
|
|
|
fs.writeFileSync(path.join(packageDir, 'tsconfig.json'), tsconfig)
|
|
|
|
|
2023-11-12 01:17:20 +03:00
|
|
|
const restoreTsconfig = () => {
|
|
|
|
fs.renameSync(path.join(packageDir, 'tsconfig.backup.json'), path.join(packageDir, 'tsconfig.json'))
|
|
|
|
}
|
|
|
|
|
2023-11-09 00:20:43 +03:00
|
|
|
try {
|
|
|
|
exec('pnpm exec tsc --build', { cwd: packageDir, stdio: 'inherit' })
|
|
|
|
} catch (e) {
|
2023-11-12 01:17:20 +03:00
|
|
|
restoreTsconfig()
|
2023-11-09 00:20:43 +03:00
|
|
|
throw e
|
|
|
|
}
|
2023-10-16 19:23:53 +03:00
|
|
|
|
|
|
|
if (buildConfig.buildCjs) {
|
|
|
|
console.log('[i] Building typescript (CJS)...')
|
|
|
|
const originalFiles = {}
|
|
|
|
|
|
|
|
if (buildConfig.esmOnlyDirectives) {
|
|
|
|
for (const f of glob.sync(path.join(packageDir, '**/*.ts'))) {
|
|
|
|
const content = fs.readFileSync(f, 'utf8')
|
|
|
|
if (!content.includes('@only-if-esm')) continue
|
|
|
|
originalFiles[f] = content
|
|
|
|
|
|
|
|
fs.writeFileSync(f, content.replace(/@only-if-esm.*?@\/only-if-esm/gs, ''))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let error = false
|
|
|
|
|
|
|
|
try {
|
|
|
|
exec('pnpm exec tsc --module commonjs --outDir dist/cjs', { cwd: packageDir, stdio: 'inherit' })
|
|
|
|
} catch (e) {
|
|
|
|
error = e
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const f of Object.keys(originalFiles)) {
|
|
|
|
fs.writeFileSync(f, originalFiles[f])
|
|
|
|
}
|
|
|
|
|
2023-11-12 01:17:20 +03:00
|
|
|
if (error) {
|
|
|
|
restoreTsconfig()
|
|
|
|
throw error
|
|
|
|
}
|
2023-10-16 19:23:53 +03:00
|
|
|
}
|
|
|
|
|
2023-11-12 01:17:20 +03:00
|
|
|
restoreTsconfig()
|
2023-11-09 00:20:43 +03:00
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
console.log('[i] Post-processing...')
|
|
|
|
|
|
|
|
if (buildConfig.removeReferenceComments) {
|
|
|
|
for (const f of glob.sync(path.join(outDir, '**/*.d.ts'))) {
|
|
|
|
let content = fs.readFileSync(f, 'utf8')
|
|
|
|
let changed = false
|
|
|
|
|
|
|
|
if (content.indexOf('/// <reference types="node" />') !== -1) {
|
|
|
|
changed = true
|
|
|
|
content = content.replace('/// <reference types="node" />', '')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (content.match(/@mtcute\/[a-z-]+\/src/)) {
|
|
|
|
changed = true
|
|
|
|
content = content.replace(/(@mtcute\/[a-z-]+)\/src/g, '$1')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed) fs.writeFileSync(f, content)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buildConfig.replaceSrcImports) {
|
|
|
|
for (const f of glob.sync(path.join(outDir, '**/*.js'))) {
|
|
|
|
let content = fs.readFileSync(f, 'utf8')
|
|
|
|
let changed = false
|
|
|
|
|
|
|
|
if (content.match(/@mtcute\/[a-z-]+\/src/)) {
|
|
|
|
changed = true
|
|
|
|
content = content.replace(/(@mtcute\/[a-z-]+)\/src/g, '$1')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed) fs.writeFileSync(f, content)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('[i] Copying files...')
|
|
|
|
|
|
|
|
if (buildConfig.buildCjs) {
|
|
|
|
fs.writeFileSync(path.join(outDir, 'cjs/package.json'), JSON.stringify({ type: 'commonjs' }, null, 2))
|
|
|
|
}
|
|
|
|
|
|
|
|
buildPackageJson()
|
|
|
|
|
|
|
|
try {
|
|
|
|
fs.cpSync(path.join(packageDir, 'README.md'), path.join(outDir, 'README.md'))
|
|
|
|
} catch (e) {
|
|
|
|
console.log('[!] Failed to copy README.md: ' + e.message)
|
|
|
|
}
|
|
|
|
|
2023-10-23 12:18:04 +03:00
|
|
|
fs.cpSync(path.join(__dirname, '../LICENSE'), path.join(outDir, 'LICENSE'))
|
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
fs.writeFileSync(path.join(outDir, '.npmignore'), '*.tsbuildinfo\n')
|
|
|
|
|
2023-11-02 21:23:17 +03:00
|
|
|
buildConfig.final()
|
2023-10-16 19:23:53 +03:00
|
|
|
|
|
|
|
console.log('[v] Done!')
|