0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-01-06 22:40:26 -05:00
verdaccio/test/lib/request.ts
2023-08-28 23:03:36 +02:00

309 lines
7.7 KiB
TypeScript

import assert from 'assert';
import buildDebug from 'debug';
import got, { HTTPAlias, Response, Headers as gotHeaders } from 'got-cjs';
import { isNil, isObject, isRegExp } from 'lodash';
import { API_MESSAGE, HEADERS, HTTP_STATUS } from '@verdaccio/core';
import { generatePackageMetadata } from '../helpers/generatePackageMetadata';
const debug = buildDebug('verdaccio:registry:request');
export interface ResponseAssert {
status(reason: any): any;
body_ok(reason: any): any;
body_error(reason: any): any;
request(reason: any): any;
response(reason: any): any;
send(reason: any): any;
}
type Options = {
url: string;
method: HTTPAlias;
headers: gotHeaders;
encoding?: string;
json: boolean;
body?: any;
};
type RegistryResponse = {
ok: string;
error: null | string;
};
class RequestAssert {
private response: Response<RegistryResponse>;
public constructor(response: Response<RegistryResponse>) {
this.response = response;
}
public status(code: number) {
debug('expected check status %s vs response code %s', code, this.response.statusCode);
assert(code === this.response.statusCode);
return this;
}
public equal_body(expected: string | RegExp) {
assert.strictEqual(expected, this.response.body);
}
public body_ok(expected: string | RegExp) {
debug('body expect ok %s', expected);
if (isRegExp(expected)) {
assert(this.response.body?.ok?.match(expected));
assert(
this.response.body?.ok.match(expected),
`'${this.response.body.ok}' doesn't match " ${expected}`
);
} else if (typeof expected === 'string') {
assert.equal(this.response.body?.ok, expected);
} else {
assert.deepEqual(this.response.body, expected);
}
}
public body_error(expected: string | RegExp) {
debug('body expect error %s', expected);
if (isRegExp(expect)) {
assert(
this.response?.body?.error?.match(expected),
`${this.response.body?.error} doesn't match ${expected}`
);
}
assert.equal(this.response.body?.ok, null);
}
}
export async function createRequest(options: Options): Promise<any> {
debug('options %s', JSON.stringify(options));
let body = undefined;
if (isNil(options.body) === false) {
body = isObject(options.body) === false ? JSON.stringify(options.body) : options.body;
}
const method = options?.method?.toLocaleLowerCase();
debug('method %s', method);
debug('url %s', options?.url);
debug('headers %s', options?.headers);
if (method === 'get') {
return got(options.url, {
isStream: false,
resolveBodyOnly: false,
throwHttpErrors: false,
// @ts-ignore
responseType: options.encoding ?? 'json',
headers: options.headers,
method: options.method,
body,
retry: { limit: 0 },
// @ts-ignore
}).then((response) => {
return new RequestAssert(response as any);
});
} else if (method === 'put') {
return (
got
.put(options.url, {
throwHttpErrors: false,
responseType: 'json',
headers: options.headers,
json: options.body ? options.body : undefined,
retry: { limit: 0 },
})
// @ts-ignore
.then((response) => {
return new RequestAssert(response as any);
})
);
} else if (method === 'delete') {
return (
got
.delete(options.url, {
throwHttpErrors: false,
responseType: 'json',
headers: options.headers,
retry: { limit: 0 },
})
// @ts-ignore
.then((response) => {
return new RequestAssert(response as any);
})
);
}
}
export class ServerQuery {
private userAgent: string;
private url: string;
public constructor(url) {
this.url = url.replace(/\/$/, '');
debug('server url %s', this.url);
this.userAgent = 'node/v18.0.0 linux x64';
}
private request(options: any): Promise<ResponseAssert> {
return createRequest({
...options,
url: `${this.url}${options.uri}`,
});
}
public debug(): Promise<ResponseAssert> {
return this.request({
uri: '/-/_debug',
method: 'get',
headers: {
[HEADERS.CONTENT_TYPE]: HEADERS.JSON,
},
});
}
/**
*
*
* @param {{ name: string; password: string }} { name, password }
* @return {*} {Promise<ResponseAssert>}
* @memberof ServerQuery
* @deprecated use createUser instead
*/
public auth({ name, password }: { name: string; password: string }): Promise<ResponseAssert> {
return this.createUser(name, password);
}
public createUser(name, password): Promise<ResponseAssert> {
return this.request({
uri: `/-/user/org.couchdb.user:${encodeURIComponent(name)}`,
method: 'PUT',
body: {
name,
password,
_id: `org.couchdb.user:${name}`,
type: 'user',
roles: [],
date: new Date(),
},
});
}
public logout(token: string) {
return this.request({
uri: `/-/user/token/${encodeURIComponent(token)}`,
method: 'DELETE',
});
}
public getPackage(name: string) {
return this.request({
uri: `/${encodeURIComponent(name)}`,
method: 'get',
});
}
public getTarball(name: string, filename: string) {
return this.request({
uri: `/${encodeURIComponent(name)}/-/${encodeURIComponent(filename)}`,
method: 'GET',
encoding: 'buffer',
});
}
/**
* Remove entire package.
* @param name package name
* @param rev revision id
* @returns
*/
public removePackage(name: string, rev) {
return this.request({
uri: `/${encodeURIComponent(name)}/-rev/${rev}`,
method: 'DELETE',
headers: {
[HEADERS.CONTENT_TYPE]: HEADERS.JSON_CHARSET,
},
});
}
public removeSingleTarball(name: string, filename: string) {
return this.request({
uri: `/${encodeURIComponent(name)}/-/${filename}/-rev/whatever`,
method: 'DELETE',
headers: {
[HEADERS.CONTENT_TYPE]: HEADERS.JSON_CHARSET,
},
});
}
/**
*
* @param name
* @param tag
* @param version
* @returns
*/
public addTag(name: string, tag: string, version: string) {
return this.request({
uri: `/${encodeURIComponent(name)}/${encodeURIComponent(tag)}`,
method: 'PUT',
body: version,
headers: {
[HEADERS.CONTENT_TYPE]: HEADERS.JSON,
},
});
}
public putVersion(name: string, version: string, data: any, headers) {
return this.request({
uri: `/${encodeURIComponent(name)}/${encodeURIComponent(version)}/-tag/latest`,
method: 'PUT',
body: data,
headers: {
[HEADERS.CONTENT_TYPE]: HEADERS.JSON,
...headers,
},
});
}
public putPackage(name: string, data, headers = {}) {
return this.request({
uri: `/${encodeURIComponent(name)}`,
method: 'PUT',
body: data,
headers: {
[HEADERS.CONTENT_TYPE]: HEADERS.JSON,
...headers,
},
});
}
public async addPackage(
name: string,
version: string = '1.0.0',
message = API_MESSAGE.PKG_CREATED
): Promise<ResponseAssert> {
return (await this.putPackage(name, generatePackageMetadata(name, version)))
.status(HTTP_STATUS.CREATED)
.body_ok(message);
}
public async addPackageAssert(name: string, version: string = '1.0.0'): Promise<ResponseAssert> {
return this.putPackage(name, generatePackageMetadata(name, version));
}
public async whoami() {
debug('request whoami');
return await this.request({
uri: '/-/whoami',
method: 'get',
});
}
public async ping() {
return (
await this.request({
uri: '/-/ping',
method: 'get',
})
).status(HTTP_STATUS.OK);
}
}