@verdaccio/core 6.0.0-6-next.3 → 6.0.0-6-next.6
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 +92 -0
- package/build/constants.d.ts +15 -0
- package/build/constants.js +20 -2
- package/build/constants.js.map +1 -1
- package/build/error-utils.d.ts +2 -0
- package/build/error-utils.js +2 -0
- package/build/error-utils.js.map +1 -1
- package/build/file-utils.d.ts +13 -0
- package/build/file-utils.js +37 -0
- package/build/file-utils.js.map +1 -1
- package/build/index.d.ts +7 -6
- package/build/index.js +18 -17
- package/build/index.js.map +1 -1
- package/build/path-utils.js.map +1 -1
- package/build/pkg-utils.d.ts +11 -3
- package/build/pkg-utils.js +18 -0
- package/build/pkg-utils.js.map +1 -1
- package/build/plugin-utils.js.map +1 -1
- package/build/schemes/publish-manifest.d.ts +7 -0
- package/build/schemes/publish-manifest.js +49 -0
- package/build/schemes/publish-manifest.js.map +1 -0
- package/build/search-utils.d.ts +8 -4
- package/build/search-utils.js +2 -0
- package/build/search-utils.js.map +1 -1
- package/build/stream-utils.d.ts +1 -1
- package/build/stream-utils.js.map +1 -1
- package/build/validation-utils.d.ts +5 -3
- package/build/validation-utils.js +25 -14
- package/build/validation-utils.js.map +1 -1
- package/build/warning-utils.d.ts +0 -3
- package/build/warning-utils.js +2 -8
- package/build/warning-utils.js.map +1 -1
- package/package.json +61 -57
- package/src/constants.ts +18 -0
- package/src/error-utils.ts +3 -0
- package/src/file-utils.ts +26 -0
- package/src/index.ts +8 -6
- package/src/pkg-utils.ts +20 -3
- package/src/plugin-utils.ts +1 -0
- package/src/schemes/publish-manifest.ts +38 -0
- package/src/search-utils.ts +15 -4
- package/src/stream-utils.ts +1 -1
- package/src/validation-utils.ts +19 -13
- package/src/warning-utils.ts +2 -18
- package/test/errors.spec.ts +7 -7
- package/test/merge.dist.tags.spec.ts +1 -1
- package/test/mystreams.spec.ts +2 -1
- package/test/pkg-utils.spec.ts +42 -0
- package/test/validation-utilts.spec.ts +96 -2
package/src/plugin-utils.ts
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Ajv, { JSONSchemaType } from 'ajv';
|
|
2
|
+
|
|
3
|
+
const ajv = new Ajv();
|
|
4
|
+
|
|
5
|
+
// FIXME: this could extend from @verdaccio/types but we need
|
|
6
|
+
// schemas from @verdaccio/types to be able to validate them
|
|
7
|
+
interface Manifest {
|
|
8
|
+
name: string;
|
|
9
|
+
versions: object;
|
|
10
|
+
_attachments: object;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const schema: JSONSchemaType<Manifest> = {
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: {
|
|
16
|
+
name: { type: 'string' },
|
|
17
|
+
versions: { type: 'object', maxProperties: 1 },
|
|
18
|
+
_attachments: { type: 'object', maxProperties: 1 },
|
|
19
|
+
},
|
|
20
|
+
required: ['name', 'versions', '_attachments'],
|
|
21
|
+
additionalProperties: true,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// validate is a type guard for MyData - type is inferred from schema type
|
|
25
|
+
const validate = ajv.compile(schema);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Validate if a manifest has the correct structure when a new package
|
|
29
|
+
* is being created. The properties name, versions and _attachments must contain 1 element.
|
|
30
|
+
* @param data a manifest object
|
|
31
|
+
* @returns boolean
|
|
32
|
+
*/
|
|
33
|
+
export function validatePublishSingleVersion(manifest: any) {
|
|
34
|
+
if (!manifest) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return validate(manifest);
|
|
38
|
+
}
|
package/src/search-utils.ts
CHANGED
|
@@ -16,10 +16,19 @@ export type SearchItemPkg = {
|
|
|
16
16
|
time?: number | Date;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
type PrivatePackage = {
|
|
20
|
+
// note: prefixed to avoid external conflicts
|
|
21
|
+
|
|
22
|
+
// the package is published as private
|
|
23
|
+
verdaccioPrivate?: boolean;
|
|
24
|
+
// if the package is not private but is cached
|
|
25
|
+
verdaccioPkgCached?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export interface SearchItem extends UnStable, PrivatePackage {
|
|
20
29
|
package: SearchItemPkg;
|
|
21
30
|
score: Score;
|
|
22
|
-
}
|
|
31
|
+
}
|
|
23
32
|
|
|
24
33
|
export type Score = {
|
|
25
34
|
final: number;
|
|
@@ -32,11 +41,13 @@ export type SearchResults = {
|
|
|
32
41
|
time: string;
|
|
33
42
|
};
|
|
34
43
|
|
|
44
|
+
// @deprecated use @verdaccio/types
|
|
35
45
|
type PublisherMaintainer = {
|
|
36
46
|
username: string;
|
|
37
47
|
email: string;
|
|
38
48
|
};
|
|
39
49
|
|
|
50
|
+
// @deprecated use @verdaccio/types
|
|
40
51
|
export type SearchPackageBody = {
|
|
41
52
|
name: string;
|
|
42
53
|
scope: string;
|
|
@@ -55,11 +66,11 @@ export type SearchPackageBody = {
|
|
|
55
66
|
maintainers?: PublisherMaintainer[];
|
|
56
67
|
};
|
|
57
68
|
|
|
58
|
-
export
|
|
69
|
+
export interface SearchPackageItem extends UnStable, PrivatePackage {
|
|
59
70
|
package: SearchPackageBody;
|
|
60
71
|
score: Score;
|
|
61
72
|
searchScore?: number;
|
|
62
|
-
}
|
|
73
|
+
}
|
|
63
74
|
|
|
64
75
|
export const UNSCOPED = 'unscoped';
|
|
65
76
|
|
package/src/stream-utils.ts
CHANGED
package/src/validation-utils.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import assert from 'assert';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import { Manifest } from '@verdaccio/types';
|
|
4
|
+
|
|
3
5
|
import { DIST_TAGS } from './constants';
|
|
4
6
|
|
|
7
|
+
export { validatePublishSingleVersion } from './schemes/publish-manifest';
|
|
8
|
+
|
|
5
9
|
export function isPackageNameScoped(name: string): boolean {
|
|
6
10
|
return name.startsWith('@');
|
|
7
11
|
}
|
|
@@ -60,27 +64,29 @@ export function validatePackage(name: string): boolean {
|
|
|
60
64
|
/**
|
|
61
65
|
* Validate the package metadata, add additional properties whether are missing within
|
|
62
66
|
* the metadata properties.
|
|
63
|
-
* @param {*}
|
|
67
|
+
* @param {*} manifest
|
|
64
68
|
* @param {*} name
|
|
65
69
|
* @return {Object} the object with additional properties as dist-tags ad versions
|
|
70
|
+
* FUTURE: rename to normalizeMetadata
|
|
66
71
|
*/
|
|
67
|
-
export function
|
|
68
|
-
assert(
|
|
69
|
-
|
|
72
|
+
export function normalizeMetadata(manifest: Manifest, name: string): Manifest {
|
|
73
|
+
assert.strictEqual(manifest.name, name);
|
|
74
|
+
const _manifest = { ...manifest };
|
|
70
75
|
|
|
71
|
-
if (!isObject(
|
|
72
|
-
|
|
76
|
+
if (!isObject(manifest[DIST_TAGS])) {
|
|
77
|
+
_manifest[DIST_TAGS] = {};
|
|
73
78
|
}
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
// This may not be nee dit
|
|
81
|
+
if (!isObject(manifest['versions'])) {
|
|
82
|
+
_manifest['versions'] = {};
|
|
77
83
|
}
|
|
78
84
|
|
|
79
|
-
if (!isObject(
|
|
80
|
-
|
|
85
|
+
if (!isObject(manifest['time'])) {
|
|
86
|
+
_manifest['time'] = {};
|
|
81
87
|
}
|
|
82
88
|
|
|
83
|
-
return
|
|
89
|
+
return _manifest;
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
/**
|
|
@@ -89,7 +95,7 @@ export function validateMetadata(object: Package, name: string): Package {
|
|
|
89
95
|
* @return {Boolean}
|
|
90
96
|
*/
|
|
91
97
|
export function isObject(obj: any): boolean {
|
|
92
|
-
if (obj === null || typeof obj === 'undefined') {
|
|
98
|
+
if (obj === null || typeof obj === 'undefined' || typeof obj === 'string') {
|
|
93
99
|
return false;
|
|
94
100
|
}
|
|
95
101
|
|
package/src/warning-utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import warning from '
|
|
1
|
+
import warning from 'process-warning';
|
|
2
2
|
|
|
3
3
|
const warningInstance = warning();
|
|
4
4
|
const verdaccioWarning = 'VerdaccioWarning';
|
|
@@ -6,11 +6,9 @@ const verdaccioDeprecation = 'VerdaccioDeprecation';
|
|
|
6
6
|
|
|
7
7
|
export enum Codes {
|
|
8
8
|
VERWAR001 = 'VERWAR001',
|
|
9
|
-
VERWAR002 = 'VERWAR002',
|
|
10
9
|
VERWAR003 = 'VERWAR003',
|
|
11
10
|
VERWAR004 = 'VERWAR004',
|
|
12
|
-
|
|
13
|
-
VERDEP002 = 'VERDEP002',
|
|
11
|
+
// deprecation warnings
|
|
14
12
|
VERDEP003 = 'VERDEP003',
|
|
15
13
|
}
|
|
16
14
|
|
|
@@ -20,8 +18,6 @@ warningInstance.create(
|
|
|
20
18
|
`Verdaccio doesn't need superuser privileges. don't run it under root`
|
|
21
19
|
);
|
|
22
20
|
|
|
23
|
-
warningInstance.create(verdaccioWarning, Codes.VERWAR002, 'logger is not defined');
|
|
24
|
-
|
|
25
21
|
warningInstance.create(
|
|
26
22
|
verdaccioWarning,
|
|
27
23
|
Codes.VERWAR003,
|
|
@@ -36,18 +32,6 @@ host:port (e.g. "localhost:4873") or full url '(e.g. "http://localhost:4873/")
|
|
|
36
32
|
https://verdaccio.org/docs/en/configuration#listen-port`
|
|
37
33
|
);
|
|
38
34
|
|
|
39
|
-
warningInstance.create(
|
|
40
|
-
verdaccioDeprecation,
|
|
41
|
-
Codes.VERDEP001,
|
|
42
|
-
'config.logs is deprecated, rename configuration to "config.log" in singular'
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
warningInstance.create(
|
|
46
|
-
verdaccioDeprecation,
|
|
47
|
-
Codes.VERDEP002,
|
|
48
|
-
'deprecate: multiple logger configuration is deprecated, please check the migration guide.'
|
|
49
|
-
);
|
|
50
|
-
|
|
51
35
|
warningInstance.create(
|
|
52
36
|
verdaccioDeprecation,
|
|
53
37
|
Codes.VERDEP003,
|
package/test/errors.spec.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import { HTTP_STATUS } from '../src/constants';
|
|
3
2
|
|
|
3
|
+
import { HTTP_STATUS } from '../src/constants';
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
API_ERROR,
|
|
6
6
|
VerdaccioError,
|
|
7
|
-
getConflict,
|
|
8
7
|
getBadData,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
getUnauthorized,
|
|
8
|
+
getCode,
|
|
9
|
+
getConflict,
|
|
12
10
|
getForbidden,
|
|
11
|
+
getInternalError,
|
|
12
|
+
getNotFound,
|
|
13
13
|
getServiceUnavailable,
|
|
14
|
-
|
|
14
|
+
getUnauthorized,
|
|
15
15
|
} from '../src/error-utils';
|
|
16
16
|
|
|
17
17
|
describe('testing errors', () => {
|
package/test/mystreams.spec.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Stream } from 'stream';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import { ReadTarball, UploadTarball, readableToString } from '../src/stream-utils';
|
|
3
4
|
|
|
4
5
|
describe('mystreams', () => {
|
|
5
6
|
test('should delay events on ReadTarball abort', (cb) => {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DIST_TAGS, pkgUtils } from '../src';
|
|
2
|
+
|
|
3
|
+
describe('pkg-utils', () => {
|
|
4
|
+
test('extractTarballName', () => {
|
|
5
|
+
expect(pkgUtils.extractTarballName('https://registry.npmjs.org/test/-/test-0.0.2.tgz')).toBe(
|
|
6
|
+
'test-0.0.2.tgz'
|
|
7
|
+
);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('extractTarballName with no tarball should not fails', () => {
|
|
11
|
+
expect(pkgUtils.extractTarballName('https://registry.npmjs.org/')).toBe('');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('extractTarballName fails', () => {
|
|
15
|
+
expect(() =>
|
|
16
|
+
pkgUtils.extractTarballName('xxxxregistry.npmjs.org/test/-/test-0.0.2.tgz')
|
|
17
|
+
).toThrow();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('getLatest fails if no versions', () => {
|
|
21
|
+
expect(() =>
|
|
22
|
+
// @ts-expect-error
|
|
23
|
+
pkgUtils.getLatest({
|
|
24
|
+
versions: {},
|
|
25
|
+
})
|
|
26
|
+
).toThrow('cannot get lastest version of none');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('getLatest get latest', () => {
|
|
30
|
+
expect(
|
|
31
|
+
pkgUtils.getLatest({
|
|
32
|
+
versions: {
|
|
33
|
+
// @ts-expect-error
|
|
34
|
+
'1.0.0': {},
|
|
35
|
+
},
|
|
36
|
+
[DIST_TAGS]: {
|
|
37
|
+
latest: '1.0.0',
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
).toBe('1.0.0');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DIST_TAGS } from '../src/constants';
|
|
2
|
+
import { validatePublishSingleVersion } from '../src/schemes/publish-manifest';
|
|
3
|
+
import {
|
|
4
|
+
isObject,
|
|
5
|
+
normalizeMetadata,
|
|
6
|
+
validateName,
|
|
7
|
+
validatePackage,
|
|
8
|
+
} from '../src/validation-utils';
|
|
2
9
|
|
|
3
10
|
describe('validatePackage', () => {
|
|
4
11
|
test('should validate package names', () => {
|
|
@@ -19,13 +26,41 @@ describe('validatePackage', () => {
|
|
|
19
26
|
describe('isObject', () => {
|
|
20
27
|
test('isObject metadata', () => {
|
|
21
28
|
expect(isObject({ foo: 'bar' })).toBeTruthy();
|
|
22
|
-
expect(isObject('foo')).toBeTruthy();
|
|
29
|
+
// expect(isObject('foo')).toBeTruthy();
|
|
23
30
|
expect(isObject(['foo'])).toBeFalsy();
|
|
24
31
|
expect(isObject(null)).toBeFalsy();
|
|
25
32
|
expect(isObject(undefined)).toBeFalsy();
|
|
26
33
|
});
|
|
27
34
|
});
|
|
28
35
|
|
|
36
|
+
describe('normalizeMetadata', () => {
|
|
37
|
+
test('should fills an empty metadata object', () => {
|
|
38
|
+
// intended to fail with flow, do not remove
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
expect(Object.keys(normalizeMetadata({}))).toContain(DIST_TAGS);
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
expect(Object.keys(normalizeMetadata({}))).toContain('versions');
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
expect(Object.keys(normalizeMetadata({}))).toContain('time');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test.skip('should fails the assertions is not an object', () => {
|
|
48
|
+
expect(function () {
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
normalizeMetadata('');
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
}).toThrow(expect.hasAssertions());
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('should fails the assertions is name does not match', () => {
|
|
56
|
+
expect(function () {
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
normalizeMetadata({}, 'no-name');
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
}).toThrow(expect.hasAssertions());
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
29
64
|
describe('validateName', () => {
|
|
30
65
|
test('should fails with no string', () => {
|
|
31
66
|
// intended to fail with Typescript, do not remove
|
|
@@ -72,3 +107,62 @@ describe('validateName', () => {
|
|
|
72
107
|
expect(validateName('pk:g')).toBeFalsy();
|
|
73
108
|
});
|
|
74
109
|
});
|
|
110
|
+
|
|
111
|
+
describe('validatePublishSingleVersion', () => {
|
|
112
|
+
test('should be valid', () => {
|
|
113
|
+
expect(
|
|
114
|
+
validatePublishSingleVersion({
|
|
115
|
+
name: 'foo-pkg',
|
|
116
|
+
_attachments: { '2': {} },
|
|
117
|
+
versions: { '1': {} },
|
|
118
|
+
})
|
|
119
|
+
).toBeTruthy();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('should be invalid if name is missing', () => {
|
|
123
|
+
expect(
|
|
124
|
+
validatePublishSingleVersion({
|
|
125
|
+
_attachments: { '2': {} },
|
|
126
|
+
versions: { '1': {} },
|
|
127
|
+
})
|
|
128
|
+
).toBeFalsy();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('should be invalid if _attachments is missing', () => {
|
|
132
|
+
expect(
|
|
133
|
+
validatePublishSingleVersion({
|
|
134
|
+
name: 'foo-pkg',
|
|
135
|
+
versions: { '1': {} },
|
|
136
|
+
})
|
|
137
|
+
).toBeFalsy();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('should be invalid if versions is missing', () => {
|
|
141
|
+
expect(
|
|
142
|
+
validatePublishSingleVersion({
|
|
143
|
+
name: 'foo-pkg',
|
|
144
|
+
_attachments: { '1': {} },
|
|
145
|
+
})
|
|
146
|
+
).toBeFalsy();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test('should be invalid if versions is more than 1', () => {
|
|
150
|
+
expect(
|
|
151
|
+
validatePublishSingleVersion({
|
|
152
|
+
name: 'foo-pkg',
|
|
153
|
+
versions: { '1': {}, '2': {} },
|
|
154
|
+
_attachments: { '1': {} },
|
|
155
|
+
})
|
|
156
|
+
).toBeFalsy();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('should be invalid if _attachments is more than 1', () => {
|
|
160
|
+
expect(
|
|
161
|
+
validatePublishSingleVersion({
|
|
162
|
+
name: 'foo-pkg',
|
|
163
|
+
_attachments: { '1': {}, '2': {} },
|
|
164
|
+
versions: { '1': {} },
|
|
165
|
+
})
|
|
166
|
+
).toBeFalsy();
|
|
167
|
+
});
|
|
168
|
+
});
|