@verdaccio/web 6.0.0-6-next.26 → 6.0.0-6-next.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/build/api/readme.js +2 -3
- package/build/api/readme.js.map +1 -1
- package/build/api/search.js +64 -61
- package/build/api/search.js.map +1 -1
- package/build/middleware/render-web.d.ts +1 -1
- package/build/middleware/render-web.js +1 -6
- package/build/middleware/render-web.js.map +1 -1
- package/build/middleware/web-api.js +1 -6
- package/build/middleware/web-api.js.map +1 -1
- package/build/renderHTML.js +3 -0
- package/build/renderHTML.js.map +1 -1
- package/build/web-middleware.js +1 -1
- package/build/web-middleware.js.map +1 -1
- package/package.json +19 -15
- package/src/api/readme.ts +2 -3
- package/src/api/search.ts +64 -55
- package/src/middleware/render-web.ts +1 -3
- package/src/middleware/web-api.ts +0 -2
- package/src/renderHTML.ts +6 -1
- package/src/web-middleware.ts +1 -1
- package/test/api.readme.test.ts +29 -27
- package/test/api.search.test.ts +18 -45
- package/test/api.sidebar.test.ts +22 -36
- package/test/api.user.test.ts +1 -1
- package/test/config/default-test.yaml +1 -5
- package/test/config/login-disabled.yaml +1 -5
- package/test/helper.ts +7 -23
- package/test/partials/search/search-v1.json +157 -0
- package/test/render.test.ts +1 -1
- package/tsconfig.json +6 -0
package/src/api/search.ts
CHANGED
|
@@ -1,55 +1,39 @@
|
|
|
1
1
|
import buildDebug from 'debug';
|
|
2
2
|
import { Router } from 'express';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
import { URLSearchParams } from 'url';
|
|
3
5
|
|
|
4
6
|
import { IAuth } from '@verdaccio/auth';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
+
import { errorUtils, searchUtils } from '@verdaccio/core';
|
|
8
|
+
import { SearchQuery } from '@verdaccio/core/src/search-utils';
|
|
7
9
|
import { Storage } from '@verdaccio/store';
|
|
8
|
-
import {
|
|
10
|
+
import { Manifest } from '@verdaccio/types';
|
|
9
11
|
|
|
10
12
|
import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from './package';
|
|
11
13
|
|
|
12
14
|
const debug = buildDebug('verdaccio:web:api:search');
|
|
13
15
|
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
auth.allow_access(
|
|
29
|
-
{ packageName: pkg.name },
|
|
30
|
-
remoteUser,
|
|
31
|
-
function (err, allowed): void {
|
|
32
|
-
debug('is allowed %o', allowed);
|
|
33
|
-
if (err || !allowed) {
|
|
34
|
-
debug('deny access');
|
|
35
|
-
reject(err);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
debug('access succeed');
|
|
39
|
-
resolve(pkg.versions[pkg[DIST_TAGS].latest]);
|
|
40
|
-
}
|
|
41
|
-
);
|
|
42
|
-
} else {
|
|
43
|
-
reject(err);
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
} catch (err: any) {
|
|
48
|
-
reject(err);
|
|
16
|
+
function checkAccess(pkg: any, auth: any, remoteUser): Promise<Manifest | null> {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
auth.allow_access({ packageName: pkg?.package?.name }, remoteUser, function (err, allowed) {
|
|
19
|
+
if (err) {
|
|
20
|
+
if (err.status && String(err.status).match(/^4\d\d$/)) {
|
|
21
|
+
// auth plugin returns 4xx user error,
|
|
22
|
+
// that's equivalent of !allowed basically
|
|
23
|
+
allowed = false;
|
|
24
|
+
return resolve(null);
|
|
25
|
+
} else {
|
|
26
|
+
reject(err);
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
return resolve(allowed ? pkg : null);
|
|
49
30
|
}
|
|
50
31
|
});
|
|
51
|
-
};
|
|
32
|
+
});
|
|
33
|
+
}
|
|
52
34
|
|
|
35
|
+
function addSearchWebApi(storage: Storage, auth: IAuth): Router {
|
|
36
|
+
const router = Router(); /* eslint new-cap: 0 */
|
|
53
37
|
router.get(
|
|
54
38
|
'/search/:anything',
|
|
55
39
|
async function (
|
|
@@ -57,22 +41,47 @@ function addSearchWebApi(storage: Storage, auth: IAuth): Router {
|
|
|
57
41
|
res: $ResponseExtend,
|
|
58
42
|
next: $NextFunctionVer
|
|
59
43
|
): Promise<void> {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
44
|
+
try {
|
|
45
|
+
let data;
|
|
46
|
+
const abort = new AbortController();
|
|
47
|
+
req.on('aborted', () => {
|
|
48
|
+
debug('search web aborted');
|
|
49
|
+
abort.abort();
|
|
50
|
+
});
|
|
51
|
+
const text: string = (req.params.anything as string) ?? '';
|
|
52
|
+
// These values are declared as optimal by npm cli
|
|
53
|
+
// FUTURE: could be overwritten by ui settings.
|
|
54
|
+
const size = 20;
|
|
55
|
+
const from = 0;
|
|
56
|
+
const query: SearchQuery = {
|
|
57
|
+
from: 0,
|
|
58
|
+
maintenance: 0.5,
|
|
59
|
+
popularity: 0.98,
|
|
60
|
+
quality: 0.65,
|
|
61
|
+
size: 20,
|
|
62
|
+
text,
|
|
63
|
+
};
|
|
64
|
+
// @ts-ignore
|
|
65
|
+
const urlParams = new URLSearchParams(query);
|
|
66
|
+
debug('search web init');
|
|
67
|
+
data = await storage.searchManager?.search({
|
|
68
|
+
query,
|
|
69
|
+
url: `/-/v1/search?${urlParams.toString()}`,
|
|
70
|
+
abort,
|
|
71
|
+
});
|
|
72
|
+
const checkAccessPromises: searchUtils.SearchItemPkg[] = await Promise.all(
|
|
73
|
+
data.map((pkgItem) => {
|
|
74
|
+
return checkAccess(pkgItem, auth, req.remote_user);
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const final: searchUtils.SearchItemPkg[] = checkAccessPromises
|
|
79
|
+
.filter((i) => !_.isNull(i))
|
|
80
|
+
.slice(from, size);
|
|
81
|
+
|
|
82
|
+
next(final);
|
|
83
|
+
} catch (err: any) {
|
|
84
|
+
next(errorUtils.getInternalError(err.message));
|
|
76
85
|
}
|
|
77
86
|
}
|
|
78
87
|
);
|
|
@@ -5,7 +5,6 @@ import path from 'path';
|
|
|
5
5
|
|
|
6
6
|
import { HTTP_STATUS } from '@verdaccio/core';
|
|
7
7
|
import { loadPlugin } from '@verdaccio/loaders';
|
|
8
|
-
import { SearchInstance } from '@verdaccio/store';
|
|
9
8
|
import { isURLhasValidProtocol } from '@verdaccio/url';
|
|
10
9
|
|
|
11
10
|
import renderHTML from '../renderHTML';
|
|
@@ -40,10 +39,9 @@ const sendFileCallback = (next) => (err) => {
|
|
|
40
39
|
}
|
|
41
40
|
};
|
|
42
41
|
|
|
43
|
-
export function renderWebMiddleware(config, auth
|
|
42
|
+
export function renderWebMiddleware(config, auth): any {
|
|
44
43
|
const { staticPath, manifest, manifestFiles } = require('@verdaccio/ui-theme')();
|
|
45
44
|
debug('static path %o', staticPath);
|
|
46
|
-
SearchInstance.configureStorage(storage);
|
|
47
45
|
|
|
48
46
|
/* eslint new-cap:off */
|
|
49
47
|
const router = express.Router();
|
|
@@ -3,7 +3,6 @@ import { Router } from 'express';
|
|
|
3
3
|
|
|
4
4
|
import { IAuth } from '@verdaccio/auth';
|
|
5
5
|
import { match, validateName, validatePackage } from '@verdaccio/middleware';
|
|
6
|
-
import { SearchInstance } from '@verdaccio/store';
|
|
7
6
|
import { Storage } from '@verdaccio/store';
|
|
8
7
|
import { Config } from '@verdaccio/types';
|
|
9
8
|
|
|
@@ -13,7 +12,6 @@ import { setSecurityWebHeaders } from './security';
|
|
|
13
12
|
export function webAPI(config: Config, auth: IAuth, storage: Storage): Router {
|
|
14
13
|
// eslint-disable-next-line new-cap
|
|
15
14
|
const route = Router();
|
|
16
|
-
SearchInstance.configureStorage(storage);
|
|
17
15
|
// validate all of these params as a package name
|
|
18
16
|
// this might be too harsh, so ask if it causes trouble=
|
|
19
17
|
route.param('package', validatePackage);
|
package/src/renderHTML.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { URL } from 'url';
|
|
|
4
4
|
|
|
5
5
|
import { WEB_TITLE } from '@verdaccio/config';
|
|
6
6
|
import { HEADERS } from '@verdaccio/core';
|
|
7
|
+
import { TemplateUIOptions } from '@verdaccio/types';
|
|
7
8
|
import { getPublicUrl } from '@verdaccio/url';
|
|
8
9
|
|
|
9
10
|
import renderTemplate from './template';
|
|
@@ -32,6 +33,9 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
|
|
|
32
33
|
const logoURI = config?.web?.logo ?? '';
|
|
33
34
|
const pkgManagers = config?.web?.pkgManagers ?? ['yarn', 'pnpm', 'npm'];
|
|
34
35
|
const version = pkgJSON.version;
|
|
36
|
+
const flags = {
|
|
37
|
+
...config.flags,
|
|
38
|
+
};
|
|
35
39
|
const primaryColor = validatePrimaryColor(config?.web?.primary_color) ?? '#4b5e40';
|
|
36
40
|
const { scriptsBodyAfter, metaScripts, scriptsbodyBefore } = Object.assign(
|
|
37
41
|
{},
|
|
@@ -42,7 +46,7 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
|
|
|
42
46
|
},
|
|
43
47
|
config?.web
|
|
44
48
|
);
|
|
45
|
-
const options = {
|
|
49
|
+
const options: TemplateUIOptions = {
|
|
46
50
|
darkMode,
|
|
47
51
|
url_prefix,
|
|
48
52
|
basename,
|
|
@@ -50,6 +54,7 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
|
|
|
50
54
|
primaryColor,
|
|
51
55
|
version,
|
|
52
56
|
logoURI,
|
|
57
|
+
flags,
|
|
53
58
|
login,
|
|
54
59
|
pkgManagers,
|
|
55
60
|
title,
|
package/src/web-middleware.ts
CHANGED
|
@@ -7,7 +7,7 @@ export default (config, auth, storage) => {
|
|
|
7
7
|
// eslint-disable-next-line new-cap
|
|
8
8
|
const app = express.Router();
|
|
9
9
|
// load application
|
|
10
|
-
app.use('/', renderWebMiddleware(config, auth
|
|
10
|
+
app.use('/', renderWebMiddleware(config, auth));
|
|
11
11
|
// web endpoints, search, packages, etc
|
|
12
12
|
app.use('/-/verdaccio/', webAPI(config, auth, storage));
|
|
13
13
|
return app;
|
package/test/api.readme.test.ts
CHANGED
|
@@ -3,7 +3,7 @@ import supertest from 'supertest';
|
|
|
3
3
|
|
|
4
4
|
import { HEADERS, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/core';
|
|
5
5
|
import { setup } from '@verdaccio/logger';
|
|
6
|
-
import {
|
|
6
|
+
import { publishVersion } from '@verdaccio/test-helper';
|
|
7
7
|
|
|
8
8
|
import { NOT_README_FOUND } from '../src/api/readme';
|
|
9
9
|
import { initializeServer } from './helper';
|
|
@@ -13,30 +13,6 @@ setup([]);
|
|
|
13
13
|
const mockManifest = jest.fn();
|
|
14
14
|
jest.mock('@verdaccio/ui-theme', () => mockManifest());
|
|
15
15
|
|
|
16
|
-
jest.mock('@verdaccio/store', () => ({
|
|
17
|
-
Storage: class {
|
|
18
|
-
public init() {
|
|
19
|
-
return Promise.resolve();
|
|
20
|
-
}
|
|
21
|
-
public getPackage({ name, callback }: IGetPackageOptions) {
|
|
22
|
-
callback(null, {
|
|
23
|
-
name,
|
|
24
|
-
['dist-tags']: {
|
|
25
|
-
latest: '1.0.0',
|
|
26
|
-
},
|
|
27
|
-
versions: {
|
|
28
|
-
['1.0.0']: {
|
|
29
|
-
name,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
SearchInstance: {
|
|
36
|
-
configureStorage: () => {},
|
|
37
|
-
},
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
16
|
describe('readme api', () => {
|
|
41
17
|
beforeAll(() => {
|
|
42
18
|
mockManifest.mockReturnValue(() => ({
|
|
@@ -54,7 +30,20 @@ describe('readme api', () => {
|
|
|
54
30
|
});
|
|
55
31
|
|
|
56
32
|
test('should fetch readme scoped package', async () => {
|
|
57
|
-
const
|
|
33
|
+
const app = await initializeServer('default-test.yaml');
|
|
34
|
+
await publishVersion(app, '@scope/pk1-test', '1.0.0', { readme: 'my readme scoped' });
|
|
35
|
+
const response = await supertest(app)
|
|
36
|
+
.get('/-/verdaccio/data/package/readme/@scope/pk1-test')
|
|
37
|
+
.set('Accept', HEADERS.TEXT_PLAIN)
|
|
38
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_PLAIN_UTF8)
|
|
39
|
+
.expect(HTTP_STATUS.OK);
|
|
40
|
+
expect(response.text).toMatch('my readme scoped');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('should fetch readme scoped package with not found message', async () => {
|
|
44
|
+
const app = await initializeServer('default-test.yaml');
|
|
45
|
+
await publishVersion(app, '@scope/pk1-test', '1.0.0', { readme: null });
|
|
46
|
+
const response = await supertest(app)
|
|
58
47
|
.get('/-/verdaccio/data/package/readme/@scope/pk1-test')
|
|
59
48
|
.set('Accept', HEADERS.TEXT_PLAIN)
|
|
60
49
|
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_PLAIN_UTF8)
|
|
@@ -63,7 +52,20 @@ describe('readme api', () => {
|
|
|
63
52
|
});
|
|
64
53
|
|
|
65
54
|
test('should fetch readme a package', async () => {
|
|
66
|
-
const
|
|
55
|
+
const app = await initializeServer('default-test.yaml');
|
|
56
|
+
await publishVersion(app, 'pk1-test', '1.0.0', { readme: 'my readme' });
|
|
57
|
+
const response = await supertest(app)
|
|
58
|
+
.get('/-/verdaccio/data/package/readme/pk1-test')
|
|
59
|
+
.set('Accept', HEADERS.TEXT_PLAIN)
|
|
60
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_PLAIN_UTF8)
|
|
61
|
+
.expect(HTTP_STATUS.OK);
|
|
62
|
+
expect(response.text).toMatch('my readme');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('should fetch readme a package with not found message', async () => {
|
|
66
|
+
const app = await initializeServer('default-test.yaml');
|
|
67
|
+
await publishVersion(app, 'pk1-test', '1.0.0', { readme: null });
|
|
68
|
+
const response = await supertest(app)
|
|
67
69
|
.get('/-/verdaccio/data/package/readme/pk1-test')
|
|
68
70
|
.set('Accept', HEADERS.TEXT_PLAIN)
|
|
69
71
|
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_PLAIN_UTF8)
|
package/test/api.search.test.ts
CHANGED
|
@@ -3,44 +3,15 @@ import supertest from 'supertest';
|
|
|
3
3
|
|
|
4
4
|
import { HEADERS, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/core';
|
|
5
5
|
import { setup } from '@verdaccio/logger';
|
|
6
|
-
import {
|
|
6
|
+
import { publishVersion } from '@verdaccio/test-helper';
|
|
7
7
|
|
|
8
8
|
import { initializeServer } from './helper';
|
|
9
9
|
|
|
10
10
|
setup([]);
|
|
11
11
|
|
|
12
12
|
const mockManifest = jest.fn();
|
|
13
|
-
const mockQuery = jest.fn(() => [
|
|
14
|
-
{ ref: 'pkg1', score: 1 },
|
|
15
|
-
{ ref: 'pk2', score: 0.9 },
|
|
16
|
-
]);
|
|
17
13
|
jest.mock('@verdaccio/ui-theme', () => mockManifest());
|
|
18
14
|
|
|
19
|
-
jest.mock('@verdaccio/store', () => ({
|
|
20
|
-
Storage: class {
|
|
21
|
-
public init() {
|
|
22
|
-
return Promise.resolve();
|
|
23
|
-
}
|
|
24
|
-
public getPackage({ name, callback }: IGetPackageOptions) {
|
|
25
|
-
callback(null, {
|
|
26
|
-
name,
|
|
27
|
-
['dist-tags']: {
|
|
28
|
-
latest: '1.0.0',
|
|
29
|
-
},
|
|
30
|
-
versions: {
|
|
31
|
-
['1.0.0']: {
|
|
32
|
-
name,
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
SearchInstance: {
|
|
39
|
-
configureStorage: () => {},
|
|
40
|
-
query: () => mockQuery(),
|
|
41
|
-
},
|
|
42
|
-
}));
|
|
43
|
-
|
|
44
15
|
describe('test web server', () => {
|
|
45
16
|
beforeAll(() => {
|
|
46
17
|
mockManifest.mockReturnValue(() => ({
|
|
@@ -53,21 +24,24 @@ describe('test web server', () => {
|
|
|
53
24
|
});
|
|
54
25
|
|
|
55
26
|
afterEach(() => {
|
|
27
|
+
Date.now = jest.fn(() => new Date(Date.UTC(2017, 1, 14)).valueOf());
|
|
56
28
|
jest.clearAllMocks();
|
|
57
29
|
mockManifest.mockClear();
|
|
58
30
|
});
|
|
59
31
|
|
|
60
|
-
test('should
|
|
61
|
-
const
|
|
62
|
-
|
|
32
|
+
test('should find results to search api', async () => {
|
|
33
|
+
const app = await initializeServer('default-test.yaml');
|
|
34
|
+
await publishVersion(app, 'foo', '1.0.0');
|
|
35
|
+
const response = await supertest(app)
|
|
36
|
+
.get('/-/verdaccio/data/search/foo')
|
|
63
37
|
.set('Accept', HEADERS.JSON_CHARSET)
|
|
64
38
|
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
65
39
|
.expect(HTTP_STATUS.OK);
|
|
66
|
-
expect(response.body).toHaveLength(
|
|
40
|
+
expect(response.body).toHaveLength(1);
|
|
41
|
+
// FUTURE: we can improve here matching the right outcome
|
|
67
42
|
});
|
|
68
43
|
|
|
69
|
-
test('should
|
|
70
|
-
mockQuery.mockReturnValue([]);
|
|
44
|
+
test('should found no results to search', async () => {
|
|
71
45
|
const response = await supertest(await initializeServer('default-test.yaml'))
|
|
72
46
|
.get('/-/verdaccio/data/search/notFound')
|
|
73
47
|
.set('Accept', HEADERS.JSON_CHARSET)
|
|
@@ -76,19 +50,18 @@ describe('test web server', () => {
|
|
|
76
50
|
expect(response.body).toHaveLength(0);
|
|
77
51
|
});
|
|
78
52
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return [
|
|
82
|
-
{ ref: 'aa', score: 1 },
|
|
83
|
-
{ ref: 'bb', score: 0.8 },
|
|
84
|
-
{ ref: 'cc', score: 0.6 },
|
|
85
|
-
];
|
|
86
|
-
});
|
|
53
|
+
// TODO: need a way to make this fail
|
|
54
|
+
test.skip('should fail search api', async () => {
|
|
87
55
|
const response = await supertest(await initializeServer('default-test.yaml'))
|
|
88
|
-
.get('/-/verdaccio/data/search/
|
|
56
|
+
.get('/-/verdaccio/data/search/thisWillFail')
|
|
89
57
|
.set('Accept', HEADERS.JSON_CHARSET)
|
|
90
58
|
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
91
59
|
.expect(HTTP_STATUS.OK);
|
|
92
60
|
expect(response.body).toHaveLength(3);
|
|
93
61
|
});
|
|
62
|
+
|
|
63
|
+
test.todo('search abort request');
|
|
64
|
+
// maybe these could be done in storage package to avoid have specifics on this level
|
|
65
|
+
test.todo('search allow request permissions');
|
|
66
|
+
test.todo('search query params, pagination etc');
|
|
94
67
|
});
|
package/test/api.sidebar.test.ts
CHANGED
|
@@ -3,9 +3,8 @@ import supertest from 'supertest';
|
|
|
3
3
|
|
|
4
4
|
import { HEADERS, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/core';
|
|
5
5
|
import { setup } from '@verdaccio/logger';
|
|
6
|
-
import {
|
|
6
|
+
import { publishVersion } from '@verdaccio/test-helper';
|
|
7
7
|
|
|
8
|
-
import { NOT_README_FOUND } from '../src/api/readme';
|
|
9
8
|
import { initializeServer } from './helper';
|
|
10
9
|
|
|
11
10
|
setup([]);
|
|
@@ -13,36 +12,15 @@ setup([]);
|
|
|
13
12
|
const mockManifest = jest.fn();
|
|
14
13
|
jest.mock('@verdaccio/ui-theme', () => mockManifest());
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
Storage: class {
|
|
18
|
-
public init() {
|
|
19
|
-
return Promise.resolve();
|
|
20
|
-
}
|
|
21
|
-
public getPackage({ name, callback }: IGetPackageOptions) {
|
|
22
|
-
callback(null, {
|
|
23
|
-
name,
|
|
24
|
-
['dist-tags']: {
|
|
25
|
-
latest: '1.0.0',
|
|
26
|
-
},
|
|
27
|
-
versions: {
|
|
28
|
-
['1.0.0']: {
|
|
29
|
-
name,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
SearchInstance: {
|
|
36
|
-
configureStorage: () => {},
|
|
37
|
-
},
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
|
-
describe.skip('sidebar api', () => {
|
|
15
|
+
describe('sidebar api', () => {
|
|
41
16
|
beforeAll(() => {
|
|
42
|
-
mockManifest.mockReturnValue({
|
|
17
|
+
mockManifest.mockReturnValue(() => ({
|
|
43
18
|
staticPath: path.join(__dirname, 'static'),
|
|
19
|
+
manifestFiles: {
|
|
20
|
+
js: ['runtime.js', 'vendors.js', 'main.js'],
|
|
21
|
+
},
|
|
44
22
|
manifest: require('./partials/manifest/manifest.json'),
|
|
45
|
-
});
|
|
23
|
+
}));
|
|
46
24
|
});
|
|
47
25
|
|
|
48
26
|
afterEach(() => {
|
|
@@ -50,15 +28,23 @@ describe.skip('sidebar api', () => {
|
|
|
50
28
|
mockManifest.mockClear();
|
|
51
29
|
});
|
|
52
30
|
|
|
53
|
-
test('should display sidebar info', async () => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const response = await supertest(await initializeServer('default-test.yaml'))
|
|
31
|
+
test('should display sidebar info scoped package', async () => {
|
|
32
|
+
const app = await initializeServer('default-test.yaml');
|
|
33
|
+
await publishVersion(app, '@scope/pk1-test', '1.0.0', { readme: 'my readme scoped' });
|
|
34
|
+
const response = await supertest(app)
|
|
58
35
|
.get('/-/verdaccio/data/sidebar/@scope/pk1-test')
|
|
59
|
-
.set('Accept', HEADERS.TEXT_PLAIN)
|
|
60
36
|
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
61
37
|
.expect(HTTP_STATUS.OK);
|
|
62
|
-
expect(response.text).toMatch(
|
|
38
|
+
expect(response.text).toMatch('@scope/pk1-test');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('should display sidebar info package', async () => {
|
|
42
|
+
const app = await initializeServer('default-test.yaml');
|
|
43
|
+
await publishVersion(app, 'pk2-test', '1.0.0', { readme: 'my readme scoped' });
|
|
44
|
+
const response = await supertest(app)
|
|
45
|
+
.get('/-/verdaccio/data/sidebar/pk2-test')
|
|
46
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
47
|
+
.expect(HTTP_STATUS.OK);
|
|
48
|
+
expect(response.text).toMatch('pk2-test');
|
|
63
49
|
});
|
|
64
50
|
});
|
package/test/api.user.test.ts
CHANGED
|
@@ -64,7 +64,7 @@ describe('test web server', () => {
|
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
-
test('log in should be disabled', async () => {
|
|
67
|
+
test.skip('log in should be disabled', async () => {
|
|
68
68
|
return supertest(await initializeServer('login-disabled.yaml'))
|
|
69
69
|
.post('/-/verdaccio/sec/login')
|
|
70
70
|
.send(
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
store:
|
|
2
|
-
memory:
|
|
3
|
-
limit: 1000
|
|
4
|
-
|
|
5
1
|
auth:
|
|
6
2
|
auth-memory:
|
|
7
3
|
users:
|
|
@@ -17,7 +13,7 @@ publish:
|
|
|
17
13
|
|
|
18
14
|
uplinks:
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
log: { type: stdout, format: pretty, level: trace }
|
|
21
17
|
|
|
22
18
|
packages:
|
|
23
19
|
'@*/*':
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
store:
|
|
2
|
-
memory:
|
|
3
|
-
limit: 1000
|
|
4
|
-
|
|
5
1
|
auth:
|
|
6
2
|
auth-memory:
|
|
7
3
|
users:
|
|
@@ -18,7 +14,7 @@ publish:
|
|
|
18
14
|
|
|
19
15
|
uplinks:
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
log: { type: stdout, format: pretty, level: trace }
|
|
22
18
|
|
|
23
19
|
packages:
|
|
24
20
|
'@*/*':
|
package/test/helper.ts
CHANGED
|
@@ -1,38 +1,22 @@
|
|
|
1
|
-
import bodyParser from 'body-parser';
|
|
2
|
-
import express from 'express';
|
|
3
1
|
import { Application } from 'express';
|
|
4
2
|
import path from 'path';
|
|
5
3
|
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
4
|
+
import apiMiddleware from '@verdaccio/api';
|
|
5
|
+
import { parseConfigFile } from '@verdaccio/config';
|
|
8
6
|
import { setup } from '@verdaccio/logger';
|
|
9
|
-
import { errorReportingMiddleware, final, handleError } from '@verdaccio/middleware';
|
|
10
7
|
import { Storage } from '@verdaccio/store';
|
|
8
|
+
import { initializeServer as initializeServerHelper } from '@verdaccio/test-helper';
|
|
11
9
|
|
|
12
10
|
import routes from '../src';
|
|
13
11
|
|
|
14
12
|
setup([]);
|
|
15
13
|
|
|
16
|
-
const getConf = (configName: string) => {
|
|
14
|
+
export const getConf = (configName: string) => {
|
|
17
15
|
const configPath = path.join(__dirname, 'config', configName);
|
|
18
16
|
return parseConfigFile(configPath);
|
|
19
17
|
};
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
config.checkSecretKey('12345');
|
|
25
|
-
const storage = new Storage(config);
|
|
26
|
-
await storage.init(config, []);
|
|
27
|
-
const auth: IAuth = new Auth(config);
|
|
28
|
-
// for parsing the body (login api)
|
|
29
|
-
app.use(bodyParser.json({ strict: false, limit: '10mb' }));
|
|
30
|
-
// @ts-ignore
|
|
31
|
-
app.use(errorReportingMiddleware);
|
|
32
|
-
app.use(routes(config, auth, storage));
|
|
33
|
-
// @ts-ignore
|
|
34
|
-
app.use(handleError);
|
|
35
|
-
// @ts-ignore
|
|
36
|
-
app.use(final);
|
|
37
|
-
return app;
|
|
19
|
+
// @deprecated
|
|
20
|
+
export async function initializeServer(configName): Promise<Application> {
|
|
21
|
+
return initializeServerHelper(getConf(configName), [apiMiddleware, routes], Storage);
|
|
38
22
|
}
|