@eik/core 2.1.76 → 2.1.77
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 +7 -0
- package/lib/handlers/versions.get.js +71 -45
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [2.1.77](https://github.com/eik-lib/core/compare/v2.1.76...v2.1.77) (2026-08-17)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* propagate sink errors in versions.get as 502 rather than 404 ([#636](https://github.com/eik-lib/core/issues/636)) ([21b8619](https://github.com/eik-lib/core/commit/21b8619eeff9150914adcfa2ae6a233e2c10ec60))
|
|
7
|
+
|
|
1
8
|
## [2.1.76](https://github.com/eik-lib/core/compare/v2.1.75...v2.1.76) (2026-08-14)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -81,57 +81,83 @@ const VersionsGet = class VersionsGet {
|
|
|
81
81
|
}
|
|
82
82
|
const path = createFilePathToVersion({ org, type, name: pName });
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (this._etag) {
|
|
91
|
-
outgoing.etag = file.etag;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (this._etag && req.headers["if-none-match"] === file.etag) {
|
|
95
|
-
outgoing.statusCode = 304;
|
|
96
|
-
file.stream.destroy();
|
|
97
|
-
} else {
|
|
98
|
-
outgoing.statusCode = 200;
|
|
99
|
-
outgoing.stream = file.stream;
|
|
100
|
-
|
|
101
|
-
const outgoingStream = outgoing.stream;
|
|
102
|
-
if (outgoingStream) {
|
|
103
|
-
outgoingStream.on(
|
|
104
|
-
"error",
|
|
105
|
-
(/** @type {NodeJS.ErrnoException} */ err) => {
|
|
106
|
-
// ERR_STREAM_PREMATURE_CLOSE means the client closed the
|
|
107
|
-
// connection before the transfer finished. This is normal
|
|
108
|
-
// browser behaviour (navigation, cancelled requests, etc.)
|
|
109
|
-
// and not a server-side error worth alerting on.
|
|
110
|
-
if (err.code === "ERR_STREAM_PREMATURE_CLOSE") {
|
|
111
|
-
this._log.debug(`pkg:latest - File stream error - ${err}`);
|
|
112
|
-
} else {
|
|
113
|
-
this._log.info(`pkg:latest - File stream error - ${err}`);
|
|
114
|
-
}
|
|
115
|
-
end({ labels: { success: false, status: 503, type } });
|
|
116
|
-
},
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
outgoingStream.on("end", () => {
|
|
120
|
-
end({ labels: { status: outgoing.statusCode, type } });
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
84
|
+
if (!this._sink) {
|
|
85
|
+
const e = new HttpError.NotFound();
|
|
86
|
+
end({ labels: { success: false, status: e.status, type } });
|
|
87
|
+
throw e;
|
|
88
|
+
}
|
|
124
89
|
|
|
125
|
-
|
|
90
|
+
// Check existence first to distinguish a genuinely missing package
|
|
91
|
+
// from a transient infrastructure error. Without this distinction,
|
|
92
|
+
// any GCS or network failure would surface as 404, which callers
|
|
93
|
+
// may misinterpret as "package does not exist".
|
|
94
|
+
try {
|
|
95
|
+
await this._sink.exist(path);
|
|
96
|
+
} catch {
|
|
97
|
+
this._log.debug(
|
|
98
|
+
`pkg:latest - Package versions not found - Pathname: ${path}`,
|
|
99
|
+
);
|
|
100
|
+
const e = new HttpError.NotFound();
|
|
101
|
+
end({ labels: { success: false, status: e.status, type } });
|
|
102
|
+
throw e;
|
|
103
|
+
}
|
|
126
104
|
|
|
127
|
-
|
|
128
|
-
|
|
105
|
+
// File exists — any read failure here is an infrastructure error.
|
|
106
|
+
let file;
|
|
107
|
+
try {
|
|
108
|
+
file = await this._sink.read(path);
|
|
129
109
|
} catch (error) {
|
|
130
|
-
this._log.
|
|
131
|
-
|
|
110
|
+
this._log.error(
|
|
111
|
+
`pkg:latest - Failed to read package versions from sink - Pathname: ${path}`,
|
|
112
|
+
);
|
|
113
|
+
this._log.trace(error);
|
|
114
|
+
const e = new HttpError.BadGateway();
|
|
132
115
|
end({ labels: { success: false, status: e.status, type } });
|
|
133
116
|
throw e;
|
|
134
117
|
}
|
|
118
|
+
|
|
119
|
+
const outgoing = new HttpOutgoing();
|
|
120
|
+
outgoing.cacheControl = this._cacheControl;
|
|
121
|
+
outgoing.mimeType = "application/json";
|
|
122
|
+
|
|
123
|
+
if (this._etag) {
|
|
124
|
+
outgoing.etag = file.etag;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (this._etag && req.headers["if-none-match"] === file.etag) {
|
|
128
|
+
outgoing.statusCode = 304;
|
|
129
|
+
file.stream.destroy();
|
|
130
|
+
} else {
|
|
131
|
+
outgoing.statusCode = 200;
|
|
132
|
+
outgoing.stream = file.stream;
|
|
133
|
+
|
|
134
|
+
const outgoingStream = outgoing.stream;
|
|
135
|
+
if (outgoingStream) {
|
|
136
|
+
outgoingStream.on(
|
|
137
|
+
"error",
|
|
138
|
+
(/** @type {NodeJS.ErrnoException} */ err) => {
|
|
139
|
+
// ERR_STREAM_PREMATURE_CLOSE means the client closed the
|
|
140
|
+
// connection before the transfer finished. This is normal
|
|
141
|
+
// browser behaviour (navigation, cancelled requests, etc.)
|
|
142
|
+
// and not a server-side error worth alerting on.
|
|
143
|
+
if (err.code === "ERR_STREAM_PREMATURE_CLOSE") {
|
|
144
|
+
this._log.debug(`pkg:latest - File stream error - ${err}`);
|
|
145
|
+
} else {
|
|
146
|
+
this._log.info(`pkg:latest - File stream error - ${err}`);
|
|
147
|
+
}
|
|
148
|
+
end({ labels: { success: false, status: 503, type } });
|
|
149
|
+
},
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
outgoingStream.on("end", () => {
|
|
153
|
+
end({ labels: { status: outgoing.statusCode, type } });
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this._log.debug(`pkg:latest - Package versions found - Pathname: ${path}`);
|
|
159
|
+
|
|
160
|
+
return outgoing;
|
|
135
161
|
}
|
|
136
162
|
};
|
|
137
163
|
export default VersionsGet;
|