⚝
One Hat Cyber Team
⚝
Your IP:
172.22.0.1
Server IP:
151.80.20.34
Server:
Linux 794f04d97d5e 5.15.0-143-generic #153-Ubuntu SMP Fri Jun 13 19:10:45 UTC 2025 x86_64
Server Software:
Apache/2.4.62 (Debian)
PHP Version:
8.2.28
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
nodejs
/
@npmcli
/
mock-registry
/
lib
/
Edit File: index.js
const pacote = require('pacote') const Arborist = require('@npmcli/arborist') const npa = require('npm-package-arg') const Nock = require('nock') class MockRegistry { #tap #nock #registry #authorization #basic #debug #strict constructor (opts) { if (!opts.registry) { throw new Error('mock registry requires a registry value') } this.#registry = (new URL(opts.registry)).origin this.#authorization = opts.authorization this.#basic = opts.basic this.#debug = opts.debug this.#strict = opts.strict // Required for this.package this.#tap = opts.tap if (this.#tap) { this.startNock() } } static tnock (t, host, opts, { debug = false, strict = false } = {}) { const noMatch = (req) => { if (strict) { // There are network requests that get caught regardless of error code. // Turning on strict mode requires that those requests get explicitly // mocked with a 404, 500, etc. // XXX: this is opt-in currently because it breaks some existing CLI // tests. We should work towards making this the default for all tests. t.fail(`Unmatched request: ${JSON.stringify(req.options, null, 2)}`) } if (debug) { console.error('NO MATCH', t.name, req.options) } } Nock.emitter.on('no match', noMatch) Nock.disableNetConnect() const server = Nock(host, opts) if (strict) { // this requires that mocks not be shared between sub tests but it helps // find mistakes quicker instead of waiting for the entire test to end t.afterEach((t) => { t.strictSame(server.pendingMocks(), [], 'no pending mocks after each') t.strictSame(server.activeMocks(), [], 'no active mocks after each') }) } t.teardown(() => { Nock.enableNetConnect() server.done() Nock.emitter.off('no match', noMatch) }) return server } get origin () { return this.#registry } get nock () { return this.#nock } set nock (nock) { this.#nock = nock } startNock () { if (this.nock) { return } if (!this.#tap) { throw new Error('cannot mock packages without a tap fixture') } const reqheaders = {} if (this.#authorization) { reqheaders.authorization = `Bearer ${this.#authorization}` } if (this.#basic) { reqheaders.authorization = `Basic ${this.#basic}` } this.nock = MockRegistry.tnock( this.#tap, this.#registry, { reqheaders }, { debug: this.#debug, strict: this.#strict } ) } search ({ responseCode = 200, results = [], error }) { // the flags, score, and searchScore parts of the response are never used // by npm, only package is used const response = results.map(p => ({ package: p })) this.nock = this.nock.get('/-/v1/search').query(true) if (error) { this.nock = this.nock.replyWithError(error) } else { this.nock = this.nock.reply(responseCode, { objects: response }) } return this.nock } whoami ({ username, body, responseCode = 200, times = 1 }) { if (username) { this.nock = this.nock.get('/-/whoami').times(times).reply(responseCode, { username }) } else { this.nock = this.nock.get('/-/whoami').times(times).reply(responseCode, body) } } setAccess ({ spec, body = {} }) { this.nock = this.nock.post( `/-/package/${npa(spec).escapedName}/access`, body ).reply(200) } getVisibility ({ spec, visibility }) { this.nock = this.nock.get(`/-/package/${npa(spec).escapedName}/visibility`) .reply(200, visibility) } setPermissions ({ spec, team, permissions }) { if (team.startsWith('@')) { team = team.slice(1) } const [scope, teamName] = team.split(':') this.nock = this.nock.put( `/-/team/${encodeURIComponent(scope)}/${encodeURIComponent(teamName)}/package`, { package: spec, permissions } ).reply(200) } removePermissions ({ spec, team }) { if (team.startsWith('@')) { team = team.slice(1) } const [scope, teamName] = team.split(':') this.nock = this.nock.delete( `/-/team/${encodeURIComponent(scope)}/${encodeURIComponent(teamName)}/package`, { package: spec } ).reply(200) } couchuser ({ username, body, responseCode = 200 }) { if (body) { this.nock = this.nock.get(`/-/user/org.couchdb.user:${encodeURIComponent(username)}`) .reply(responseCode, body) } else { this.nock = this.nock.get(`/-/user/org.couchdb.user:${encodeURIComponent(username)}`) .reply(responseCode, { _id: `org.couchdb.user:${username}`, email: '', name: username }) } } couchadduser ({ username, email, password, token = 'npm_default-test-token' }) { this.nock = this.nock.put(`/-/user/org.couchdb.user:${username}`, body => { this.#tap.match(body, { _id: `org.couchdb.user:${username}`, name: username, email, // Sole difference from couchlogin password, type: 'user', roles: [], }) if (!body.date) { return false } return true }).reply(201, { id: 'org.couchdb.user:undefined', rev: '_we_dont_use_revs_any_more', token, }) } couchlogin ({ username, password, token = 'npm_default-test-token' }) { this.nock = this.nock.put(`/-/user/org.couchdb.user:${username}`, body => { this.#tap.match(body, { _id: `org.couchdb.user:${username}`, name: username, password, type: 'user', roles: [], }) if (!body.date) { return false } return true }).reply(201, { id: 'org.couchdb.user:undefined', rev: '_we_dont_use_revs_any_more', token, }) } webadduser ({ username, password, token = 'npm_default-test-token' }) { const doneUrl = new URL('/npm-cli-test/done', this.#registry).href const loginUrl = new URL('/npm-cli-test/login', this.#registry).href this.nock = this.nock .post('/-/v1/login', body => { this.#tap.ok(body.create) // Sole difference from weblogin this.#tap.ok(body.hostname) return true }) .reply(200, { doneUrl, loginUrl }) .get('/npm-cli-test/done') .reply(200, { token }) } weblogin ({ token = 'npm_default-test-token' }) { const doneUrl = new URL('/npm-cli-test/done', this.#registry).href const loginUrl = new URL('/npm-cli-test/login', this.#registry).href this.nock = this.nock .post('/-/v1/login', body => { this.#tap.ok(body.hostname) return true }) .reply(200, { doneUrl, loginUrl }) .get('/npm-cli-test/done') .reply(200, { token }) } // team can be a team or a username getPackages ({ user, team, packages = {}, times = 1, responseCode = 200 }) { let uri if (user) { uri = `/-/user/${user}/package` } else { if (team.startsWith('@')) { team = team.slice(1) } const [scope, teamName] = team.split(':').map(encodeURIComponent) if (teamName) { uri = `/-/team/${scope}/${teamName}/package` } else { uri = `/-/org/${scope}/package` } } this.nock = this.nock.get(uri).times(times).reply(responseCode, packages) } getCollaborators ({ spec, collaborators = {} }) { this.nock = this.nock.get(`/-/package/${npa(spec).escapedName}/collaborators`) .reply(200, collaborators) } advisory (advisory = {}) { const id = advisory.id || parseInt(Math.random() * 1000000) return { id, url: `https://github.com/advisories/GHSA-${id}`, title: `Test advisory ${id}`, severity: 'high', vulnerable_versions: '*', cwe: [ 'cwe-0', ], cvss: { score: 0, }, ...advisory, } } star (manifest, users) { const spec = npa(manifest.name) this.nock = this.nock.put(`/${spec.escapedName}`, { _id: manifest._id, _rev: manifest._rev, users, }).reply(200, { ...manifest, users }) } ping ({ body = {}, responseCode = 200 } = {}) { this.nock = this.nock.get('/-/ping?write=true').reply(responseCode, body) } async package ({ manifest, times = 1, query, tarballs }) { let nock = this.nock const spec = npa(manifest.name) nock = nock.get(`/${spec.escapedName}`).times(times) if (query) { nock = nock.query(query) } nock = nock.reply(200, manifest) if (tarballs) { for (const version in tarballs) { const m = manifest.versions[version] nock = await this.tarball({ manifest: m, tarball: tarballs[version] }) } } this.nock = nock } async tarball ({ manifest, tarball }) { const nock = this.nock const dist = new URL(manifest.dist.tarball) const tar = await pacote.tarball(tarball, { Arborist }) nock.get(dist.pathname).reply(200, tar) return nock } // either pass in packuments if you need to set specific attributes besides version, // or an array of versions // the last packument in the packuments or versions array will be tagged latest manifest ({ name = 'test-package', users, packuments, versions } = {}) { packuments = this.packuments(versions || packuments, name) const latest = packuments.slice(-1)[0] const manifest = { _id: `${name}@${latest.version}`, _rev: '00-testdeadbeef', name, description: 'test package mock manifest', dependencies: {}, versions: {}, time: {}, 'dist-tags': { latest: latest.version }, ...latest, } if (users) { manifest.users = users } for (const packument of packuments) { const unscoped = name.includes('/') ? name.split('/')[1] : name manifest.versions[packument.version] = { _id: `${name}@${packument.version}`, name, description: 'test package mock manifest', dependencies: {}, dist: { tarball: `${this.#registry}/${name}/-/${unscoped}-${packument.version}.tgz`, }, maintainers: [], ...packument, } manifest.time[packument.version] = new Date() } return manifest } packuments (packuments = ['1.0.0'], name) { return packuments.map(p => this.packument(p, name)) } // Generate packument from shorthand packument (packument, name = 'test-package') { if (!packument.version) { packument = { version: packument } } return { name, version: '1.0.0', description: 'mocked test package', dependencies: {}, ...packument, } } } module.exports = MockRegistry
Simpan