2024-08-13 04:53:07 +03:00
|
|
|
import * as cp from 'node:child_process'
|
|
|
|
import * as fs from 'node:fs'
|
|
|
|
import { createRequire } from 'node:module'
|
|
|
|
import * as path from 'node:path'
|
|
|
|
import { fileURLToPath } from 'node:url'
|
2021-06-06 00:37:44 +03:00
|
|
|
|
2024-08-12 09:19:45 +03:00
|
|
|
import * as stc from '@teidesu/slow-types-compiler'
|
2024-08-13 04:53:07 +03:00
|
|
|
|
2024-04-20 01:07:53 +03:00
|
|
|
const IS_JSR = process.env.JSR === '1'
|
2024-05-08 02:44:54 +03:00
|
|
|
const MAIN_REGISTRY = IS_JSR ? 'https://jsr.io/' : 'https://registry.npmjs.org'
|
2024-04-23 13:20:42 +03:00
|
|
|
let REGISTRY = process.env.REGISTRY || MAIN_REGISTRY
|
2024-08-12 09:19:45 +03:00
|
|
|
const EXPORTED_REGISTRY = REGISTRY
|
|
|
|
|
|
|
|
const __dirname = path.dirname(new URL(import.meta.url).pathname)
|
|
|
|
const require = createRequire(import.meta.url)
|
|
|
|
|
2024-04-23 13:20:42 +03:00
|
|
|
if (!REGISTRY.endsWith('/')) REGISTRY += '/'
|
|
|
|
|
|
|
|
if (process.env.E2E && IS_JSR) {
|
|
|
|
// running behind a socat proxy seems to fix some of the docker networking issues (thx kamillaova)
|
|
|
|
const hostname = new URL(REGISTRY).hostname
|
|
|
|
const port = new URL(REGISTRY).port || { 'http:': 80, 'https:': 443 }[new URL(REGISTRY).protocol]
|
|
|
|
cp.spawn('bash', ['-c', `socat TCP-LISTEN:1234,fork,reuseaddr TCP4:${hostname}:${port}`], { stdio: 'ignore' })
|
|
|
|
REGISTRY = 'http://localhost:1234/'
|
|
|
|
}
|
2021-06-06 00:37:44 +03:00
|
|
|
|
2024-04-20 01:07:53 +03:00
|
|
|
if (IS_JSR) {
|
|
|
|
// for the underlying tools that expect JSR_URL env var
|
|
|
|
process.env.JSR_URL = REGISTRY
|
|
|
|
}
|
|
|
|
|
|
|
|
const JSR_EXCEPTIONS = {
|
2024-08-13 04:53:07 +03:00
|
|
|
'bun': 'never',
|
2024-04-20 01:07:53 +03:00
|
|
|
'create-bot': 'never',
|
|
|
|
'crypto-node': 'never',
|
2024-08-13 04:53:07 +03:00
|
|
|
'deno': 'only',
|
|
|
|
'node': 'never',
|
2024-04-20 01:07:53 +03:00
|
|
|
'http-proxy': 'never',
|
|
|
|
'socks-proxy': 'never',
|
2024-08-13 04:53:07 +03:00
|
|
|
'mtproxy': 'never',
|
|
|
|
'test': 'never',
|
2024-04-20 01:07:53 +03:00
|
|
|
}
|
|
|
|
|
2024-04-23 13:20:42 +03:00
|
|
|
function fetchRetry(url, init, retry = 0) {
|
|
|
|
return fetch(url, init).catch((err) => {
|
|
|
|
if (retry >= 5) throw err
|
|
|
|
|
|
|
|
// for whatever reason this request sometimes fails with ECONNRESET
|
|
|
|
// no idea why, probably some issue in docker networking
|
2024-08-21 11:05:07 +03:00
|
|
|
if (err.cause?.code !== 'UND_ERR_SOCKET') {
|
|
|
|
console.log('[i] Error fetching %s:', url)
|
|
|
|
console.log(err)
|
|
|
|
}
|
2024-04-23 13:20:42 +03:00
|
|
|
|
2024-08-13 04:53:07 +03:00
|
|
|
return new Promise(resolve => setTimeout(resolve, 1000)).then(() => fetchRetry(url, init, retry + 1))
|
2024-04-23 13:20:42 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async function checkVersion(name, version) {
|
2024-08-13 04:53:07 +03:00
|
|
|
const registry = REGISTRY
|
2023-12-29 16:18:59 +03:00
|
|
|
|
2024-04-20 01:07:53 +03:00
|
|
|
const url = IS_JSR ? `${registry}@mtcute/${name}/${version}_meta.json` : `${registry}@mtcute/${name}/${version}`
|
|
|
|
|
2024-08-13 04:53:07 +03:00
|
|
|
return fetchRetry(url).then(r => r.status === 200)
|
2024-04-23 13:20:42 +03:00
|
|
|
}
|
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
async function publishSinglePackage(name) {
|
2024-08-13 04:53:07 +03:00
|
|
|
const packageDir = path.join(__dirname, '../packages', name)
|
2021-06-06 19:23:43 +03:00
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
console.log('[i] Building %s', name)
|
2021-06-06 19:23:43 +03:00
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
// run build script
|
2024-08-21 11:05:07 +03:00
|
|
|
cp.execSync(`pnpm run build-package ${name}`, {
|
2023-10-16 19:23:53 +03:00
|
|
|
stdio: 'inherit',
|
|
|
|
})
|
2021-06-06 19:23:43 +03:00
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
console.log('[i] Publishing %s', name)
|
2021-06-06 19:23:43 +03:00
|
|
|
|
2024-08-13 04:53:07 +03:00
|
|
|
const version = IS_JSR
|
|
|
|
? require(path.join(packageDir, 'dist/jsr/deno.json')).version
|
|
|
|
: require(path.join(packageDir, 'dist/package.json')).version
|
2021-06-06 19:23:43 +03:00
|
|
|
|
2023-12-29 16:18:59 +03:00
|
|
|
const exists = await checkVersion(name, version)
|
2021-06-06 19:23:43 +03:00
|
|
|
|
2023-12-29 16:18:59 +03:00
|
|
|
if (exists) {
|
2024-04-20 01:07:53 +03:00
|
|
|
if (process.env.E2E && !IS_JSR) {
|
2023-10-16 19:23:53 +03:00
|
|
|
console.log('[i] %s already exists, unpublishing..', name)
|
|
|
|
cp.execSync(`npm unpublish --registry ${REGISTRY} --force @mtcute/${name}`, {
|
|
|
|
cwd: path.join(packageDir, 'dist'),
|
|
|
|
stdio: 'inherit',
|
|
|
|
})
|
2023-12-29 16:18:59 +03:00
|
|
|
} else {
|
|
|
|
console.log('[i] %s already exists, skipping..', name)
|
|
|
|
|
|
|
|
return
|
2021-06-06 19:23:43 +03:00
|
|
|
}
|
2024-04-23 13:20:42 +03:00
|
|
|
} else if (IS_JSR && process.env.JSR_TOKEN) {
|
2024-04-29 01:36:42 +03:00
|
|
|
await stc.jsrMaybeCreatePackage({
|
|
|
|
name: `@mtcute/${name}`,
|
|
|
|
token: process.env.JSR_TOKEN,
|
|
|
|
registry: REGISTRY,
|
|
|
|
})
|
2021-06-06 19:23:43 +03:00
|
|
|
}
|
|
|
|
|
2024-04-20 01:07:53 +03:00
|
|
|
if (IS_JSR) {
|
|
|
|
// publish to jsr
|
2024-04-23 13:20:42 +03:00
|
|
|
const params = process.env.JSR_TOKEN ? `--token ${process.env.JSR_TOKEN}` : ''
|
2024-05-08 02:44:54 +03:00
|
|
|
cp.execSync(`deno publish --allow-dirty --quiet ${params}`, {
|
2024-04-20 01:07:53 +03:00
|
|
|
cwd: path.join(packageDir, 'dist/jsr'),
|
|
|
|
stdio: 'inherit',
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
// make sure dist/jsr doesn't exist (it shouldn't, but just in case)
|
|
|
|
if (fs.existsSync(path.join(packageDir, 'dist/jsr'))) {
|
|
|
|
fs.rmdirSync(path.join(packageDir, 'dist/jsr'), { recursive: true })
|
|
|
|
}
|
2022-05-06 13:23:29 +03:00
|
|
|
|
2024-04-20 01:07:53 +03:00
|
|
|
// publish to npm
|
|
|
|
const params = REGISTRY === MAIN_REGISTRY ? '--access public' : '--force'
|
|
|
|
cp.execSync(`npm publish --registry ${REGISTRY} ${params} -q`, {
|
|
|
|
cwd: path.join(packageDir, 'dist'),
|
|
|
|
stdio: 'inherit',
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-05-06 13:23:29 +03:00
|
|
|
|
2024-05-09 02:26:53 +03:00
|
|
|
function listPackages(all = false) {
|
2024-04-20 01:07:53 +03:00
|
|
|
let packages = []
|
2021-06-06 19:23:43 +03:00
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
for (const f of fs.readdirSync(path.join(__dirname, '../packages'))) {
|
|
|
|
if (f[0] === '.') continue
|
2024-05-09 02:26:53 +03:00
|
|
|
|
|
|
|
if (!all) {
|
|
|
|
if (IS_JSR && JSR_EXCEPTIONS[f] === 'never') continue
|
|
|
|
if (!IS_JSR && JSR_EXCEPTIONS[f] === 'only') continue
|
|
|
|
}
|
2021-06-06 00:37:44 +03:00
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
packages.push(f)
|
2021-06-06 19:23:43 +03:00
|
|
|
}
|
|
|
|
|
2024-04-20 01:07:53 +03:00
|
|
|
if (IS_JSR) {
|
|
|
|
// we should sort them in a way that dependencies are published first. stc has a util for that
|
|
|
|
const map = {}
|
|
|
|
|
|
|
|
for (const pkg of packages) {
|
|
|
|
const deps = require(`../packages/${pkg}/package.json`).dependencies || {}
|
|
|
|
map[pkg] = Object.keys(deps)
|
2024-08-13 04:53:07 +03:00
|
|
|
.filter(d => d.startsWith('@mtcute/'))
|
|
|
|
.map(d => d.slice(8))
|
2024-04-20 01:07:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
packages = stc.determinePublishOrder(map)
|
|
|
|
console.log('[i] Publishing order:', packages.join(', '))
|
|
|
|
}
|
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
return packages
|
2021-06-06 00:37:44 +03:00
|
|
|
}
|
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
async function main(arg = process.argv[2]) {
|
2021-06-06 00:37:44 +03:00
|
|
|
if (!arg) {
|
2023-10-16 19:23:53 +03:00
|
|
|
console.log('Usage: publish.js <package name | all | updated>')
|
2021-06-06 00:37:44 +03:00
|
|
|
process.exit(0)
|
|
|
|
}
|
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
console.log('[i] Using registry %s', REGISTRY)
|
2021-06-06 00:37:44 +03:00
|
|
|
|
2023-12-29 16:55:34 +03:00
|
|
|
const publishedPkgs = []
|
2024-03-24 01:31:44 +03:00
|
|
|
const failedPkgs = []
|
2023-10-31 21:17:39 +03:00
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
if (arg === 'all' || arg === 'updated') {
|
|
|
|
for (const pkg of listPackages()) {
|
2023-12-29 15:55:24 +03:00
|
|
|
const pkgVersion = require(`../packages/${pkg}/package.json`).version
|
|
|
|
const published = await checkVersion(pkg, pkgVersion)
|
|
|
|
|
2024-04-22 00:05:08 +03:00
|
|
|
if (published && !process.env.E2E) {
|
2023-12-29 15:55:24 +03:00
|
|
|
console.log('[i] %s is up to date', pkg)
|
|
|
|
continue
|
2023-10-16 19:23:53 +03:00
|
|
|
}
|
|
|
|
|
2024-03-24 01:31:44 +03:00
|
|
|
try {
|
|
|
|
await publishSinglePackage(pkg)
|
|
|
|
publishedPkgs.push(pkg)
|
|
|
|
} catch (e) {
|
|
|
|
console.error('[!] Failed to publish %s:', pkg)
|
|
|
|
console.error(e)
|
2024-04-23 13:20:42 +03:00
|
|
|
if (IS_JSR || process.env.E2E) throw e
|
2024-03-24 01:31:44 +03:00
|
|
|
failedPkgs.push(pkg)
|
|
|
|
}
|
2021-06-06 00:37:44 +03:00
|
|
|
}
|
|
|
|
} else {
|
2024-05-08 02:44:54 +03:00
|
|
|
let pkgs = arg.split(',')
|
2024-08-13 04:53:07 +03:00
|
|
|
const filteredPkgs = []
|
2024-05-08 02:44:54 +03:00
|
|
|
|
|
|
|
const deps = {}
|
|
|
|
// determine the order of packages to publish
|
|
|
|
|
|
|
|
for (const pkg of pkgs) {
|
|
|
|
if (IS_JSR && JSR_EXCEPTIONS[pkg] === 'never') continue
|
|
|
|
if (!IS_JSR && JSR_EXCEPTIONS[pkg] === 'only') continue
|
|
|
|
|
2024-05-09 02:26:53 +03:00
|
|
|
filteredPkgs.push(pkg)
|
|
|
|
|
2024-05-08 02:44:54 +03:00
|
|
|
if (IS_JSR) {
|
|
|
|
const pkgDeps = require(`../packages/${pkg}/package.json`).dependencies || {}
|
|
|
|
deps[pkg] = Object.keys(pkgDeps)
|
2024-08-13 04:53:07 +03:00
|
|
|
.filter(d => d.startsWith('@mtcute/'))
|
|
|
|
.map(d => d.slice(8))
|
2024-05-08 02:44:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-09 02:26:53 +03:00
|
|
|
pkgs = filteredPkgs
|
|
|
|
|
2024-05-08 02:44:54 +03:00
|
|
|
if (IS_JSR) {
|
|
|
|
pkgs = stc.determinePublishOrder(deps)
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const pkg of pkgs) {
|
2024-03-24 01:31:44 +03:00
|
|
|
try {
|
|
|
|
await publishSinglePackage(pkg)
|
|
|
|
publishedPkgs.push(pkg)
|
|
|
|
} catch (e) {
|
|
|
|
console.error('[!] Failed to publish %s:', pkg)
|
|
|
|
console.error(e)
|
2024-04-23 13:20:42 +03:00
|
|
|
if (IS_JSR || process.env.E2E) throw e
|
|
|
|
|
2024-03-24 01:31:44 +03:00
|
|
|
failedPkgs.push(pkg)
|
|
|
|
}
|
2023-10-31 21:17:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-24 01:31:44 +03:00
|
|
|
if (failedPkgs.length > 0) {
|
|
|
|
console.error('[!] Failed to publish packages:')
|
|
|
|
|
|
|
|
for (const pkg of failedPkgs) {
|
|
|
|
console.error(' - %s', pkg)
|
|
|
|
}
|
|
|
|
process.exit(1)
|
|
|
|
}
|
|
|
|
|
2023-10-31 21:17:39 +03:00
|
|
|
if (process.env.GH_RELEASE) {
|
|
|
|
// we should also generate tgz files for all published packages
|
|
|
|
// for a github release, and also generate a title
|
|
|
|
const tarballs = []
|
|
|
|
|
2023-12-29 16:55:34 +03:00
|
|
|
for (const pkg of publishedPkgs) {
|
2023-10-31 21:17:39 +03:00
|
|
|
const dir = path.join(__dirname, '../packages', pkg, 'dist')
|
|
|
|
const tar = cp.execSync('npm pack -q', { cwd: dir })
|
|
|
|
tarballs.push(path.join(dir, tar.toString().trim()))
|
|
|
|
}
|
|
|
|
|
|
|
|
fs.writeFileSync(process.env.GITHUB_OUTPUT, `tarballs=${tarballs.join(',')}\n`, { flag: 'a' })
|
2021-06-06 00:37:44 +03:00
|
|
|
}
|
2024-04-13 06:59:12 +03:00
|
|
|
|
|
|
|
process.exit(0) // idk why but it sometimes hangs indefinitely
|
2021-06-06 00:37:44 +03:00
|
|
|
}
|
2023-10-16 19:23:53 +03:00
|
|
|
|
2024-08-12 09:19:45 +03:00
|
|
|
export { listPackages, main, EXPORTED_REGISTRY as REGISTRY }
|
2023-10-16 19:23:53 +03:00
|
|
|
|
2024-08-12 09:19:45 +03:00
|
|
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
|
|
await main()
|
2023-10-16 19:23:53 +03:00
|
|
|
}
|