Registry: resolve dev packages

Also resolve @sap packages, but forward non-cds packages to default
registry
This commit is contained in:
Christian Georgi
2022-08-08 23:10:31 +02:00
parent dff3dd4b89
commit 21be9d1bbf

View File

@@ -1,27 +1,34 @@
const { exec } = require ('child_process') const { exec, execSync } = require ('child_process')
const isWin = process.platform === 'win32' const isWin = process.platform === 'win32'
const express = require ('express') const express = require ('express')
const fs = require ('fs') const fs = require ('fs')
const { dirname, relative } = require('path')
const axios = require('axios')
const app = express() const app = express()
const { PORT=4444 } = process.env
const [,,port=PORT,scope='@capire'] = process.argv
const cwd = __dirname const cwd = __dirname
const port=process.env.PORT || 4444
let scopes = process.argv.filter(a => a.startsWith('@'))
if (!scopes.length) scopes = ['@capire']
// clean up on start (exit handler might not complete on Windows) // clean up on start (exit handler might not complete on Windows)
exec(isWin ? 'del *.tgz' : 'rm *.tgz', {cwd}) exec(isWin ? 'del *.tgz' : 'rm *.tgz', {cwd})
app.use('/-/:tarball', (req,res,next) => { app.use('/-/:tarball', async (req,res,next) => {
console.debug ('GET', req.params) console.debug ('GET', req.params)
try { try {
const { tarball } = req.params const { tarball } = req.params
const pkgFull = tarball.substring(0, tarball.lastIndexOf('-')) const pkgFull = tarball.substring(0, tarball.lastIndexOf('-'))
const [, pkg ] = /^\w+-(.+)/.exec(pkgFull) const scope = '@'+pkgFull.substring(0, pkgFull.indexOf('-'))
const pkg = pkgFull.substring(pkgFull.indexOf('-')+1)
fs.lstat(tarball,(err => { fs.lstat(tarball,(err => {
if (err) console.debug (`npm pack ../${pkg}`) if (err) { // no tgz yet
if (err) exec(`npm pack ../${pkg}`,{cwd},next) const loc = dirname(require.resolve(`${scope}/${pkg}/package.json`))
else next() console.debug (`npm pack ${relative(cwd, loc)}`)
exec(`npm pack ${loc}`,{cwd},next)
}
else next() //> express.static below
})) }))
} catch (e) { } catch (e) {
console.error(e) console.error(e)
@@ -31,14 +38,20 @@ app.use('/-/:tarball', (req,res,next) => {
app.use('/-', express.static(__dirname)) app.use('/-', express.static(__dirname))
app.get('/*', (req,res)=>{ app.get('/*', async (req,res)=>{
const urlRegex = /^\/(@[\w-]+)\/(.+)/ const urlRegex = /^\/(@[\w-]+)\/(.+)/
const url = decodeURIComponent(req.url) const url = decodeURIComponent(req.url)
console.debug ('GET',url) console.debug ('GET',url)
try { try {
if (!urlRegex.test(url)) return res.sendStatus(404) if (!urlRegex.test(url)) return res.sendStatus(404)
const [, scpe, pkg ] = urlRegex.exec(url) const [, scpe, pkg ] = urlRegex.exec(url)
const package = require (`${scpe}/${pkg}/package.json`) const packageName = `${scpe}/${pkg}`
// delegate to default registry for @sap/non-cds packages
if (scpe === ('@sap') && !packageName.startsWith('@sap/cds')) {
return forward(req, res)
}
const package = require (`${packageName}/package.json`)
const tarball = `${scpe.slice(1)}-${pkg}-${package.version}.tgz` const tarball = `${scpe.slice(1)}-${pkg}-${package.version}.tgz`
// https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md // https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md
res.json({ res.json({
@@ -53,6 +66,8 @@ app.get('/*', (req,res)=>{
"dist": { "dist": {
"tarball": `${server.url}/-/${tarball}` "tarball": `${server.url}/-/${tarball}`
}, },
dependencies: package.dependencies,
devDependencies: package.devDependencies
} }
}, },
}) })
@@ -64,15 +79,32 @@ app.get('/*', (req,res)=>{
const server = app.listen(port, ()=>{ const server = app.listen(port, ()=>{
const url = server.url = `http://localhost:${server.address().port}` const url = server.url = `http://localhost:${server.address().port}`
console.log (`npm set ${scope}:registry=${url}`)
exec(`npm set ${scope}:registry=${url}`) for (const scope of scopes) {
console.log (`${scope} registry listening on ${url}`) console.log (`npm set ${scope}:registry=${url}`)
execSync(`npm set ${scope}:registry=${url}`)
}
console.log (`registry listening on ${url}`)
}) })
const _exit = ()=>{ const _exit = ()=>{
server.close() server.close()
exec(`npm conf rm "${scope}:registry"`, ()=> { process.exit() }) for (const scope of scopes) {
execSync(`npm conf rm "${scope}:registry"`)
}
process.exit()
}
async function forward(req, res) {
try {
const url = `https://registry.npmjs.org${req.url}`
const resAxios = await axios.get(url)
console.debug('->', decodeURI(url), resAxios.status)
return res.json(resAxios.data)
} catch (e) {
return res.sendStatus(e.response.status)
}
} }
process.on ('SIGTERM',_exit) process.on ('SIGTERM',_exit)