@eik/core 2.1.45 → 2.1.47
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 +14 -0
- package/lib/classes/http-incoming.js +4 -0
- package/lib/classes/http-outgoing.js +4 -0
- package/lib/classes/package.js +8 -0
- package/lib/classes/versions.js +16 -2
- package/lib/handlers/alias.delete.js +13 -4
- package/lib/handlers/alias.get-v2.js +22 -10
- package/lib/handlers/alias.get.js +10 -1
- package/lib/handlers/alias.post.js +19 -4
- package/lib/handlers/alias.put.js +19 -4
- package/lib/handlers/auth.post.js +7 -1
- package/lib/handlers/map.get.js +20 -10
- package/lib/handlers/map.put.js +38 -13
- package/lib/handlers/pkg.get.js +22 -10
- package/lib/handlers/pkg.log.js +21 -10
- package/lib/handlers/pkg.put.js +26 -4
- package/lib/handlers/versions.get.js +20 -10
- package/lib/multipart/form-file.js +3 -0
- package/lib/multipart/parser.js +65 -37
- package/lib/sinks/mem-entry.js +3 -0
- package/lib/sinks/test.js +40 -10
- package/lib/utils/healthcheck.js +16 -2
- package/lib/utils/utils.js +25 -0
- package/package.json +16 -20
- package/types/classes/alias.d.ts +4 -4
- package/types/classes/asset.d.ts +5 -5
- package/types/classes/author.d.ts +2 -2
- package/types/classes/http-incoming.d.ts +4 -4
- package/types/classes/http-outgoing.d.ts +7 -3
- package/types/classes/meta.d.ts +2 -2
- package/types/classes/package.d.ts +136 -11
- package/types/classes/versions.d.ts +14 -4
- package/types/handlers/alias.delete.d.ts +13 -6
- package/types/handlers/alias.get-v2.d.ts +16 -9
- package/types/handlers/alias.get.d.ts +15 -8
- package/types/handlers/alias.post.d.ts +24 -11
- package/types/handlers/alias.put.d.ts +24 -11
- package/types/handlers/auth.post.d.ts +15 -9
- package/types/handlers/map.get.d.ts +14 -9
- package/types/handlers/map.put.d.ts +32 -13
- package/types/handlers/pkg.get.d.ts +16 -9
- package/types/handlers/pkg.log.d.ts +15 -9
- package/types/handlers/pkg.put.d.ts +35 -15
- package/types/handlers/versions.get.d.ts +14 -9
- package/types/main.d.ts +2 -0
- package/types/multipart/form-field.d.ts +2 -2
- package/types/multipart/parser.d.ts +18 -6
- package/types/sinks/test.d.ts +26 -13
- package/types/utils/healthcheck.d.ts +6 -4
- package/types/utils/path-builders-fs.d.ts +27 -27
- package/types/utils/path-builders-uri.d.ts +16 -16
- package/types/utils/utils.d.ts +26 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [2.1.47](https://github.com/eik-lib/core/compare/v2.1.46...v2.1.47) (2026-05-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Bump dependencies ([#587](https://github.com/eik-lib/core/issues/587)) ([c81b101](https://github.com/eik-lib/core/commit/c81b10179c6e6fc8d4f4a2ee82b95f1c0e1533e7))
|
|
7
|
+
|
|
8
|
+
## [2.1.46](https://github.com/eik-lib/core/compare/v2.1.45...v2.1.46) (2026-05-22)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **deps:** update dependency @eik/sink-file-system to v2.0.32 ([#586](https://github.com/eik-lib/core/issues/586)) ([6e9ec23](https://github.com/eik-lib/core/commit/6e9ec2350596336e8931b2f340def7761deab81d))
|
|
14
|
+
|
|
1
15
|
## [2.1.45](https://github.com/eik-lib/core/compare/v2.1.44...v2.1.45) (2026-05-22)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* @class HttpIncoming
|
|
5
5
|
*/
|
|
6
6
|
const HttpIncoming = class HttpIncoming {
|
|
7
|
+
/**
|
|
8
|
+
* @param {any} [request]
|
|
9
|
+
* @param {{ version?: string, extras?: string, author?: object, alias?: string, type?: string, name?: string, org?: string }} [options]
|
|
10
|
+
*/
|
|
7
11
|
constructor(
|
|
8
12
|
request,
|
|
9
13
|
{
|
|
@@ -14,7 +14,9 @@ const HttpOutgoing = class HttpOutgoing {
|
|
|
14
14
|
this._statusCode = 200;
|
|
15
15
|
this._mimeType = "text/plain";
|
|
16
16
|
this._location = "";
|
|
17
|
+
/** @type {import("node:stream").Readable | undefined} */
|
|
17
18
|
this._stream = undefined;
|
|
19
|
+
/** @type {any} */
|
|
18
20
|
this._body = undefined;
|
|
19
21
|
this._etag = "";
|
|
20
22
|
}
|
|
@@ -63,6 +65,7 @@ const HttpOutgoing = class HttpOutgoing {
|
|
|
63
65
|
this._stream = value;
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
/** @returns {import("node:stream").Readable | undefined} */
|
|
66
69
|
get stream() {
|
|
67
70
|
return this._stream;
|
|
68
71
|
}
|
|
@@ -71,6 +74,7 @@ const HttpOutgoing = class HttpOutgoing {
|
|
|
71
74
|
this._body = value;
|
|
72
75
|
}
|
|
73
76
|
|
|
77
|
+
/** @returns {any} */
|
|
74
78
|
get body() {
|
|
75
79
|
return this._body;
|
|
76
80
|
}
|
package/lib/classes/package.js
CHANGED
|
@@ -17,7 +17,9 @@ const Package = class Package {
|
|
|
17
17
|
this._type = type;
|
|
18
18
|
this._name = name;
|
|
19
19
|
this._org = org;
|
|
20
|
+
/** @type {import("./asset.js").default[]} */
|
|
20
21
|
this._files = [];
|
|
22
|
+
/** @type {import("./meta.js").default[]} */
|
|
21
23
|
this._meta = [];
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -56,12 +58,18 @@ const Package = class Package {
|
|
|
56
58
|
return this._org;
|
|
57
59
|
}
|
|
58
60
|
|
|
61
|
+
/**
|
|
62
|
+
* @param {import("./asset.js").default} asset
|
|
63
|
+
*/
|
|
59
64
|
setAsset(asset) {
|
|
60
65
|
if (!(asset instanceof Asset))
|
|
61
66
|
throw new TypeError('Argument "asset" must be an instance of Asset');
|
|
62
67
|
this._files.push(asset);
|
|
63
68
|
}
|
|
64
69
|
|
|
70
|
+
/**
|
|
71
|
+
* @param {import("./meta.js").default} meta
|
|
72
|
+
*/
|
|
65
73
|
setMeta(meta) {
|
|
66
74
|
if (!(meta instanceof Meta))
|
|
67
75
|
throw new TypeError('Argument "meta" must be an instance of Meta');
|
package/lib/classes/versions.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import semver from "semver";
|
|
2
2
|
|
|
3
3
|
const Versions = class Versions {
|
|
4
|
+
/**
|
|
5
|
+
* @param {{ versions?: [any, any][], type?: string, name?: string, org?: string }} [options]
|
|
6
|
+
*/
|
|
4
7
|
constructor({ versions = [], type = "", name = "", org = "" } = {}) {
|
|
5
8
|
this._versions = new Map(versions);
|
|
6
9
|
this._type = type;
|
|
@@ -9,8 +12,9 @@ const Versions = class Versions {
|
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
get versions() {
|
|
12
|
-
return
|
|
13
|
-
|
|
15
|
+
return [...this._versions.entries()].toSorted(
|
|
16
|
+
(/** @type {[any, any]} */ a, /** @type {[any, any]} */ b) =>
|
|
17
|
+
a[0] > b[0] ? -1 : 1,
|
|
14
18
|
);
|
|
15
19
|
}
|
|
16
20
|
|
|
@@ -26,6 +30,10 @@ const Versions = class Versions {
|
|
|
26
30
|
return this._org;
|
|
27
31
|
}
|
|
28
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @param {string} version
|
|
35
|
+
* @param {string} integrity
|
|
36
|
+
*/
|
|
29
37
|
setVersion(version, integrity) {
|
|
30
38
|
const major = semver.major(version);
|
|
31
39
|
this._versions.set(major, {
|
|
@@ -34,10 +42,16 @@ const Versions = class Versions {
|
|
|
34
42
|
});
|
|
35
43
|
}
|
|
36
44
|
|
|
45
|
+
/**
|
|
46
|
+
* @param {number} major
|
|
47
|
+
*/
|
|
37
48
|
getVersion(major) {
|
|
38
49
|
return this._versions.get(major);
|
|
39
50
|
}
|
|
40
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @param {string} version
|
|
54
|
+
*/
|
|
41
55
|
check(version) {
|
|
42
56
|
const major = semver.major(version);
|
|
43
57
|
const previous = this.getVersion(major);
|
|
@@ -46,7 +46,7 @@ const AliasDel = class AliasDel {
|
|
|
46
46
|
|
|
47
47
|
async _exist(path = "") {
|
|
48
48
|
try {
|
|
49
|
-
await this._sink.exist(path);
|
|
49
|
+
if (this._sink) await this._sink.exist(path);
|
|
50
50
|
return true;
|
|
51
51
|
// eslint-disable-next-line no-unused-vars
|
|
52
52
|
} catch (error) {
|
|
@@ -54,6 +54,13 @@ const AliasDel = class AliasDel {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* @param {any} req
|
|
59
|
+
* @param {any} user
|
|
60
|
+
* @param {string} type
|
|
61
|
+
* @param {string} name
|
|
62
|
+
* @param {string} alias
|
|
63
|
+
*/
|
|
57
64
|
async handler(req, user, type, name, alias) {
|
|
58
65
|
const end = this._histogram.timer();
|
|
59
66
|
|
|
@@ -65,7 +72,9 @@ const AliasDel = class AliasDel {
|
|
|
65
72
|
validators.name(pName);
|
|
66
73
|
validators.type(type);
|
|
67
74
|
} catch (error) {
|
|
68
|
-
this._log.info(
|
|
75
|
+
this._log.info(
|
|
76
|
+
`alias:del - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
77
|
+
);
|
|
69
78
|
const e = new HttpError.NotFound();
|
|
70
79
|
end({ labels: { success: false, status: e.status } });
|
|
71
80
|
throw e;
|
|
@@ -103,7 +112,7 @@ const AliasDel = class AliasDel {
|
|
|
103
112
|
this._log.info(
|
|
104
113
|
`alias:del - Start deleting alias from sink - Pathname: ${path}`,
|
|
105
114
|
);
|
|
106
|
-
await this._sink.delete(path);
|
|
115
|
+
if (this._sink) await this._sink.delete(path);
|
|
107
116
|
} catch (error) {
|
|
108
117
|
this._log.error(
|
|
109
118
|
`alias:del - Failed deleting alias from sink - Pathname: ${path}`,
|
|
@@ -119,7 +128,7 @@ const AliasDel = class AliasDel {
|
|
|
119
128
|
);
|
|
120
129
|
|
|
121
130
|
const outgoing = new HttpOutgoing();
|
|
122
|
-
outgoing.cacheControl = this._cacheControl;
|
|
131
|
+
outgoing.cacheControl = this._cacheControl || "";
|
|
123
132
|
outgoing.statusCode = 204;
|
|
124
133
|
|
|
125
134
|
end({ labels: { status: outgoing.statusCode, type } });
|
|
@@ -52,6 +52,13 @@ const AliasGet = class AliasGet {
|
|
|
52
52
|
return this._metrics;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* @param {any} req
|
|
57
|
+
* @param {string} type
|
|
58
|
+
* @param {string} name
|
|
59
|
+
* @param {string} alias
|
|
60
|
+
* @param {string} extra
|
|
61
|
+
*/
|
|
55
62
|
async handler(req, type, name, alias, extra) {
|
|
56
63
|
const end = this._histogram.timer();
|
|
57
64
|
|
|
@@ -65,7 +72,9 @@ const AliasGet = class AliasGet {
|
|
|
65
72
|
validators.name(pName);
|
|
66
73
|
validators.type(type);
|
|
67
74
|
} catch (error) {
|
|
68
|
-
this._log.debug(
|
|
75
|
+
this._log.debug(
|
|
76
|
+
`alias:get - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
77
|
+
);
|
|
69
78
|
const e = new HttpError.NotFound();
|
|
70
79
|
end({ labels: { success: false, status: e.status } });
|
|
71
80
|
throw e;
|
|
@@ -103,7 +112,7 @@ const AliasGet = class AliasGet {
|
|
|
103
112
|
|
|
104
113
|
const assetPath = createFilePathToAsset(asset);
|
|
105
114
|
|
|
106
|
-
const file = await this._sink.read(assetPath);
|
|
115
|
+
const file = await (this._sink && this._sink.read(assetPath));
|
|
107
116
|
const outgoing = new HttpOutgoing();
|
|
108
117
|
outgoing.cacheControl = this._cacheControl;
|
|
109
118
|
outgoing.mimeType = asset.mimeType;
|
|
@@ -119,14 +128,17 @@ const AliasGet = class AliasGet {
|
|
|
119
128
|
outgoing.statusCode = 200;
|
|
120
129
|
outgoing.stream = file.stream;
|
|
121
130
|
|
|
122
|
-
outgoing.stream
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
131
|
+
const outgoingStream = outgoing.stream;
|
|
132
|
+
if (outgoingStream) {
|
|
133
|
+
outgoingStream.on("error", (err) => {
|
|
134
|
+
this._log.info(`alias:get - File stream error - ${err}`);
|
|
135
|
+
end({ labels: { success: false, status: 503, type } });
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
outgoingStream.on("end", () => {
|
|
139
|
+
end({ labels: { status: outgoing.statusCode, type } });
|
|
140
|
+
});
|
|
141
|
+
}
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
this._log.debug(`alias:get - Alias found - Pathname: ${path}`);
|
|
@@ -45,6 +45,13 @@ const AliasGet = class AliasGet {
|
|
|
45
45
|
return this._metrics;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @param {any} req
|
|
50
|
+
* @param {string} type
|
|
51
|
+
* @param {string} name
|
|
52
|
+
* @param {string} alias
|
|
53
|
+
* @param {string} extra
|
|
54
|
+
*/
|
|
48
55
|
async handler(req, type, name, alias, extra) {
|
|
49
56
|
const end = this._histogram.timer();
|
|
50
57
|
|
|
@@ -58,7 +65,9 @@ const AliasGet = class AliasGet {
|
|
|
58
65
|
validators.name(pName);
|
|
59
66
|
validators.type(type);
|
|
60
67
|
} catch (error) {
|
|
61
|
-
this._log.debug(
|
|
68
|
+
this._log.debug(
|
|
69
|
+
`alias:get - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
70
|
+
);
|
|
62
71
|
const e = new HttpError.NotFound();
|
|
63
72
|
end({ labels: { success: false, status: e.status } });
|
|
64
73
|
throw e;
|
|
@@ -57,6 +57,9 @@ const AliasPost = class AliasPost {
|
|
|
57
57
|
return this._metrics;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* @param {any} incoming
|
|
62
|
+
*/
|
|
60
63
|
_parser(incoming) {
|
|
61
64
|
return new Promise((resolve, reject) => {
|
|
62
65
|
this._multipart
|
|
@@ -88,7 +91,7 @@ const AliasPost = class AliasPost {
|
|
|
88
91
|
name: alias.name,
|
|
89
92
|
version: alias.version,
|
|
90
93
|
});
|
|
91
|
-
await this._sink.read(path);
|
|
94
|
+
if (this._sink) await this._sink.read(path);
|
|
92
95
|
} catch (error) {
|
|
93
96
|
this._log.error(
|
|
94
97
|
`alias:post - Unable to locate requested published package version - Version ${alias.name}@${alias.version}`,
|
|
@@ -127,10 +130,13 @@ const AliasPost = class AliasPost {
|
|
|
127
130
|
});
|
|
128
131
|
}
|
|
129
132
|
|
|
133
|
+
/**
|
|
134
|
+
* @param {any} incoming
|
|
135
|
+
*/
|
|
130
136
|
async _exist(incoming) {
|
|
131
137
|
try {
|
|
132
138
|
const path = createFilePathToAlias(incoming);
|
|
133
|
-
await this._sink.exist(path);
|
|
139
|
+
if (this._sink) await this._sink.exist(path);
|
|
134
140
|
return true;
|
|
135
141
|
// eslint-disable-next-line no-unused-vars
|
|
136
142
|
} catch (error) {
|
|
@@ -138,6 +144,13 @@ const AliasPost = class AliasPost {
|
|
|
138
144
|
}
|
|
139
145
|
}
|
|
140
146
|
|
|
147
|
+
/**
|
|
148
|
+
* @param {any} req
|
|
149
|
+
* @param {any} user
|
|
150
|
+
* @param {string} type
|
|
151
|
+
* @param {string} name
|
|
152
|
+
* @param {string} alias
|
|
153
|
+
*/
|
|
141
154
|
async handler(req, user, type, name, alias) {
|
|
142
155
|
const end = this._histogram.timer();
|
|
143
156
|
|
|
@@ -149,7 +162,9 @@ const AliasPost = class AliasPost {
|
|
|
149
162
|
validators.name(pName);
|
|
150
163
|
validators.type(type);
|
|
151
164
|
} catch (error) {
|
|
152
|
-
this._log.info(
|
|
165
|
+
this._log.info(
|
|
166
|
+
`alias:post - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
167
|
+
);
|
|
153
168
|
const e = new HttpError.NotFound();
|
|
154
169
|
end({ labels: { success: false, status: e.status } });
|
|
155
170
|
throw e;
|
|
@@ -190,7 +205,7 @@ const AliasPost = class AliasPost {
|
|
|
190
205
|
await this._parser(incoming);
|
|
191
206
|
|
|
192
207
|
const outgoing = new HttpOutgoing();
|
|
193
|
-
outgoing.cacheControl = this._cacheControl;
|
|
208
|
+
outgoing.cacheControl = this._cacheControl || "";
|
|
194
209
|
outgoing.statusCode = 303;
|
|
195
210
|
outgoing.location = createURIToAlias(incoming);
|
|
196
211
|
|
|
@@ -57,6 +57,9 @@ const AliasPut = class AliasPut {
|
|
|
57
57
|
return this._metrics;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* @param {any} incoming
|
|
62
|
+
*/
|
|
60
63
|
_parser(incoming) {
|
|
61
64
|
return new Promise((resolve, reject) => {
|
|
62
65
|
this._multipart
|
|
@@ -88,7 +91,7 @@ const AliasPut = class AliasPut {
|
|
|
88
91
|
name: alias.name,
|
|
89
92
|
version: alias.version,
|
|
90
93
|
});
|
|
91
|
-
await this._sink.read(path);
|
|
94
|
+
if (this._sink) await this._sink.read(path);
|
|
92
95
|
} catch (error) {
|
|
93
96
|
this._log.error(
|
|
94
97
|
`alias:post - Unable to locate requested published package version - Version ${alias.name}@${alias.version}`,
|
|
@@ -127,10 +130,13 @@ const AliasPut = class AliasPut {
|
|
|
127
130
|
});
|
|
128
131
|
}
|
|
129
132
|
|
|
133
|
+
/**
|
|
134
|
+
* @param {any} incoming
|
|
135
|
+
*/
|
|
130
136
|
async _exist(incoming) {
|
|
131
137
|
try {
|
|
132
138
|
const path = createFilePathToAlias(incoming);
|
|
133
|
-
await this._sink.exist(path);
|
|
139
|
+
if (this._sink) await this._sink.exist(path);
|
|
134
140
|
return true;
|
|
135
141
|
// eslint-disable-next-line no-unused-vars
|
|
136
142
|
} catch (error) {
|
|
@@ -138,6 +144,13 @@ const AliasPut = class AliasPut {
|
|
|
138
144
|
}
|
|
139
145
|
}
|
|
140
146
|
|
|
147
|
+
/**
|
|
148
|
+
* @param {any} req
|
|
149
|
+
* @param {any} user
|
|
150
|
+
* @param {string} type
|
|
151
|
+
* @param {string} name
|
|
152
|
+
* @param {string} alias
|
|
153
|
+
*/
|
|
141
154
|
async handler(req, user, type, name, alias) {
|
|
142
155
|
const end = this._histogram.timer();
|
|
143
156
|
|
|
@@ -149,7 +162,9 @@ const AliasPut = class AliasPut {
|
|
|
149
162
|
validators.name(pName);
|
|
150
163
|
validators.type(type);
|
|
151
164
|
} catch (error) {
|
|
152
|
-
this._log.info(
|
|
165
|
+
this._log.info(
|
|
166
|
+
`alias:put - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
167
|
+
);
|
|
153
168
|
const e = new HttpError.BadRequest();
|
|
154
169
|
end({ labels: { success: false, status: e.status } });
|
|
155
170
|
throw e;
|
|
@@ -190,7 +205,7 @@ const AliasPut = class AliasPut {
|
|
|
190
205
|
await this._parser(incoming);
|
|
191
206
|
|
|
192
207
|
const outgoing = new HttpOutgoing();
|
|
193
|
-
outgoing.cacheControl = this._cacheControl;
|
|
208
|
+
outgoing.cacheControl = this._cacheControl || "";
|
|
194
209
|
outgoing.statusCode = 303;
|
|
195
210
|
outgoing.location = createURIToAlias(incoming);
|
|
196
211
|
|
|
@@ -48,6 +48,9 @@ const AuthPost = class AuthPost {
|
|
|
48
48
|
return this._metrics;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* @param {any} incoming
|
|
53
|
+
*/
|
|
51
54
|
_parser(incoming) {
|
|
52
55
|
return new Promise((resolve, reject) => {
|
|
53
56
|
this._multipart
|
|
@@ -76,6 +79,9 @@ const AuthPost = class AuthPost {
|
|
|
76
79
|
});
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
/**
|
|
83
|
+
* @param {any} req
|
|
84
|
+
*/
|
|
79
85
|
async handler(req) {
|
|
80
86
|
const end = this._histogram.timer();
|
|
81
87
|
|
|
@@ -98,7 +104,7 @@ const AuthPost = class AuthPost {
|
|
|
98
104
|
const obj = await this._parser(incoming);
|
|
99
105
|
|
|
100
106
|
const outgoing = new HttpOutgoing();
|
|
101
|
-
outgoing.cacheControl = this._cacheControl;
|
|
107
|
+
outgoing.cacheControl = this._cacheControl || "";
|
|
102
108
|
outgoing.statusCode = 200;
|
|
103
109
|
outgoing.mimeType = "application/json";
|
|
104
110
|
outgoing.body = obj;
|
package/lib/handlers/map.get.js
CHANGED
|
@@ -46,6 +46,11 @@ const MapGet = class MapGet {
|
|
|
46
46
|
return this._metrics;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @param {any} req
|
|
51
|
+
* @param {string} name
|
|
52
|
+
* @param {string} version
|
|
53
|
+
*/
|
|
49
54
|
async handler(req, name, version) {
|
|
50
55
|
const end = this._histogram.timer();
|
|
51
56
|
|
|
@@ -56,7 +61,9 @@ const MapGet = class MapGet {
|
|
|
56
61
|
validators.version(pVersion);
|
|
57
62
|
validators.name(pName);
|
|
58
63
|
} catch (error) {
|
|
59
|
-
this._log.debug(
|
|
64
|
+
this._log.debug(
|
|
65
|
+
`map:get - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
66
|
+
);
|
|
60
67
|
const e = new HttpError.NotFound();
|
|
61
68
|
end({ labels: { success: false, status: e.status } });
|
|
62
69
|
throw e;
|
|
@@ -81,7 +88,7 @@ const MapGet = class MapGet {
|
|
|
81
88
|
});
|
|
82
89
|
|
|
83
90
|
try {
|
|
84
|
-
const file = await this._sink.read(path);
|
|
91
|
+
const file = await (this._sink && this._sink.read(path));
|
|
85
92
|
const outgoing = new HttpOutgoing();
|
|
86
93
|
outgoing.cacheControl = this._cacheControl;
|
|
87
94
|
outgoing.mimeType = "application/json";
|
|
@@ -97,14 +104,17 @@ const MapGet = class MapGet {
|
|
|
97
104
|
outgoing.statusCode = 200;
|
|
98
105
|
outgoing.stream = file.stream;
|
|
99
106
|
|
|
100
|
-
outgoing.stream
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
const outgoingStream = outgoing.stream;
|
|
108
|
+
if (outgoingStream) {
|
|
109
|
+
outgoingStream.on("error", (err) => {
|
|
110
|
+
this._log.info(`map:get - File stream error - ${err}`);
|
|
111
|
+
end({ labels: { success: false, status: 503, type: "map" } });
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
outgoingStream.on("end", () => {
|
|
115
|
+
end({ labels: { status: outgoing.statusCode, type: "map" } });
|
|
116
|
+
});
|
|
117
|
+
}
|
|
108
118
|
}
|
|
109
119
|
|
|
110
120
|
this._log.debug(`map:get - Import map found - Pathname: ${path}`);
|
package/lib/handlers/map.put.js
CHANGED
|
@@ -67,9 +67,13 @@ const MapPut = class MapPut {
|
|
|
67
67
|
return this._metrics;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* @param {any} incoming
|
|
72
|
+
*/
|
|
70
73
|
_parser(incoming) {
|
|
71
74
|
return new Promise((resolve, reject) => {
|
|
72
75
|
const path = createFilePathToImportMap(incoming);
|
|
76
|
+
/** @type {Promise<any>[]} */
|
|
73
77
|
const queue = [];
|
|
74
78
|
|
|
75
79
|
const busboy = Busboy({
|
|
@@ -81,15 +85,18 @@ const MapPut = class MapPut {
|
|
|
81
85
|
},
|
|
82
86
|
});
|
|
83
87
|
|
|
84
|
-
busboy.on(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
busboy.on(
|
|
89
|
+
"file",
|
|
90
|
+
(/** @type {any} */ fieldname, /** @type {any} */ file) => {
|
|
91
|
+
queue.push(
|
|
92
|
+
this._handleFile({
|
|
93
|
+
fieldname,
|
|
94
|
+
file,
|
|
95
|
+
path,
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
);
|
|
93
100
|
|
|
94
101
|
busboy.on("close", () => {
|
|
95
102
|
Promise.all(queue)
|
|
@@ -103,7 +110,7 @@ const MapPut = class MapPut {
|
|
|
103
110
|
});
|
|
104
111
|
});
|
|
105
112
|
|
|
106
|
-
busboy.on("error", (error) => {
|
|
113
|
+
busboy.on("error", (/** @type {any} */ error) => {
|
|
107
114
|
reject(error);
|
|
108
115
|
});
|
|
109
116
|
|
|
@@ -114,6 +121,9 @@ const MapPut = class MapPut {
|
|
|
114
121
|
});
|
|
115
122
|
}
|
|
116
123
|
|
|
124
|
+
/**
|
|
125
|
+
* @param {{ fieldname: any, file: any, path: any }} options
|
|
126
|
+
*/
|
|
117
127
|
async _handleFile({ fieldname, file, path }) {
|
|
118
128
|
// We accept only one file on this given fieldname.
|
|
119
129
|
// Throw if any other files is posted.
|
|
@@ -128,7 +138,7 @@ const MapPut = class MapPut {
|
|
|
128
138
|
|
|
129
139
|
// Buffer up the incoming file and check if we can
|
|
130
140
|
// parse it as JSON or not.
|
|
131
|
-
let obj
|
|
141
|
+
let obj;
|
|
132
142
|
try {
|
|
133
143
|
const str = await streamCollector(file);
|
|
134
144
|
hasher.update(str);
|
|
@@ -160,6 +170,9 @@ const MapPut = class MapPut {
|
|
|
160
170
|
return `sha512-${hasher.digest("base64")}`;
|
|
161
171
|
}
|
|
162
172
|
|
|
173
|
+
/**
|
|
174
|
+
* @param {any} incoming
|
|
175
|
+
*/
|
|
163
176
|
async _readVersions(incoming) {
|
|
164
177
|
const path = createFilePathToVersion(incoming);
|
|
165
178
|
let versions;
|
|
@@ -180,6 +193,10 @@ const MapPut = class MapPut {
|
|
|
180
193
|
return versions;
|
|
181
194
|
}
|
|
182
195
|
|
|
196
|
+
/**
|
|
197
|
+
* @param {any} incoming
|
|
198
|
+
* @param {any} versions
|
|
199
|
+
*/
|
|
183
200
|
async _writeVersions(incoming, versions) {
|
|
184
201
|
const path = createFilePathToVersion(incoming);
|
|
185
202
|
await writeJSON(this._sink, path, versions, "application/json");
|
|
@@ -188,6 +205,12 @@ const MapPut = class MapPut {
|
|
|
188
205
|
);
|
|
189
206
|
}
|
|
190
207
|
|
|
208
|
+
/**
|
|
209
|
+
* @param {any} req
|
|
210
|
+
* @param {any} user
|
|
211
|
+
* @param {string} name
|
|
212
|
+
* @param {string} version
|
|
213
|
+
*/
|
|
191
214
|
async handler(req, user, name, version) {
|
|
192
215
|
const end = this._histogram.timer();
|
|
193
216
|
|
|
@@ -198,7 +221,9 @@ const MapPut = class MapPut {
|
|
|
198
221
|
validators.version(pVersion);
|
|
199
222
|
validators.name(pName);
|
|
200
223
|
} catch (error) {
|
|
201
|
-
this._log.info(
|
|
224
|
+
this._log.info(
|
|
225
|
+
`map:put - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
226
|
+
);
|
|
202
227
|
const e = new HttpError.BadRequest();
|
|
203
228
|
end({ labels: { success: false, status: e.status } });
|
|
204
229
|
throw e;
|
|
@@ -250,7 +275,7 @@ const MapPut = class MapPut {
|
|
|
250
275
|
}
|
|
251
276
|
|
|
252
277
|
const outgoing = new HttpOutgoing();
|
|
253
|
-
outgoing.cacheControl = this._cacheControl;
|
|
278
|
+
outgoing.cacheControl = this._cacheControl || "";
|
|
254
279
|
outgoing.statusCode = 303;
|
|
255
280
|
outgoing.location = createURIPathToImportMap(incoming);
|
|
256
281
|
|
package/lib/handlers/pkg.get.js
CHANGED
|
@@ -48,6 +48,13 @@ const PkgGet = class PkgGet {
|
|
|
48
48
|
return this._metrics;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* @param {any} req
|
|
53
|
+
* @param {string} type
|
|
54
|
+
* @param {string} name
|
|
55
|
+
* @param {string} version
|
|
56
|
+
* @param {string} extra
|
|
57
|
+
*/
|
|
51
58
|
async handler(req, type, name, version, extra) {
|
|
52
59
|
const end = this._histogram.timer();
|
|
53
60
|
|
|
@@ -61,7 +68,9 @@ const PkgGet = class PkgGet {
|
|
|
61
68
|
validators.name(pName);
|
|
62
69
|
validators.type(type);
|
|
63
70
|
} catch (error) {
|
|
64
|
-
this._log.debug(
|
|
71
|
+
this._log.debug(
|
|
72
|
+
`pkg:get - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
73
|
+
);
|
|
65
74
|
const e = new HttpError.NotFound();
|
|
66
75
|
end({ labels: { success: false, status: e.status } });
|
|
67
76
|
throw e;
|
|
@@ -90,7 +99,7 @@ const PkgGet = class PkgGet {
|
|
|
90
99
|
const path = createFilePathToAsset(asset);
|
|
91
100
|
|
|
92
101
|
try {
|
|
93
|
-
const file = await this._sink.read(path);
|
|
102
|
+
const file = await (this._sink && this._sink.read(path));
|
|
94
103
|
const outgoing = new HttpOutgoing();
|
|
95
104
|
outgoing.cacheControl = this._cacheControl;
|
|
96
105
|
outgoing.mimeType = asset.mimeType;
|
|
@@ -106,14 +115,17 @@ const PkgGet = class PkgGet {
|
|
|
106
115
|
outgoing.statusCode = 200;
|
|
107
116
|
outgoing.stream = file.stream;
|
|
108
117
|
|
|
109
|
-
outgoing.stream
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
const outgoingStream = outgoing.stream;
|
|
119
|
+
if (outgoingStream) {
|
|
120
|
+
outgoingStream.on("error", (err) => {
|
|
121
|
+
this._log.info(`pkg:get - File stream error - ${err}`);
|
|
122
|
+
end({ labels: { success: false, status: 503, type } });
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
outgoingStream.on("end", () => {
|
|
126
|
+
end({ labels: { status: outgoing.statusCode, type } });
|
|
127
|
+
});
|
|
128
|
+
}
|
|
117
129
|
}
|
|
118
130
|
|
|
119
131
|
this._log.debug(`pkg:get - Asset found - Pathname: ${path}`);
|