@eik/core 2.0.27 → 2.1.1
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 +15 -0
- package/lib/handlers/alias.get-v2.js +146 -0
- package/lib/main.js +2 -0
- package/package.json +3 -3
- package/types/handlers/alias.get-v2.d.ts +51 -0
- package/types/main.d.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
## [2.1.1](https://github.com/eik-lib/core/compare/v2.1.0...v2.1.1) (2025-10-08)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **deps:** update dependency semver to v7.7.3 ([#513](https://github.com/eik-lib/core/issues/513)) ([8907d92](https://github.com/eik-lib/core/commit/8907d924380d19d419859e28f9cd2a1d986a3177))
|
|
7
|
+
|
|
8
|
+
# [2.1.0](https://github.com/eik-lib/core/compare/v2.0.27...v2.1.0) (2025-09-30)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add new alias route handler ([e7d78f6](https://github.com/eik-lib/core/commit/e7d78f6559cc9efb61c78e992ad094e0bb312a9d))
|
|
14
|
+
* add stale while revalidate to new alias route ([7639c11](https://github.com/eik-lib/core/commit/7639c11dda5a0353de499552294611fe96914fab))
|
|
15
|
+
|
|
1
16
|
## [2.0.27](https://github.com/eik-lib/core/compare/v2.0.26...v2.0.27) (2025-09-24)
|
|
2
17
|
|
|
3
18
|
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { validators } from "@eik/common";
|
|
2
|
+
import originalUrl from "original-url";
|
|
3
|
+
import HttpError from "http-errors";
|
|
4
|
+
import abslog from "abslog";
|
|
5
|
+
import Metrics from "@metrics/client";
|
|
6
|
+
import Asset from "../classes/asset.js";
|
|
7
|
+
|
|
8
|
+
import { decodeUriComponent, readJSON } from "../utils/utils.js";
|
|
9
|
+
import {
|
|
10
|
+
createFilePathToAlias,
|
|
11
|
+
createFilePathToAsset,
|
|
12
|
+
} from "../utils/path-builders-fs.js";
|
|
13
|
+
import HttpOutgoing from "../classes/http-outgoing.js";
|
|
14
|
+
import config from "../utils/defaults.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {object} AliasGetOptions
|
|
18
|
+
* @property {boolean} [etag]
|
|
19
|
+
* @property {string} [cacheControl]
|
|
20
|
+
* @property {Array<[string, string]>} [organizations] List of key-value pairs [hostname, organization]
|
|
21
|
+
* @property {import("@eik/sink").default} [sink]
|
|
22
|
+
* @property {import("abslog").AbstractLoggerOptions} [logger]
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const AliasGet = class AliasGet {
|
|
26
|
+
/**
|
|
27
|
+
* @param {AliasGetOptions} options
|
|
28
|
+
*/
|
|
29
|
+
constructor({ organizations, cacheControl, logger, sink, etag } = {}) {
|
|
30
|
+
this._organizations = organizations || config.organizations;
|
|
31
|
+
// 2 weeks stale while revalidate
|
|
32
|
+
this._cacheControl =
|
|
33
|
+
cacheControl || "public, max-age=1200, stale-while-revalidate=1209600";
|
|
34
|
+
this._sink = sink;
|
|
35
|
+
this._etag = etag || config.etag;
|
|
36
|
+
this._log = abslog(logger);
|
|
37
|
+
this._metrics = new Metrics();
|
|
38
|
+
this._histogram = this._metrics.histogram({
|
|
39
|
+
name: "eik_core_alias_swr_get_handler",
|
|
40
|
+
description:
|
|
41
|
+
"Histogram measuring time taken in @eik/core stale-while-revalidate powered AliasGet handler method",
|
|
42
|
+
labels: {
|
|
43
|
+
success: true,
|
|
44
|
+
type: "unknown",
|
|
45
|
+
},
|
|
46
|
+
buckets: [0.005, 0.01, 0.06, 0.1, 0.6, 1.0, 2.0, 4.0],
|
|
47
|
+
});
|
|
48
|
+
this._orgRegistry = new Map(this._organizations);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get metrics() {
|
|
52
|
+
return this._metrics;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async handler(req, type, name, alias, extra) {
|
|
56
|
+
const end = this._histogram.timer();
|
|
57
|
+
|
|
58
|
+
const pAlias = decodeUriComponent(alias);
|
|
59
|
+
const pExtra = decodeUriComponent(extra);
|
|
60
|
+
const pName = decodeUriComponent(name);
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
validators.alias(pAlias);
|
|
64
|
+
validators.extra(pExtra);
|
|
65
|
+
validators.name(pName);
|
|
66
|
+
validators.type(type);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
this._log.debug(`alias:get - Validation failed - ${error.message}`);
|
|
69
|
+
const e = new HttpError.NotFound();
|
|
70
|
+
end({ labels: { success: false, status: e.status } });
|
|
71
|
+
throw e;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const url = originalUrl(req);
|
|
75
|
+
const org = this._orgRegistry.get(url.hostname);
|
|
76
|
+
|
|
77
|
+
if (!org) {
|
|
78
|
+
this._log.info(
|
|
79
|
+
`alias:get - Hostname does not match a configured organization - ${url.hostname}`,
|
|
80
|
+
);
|
|
81
|
+
const e = new HttpError.BadRequest();
|
|
82
|
+
end({ labels: { success: false, status: e.status, type } });
|
|
83
|
+
throw e;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const path = createFilePathToAlias({
|
|
87
|
+
org,
|
|
88
|
+
type,
|
|
89
|
+
name: pName,
|
|
90
|
+
alias: pAlias,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const obj = await readJSON(this._sink, path);
|
|
95
|
+
|
|
96
|
+
const asset = new Asset({
|
|
97
|
+
pathname: pExtra,
|
|
98
|
+
version: obj.version,
|
|
99
|
+
name: obj.name,
|
|
100
|
+
type: obj.type,
|
|
101
|
+
org: obj.org,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const assetPath = createFilePathToAsset(asset);
|
|
105
|
+
|
|
106
|
+
const file = await this._sink.read(assetPath);
|
|
107
|
+
const outgoing = new HttpOutgoing();
|
|
108
|
+
outgoing.cacheControl = this._cacheControl;
|
|
109
|
+
outgoing.mimeType = asset.mimeType;
|
|
110
|
+
|
|
111
|
+
if (this._etag) {
|
|
112
|
+
outgoing.etag = file.etag;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (this._etag && req.headers["if-none-match"] === file.etag) {
|
|
116
|
+
outgoing.statusCode = 304;
|
|
117
|
+
file.stream.destroy();
|
|
118
|
+
} else {
|
|
119
|
+
outgoing.statusCode = 200;
|
|
120
|
+
outgoing.stream = file.stream;
|
|
121
|
+
|
|
122
|
+
outgoing.stream.on("error", (err) => {
|
|
123
|
+
this._log.info(`alias:get - File stream error - ${err}`);
|
|
124
|
+
end({ labels: { success: false, status: 503, type } });
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
outgoing.stream.on("end", () => {
|
|
128
|
+
end({ labels: { status: outgoing.statusCode, type } });
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this._log.debug(`alias:get - Alias found - Pathname: ${path}`);
|
|
133
|
+
|
|
134
|
+
end({ labels: { status: outgoing.statusCode, type } });
|
|
135
|
+
|
|
136
|
+
return outgoing;
|
|
137
|
+
// eslint-disable-next-line no-unused-vars
|
|
138
|
+
} catch (error) {
|
|
139
|
+
this._log.debug(`alias:get - Alias not found - Pathname: ${path}`);
|
|
140
|
+
const e = new HttpError.NotFound();
|
|
141
|
+
end({ labels: { success: false, status: e.status, type } });
|
|
142
|
+
throw e;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
export default AliasGet;
|
package/lib/main.js
CHANGED
|
@@ -5,6 +5,7 @@ import VersionsGet from "./handlers/versions.get.js";
|
|
|
5
5
|
import AliasPost from "./handlers/alias.post.js";
|
|
6
6
|
import AliasPut from "./handlers/alias.put.js";
|
|
7
7
|
import AliasGet from "./handlers/alias.get.js";
|
|
8
|
+
import AliasGetV2 from "./handlers/alias.get-v2.js";
|
|
8
9
|
import AliasDel from "./handlers/alias.delete.js";
|
|
9
10
|
import AuthPost from "./handlers/auth.post.js";
|
|
10
11
|
import PkgLog from "./handlers/pkg.log.js";
|
|
@@ -23,6 +24,7 @@ const http = {
|
|
|
23
24
|
AliasPost,
|
|
24
25
|
AliasPut,
|
|
25
26
|
AliasGet,
|
|
27
|
+
AliasGetV2,
|
|
26
28
|
AliasDel,
|
|
27
29
|
AuthPost,
|
|
28
30
|
PkgLog,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eik/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Core server package",
|
|
5
5
|
"main": "lib/main.js",
|
|
6
6
|
"types": "./types/main.d.ts",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"http-errors": "2.0.0",
|
|
36
36
|
"mime": "4.1.0",
|
|
37
37
|
"original-url": "1.2.3",
|
|
38
|
-
"semver": "7.7.
|
|
38
|
+
"semver": "7.7.3",
|
|
39
39
|
"ssri": "12.0.0",
|
|
40
40
|
"tar": "7.5.1",
|
|
41
41
|
"unique-slug": "5.0.0"
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"npm-run-all2": "7.0.2",
|
|
54
54
|
"prettier": "3.5.3",
|
|
55
55
|
"rimraf": "6.0.1",
|
|
56
|
-
"semantic-release": "24.2.
|
|
56
|
+
"semantic-release": "24.2.9",
|
|
57
57
|
"tap": "21.0.1",
|
|
58
58
|
"typescript": "5.6.3"
|
|
59
59
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export default AliasGet;
|
|
2
|
+
export type AliasGetOptions = {
|
|
3
|
+
etag?: boolean;
|
|
4
|
+
cacheControl?: string;
|
|
5
|
+
/**
|
|
6
|
+
* List of key-value pairs [hostname, organization]
|
|
7
|
+
*/
|
|
8
|
+
organizations?: Array<[string, string]>;
|
|
9
|
+
sink?: import("@eik/sink").default;
|
|
10
|
+
logger?: import("abslog").AbstractLoggerOptions;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {object} AliasGetOptions
|
|
14
|
+
* @property {boolean} [etag]
|
|
15
|
+
* @property {string} [cacheControl]
|
|
16
|
+
* @property {Array<[string, string]>} [organizations] List of key-value pairs [hostname, organization]
|
|
17
|
+
* @property {import("@eik/sink").default} [sink]
|
|
18
|
+
* @property {import("abslog").AbstractLoggerOptions} [logger]
|
|
19
|
+
*/
|
|
20
|
+
declare const AliasGet: {
|
|
21
|
+
new ({ organizations, cacheControl, logger, sink, etag }?: AliasGetOptions): {
|
|
22
|
+
_organizations: [string, string][];
|
|
23
|
+
_cacheControl: string;
|
|
24
|
+
_sink: import("@eik/sink").default;
|
|
25
|
+
_etag: boolean;
|
|
26
|
+
_log: abslog.ValidLogger;
|
|
27
|
+
_metrics: Metrics;
|
|
28
|
+
_histogram: Metrics.MetricsHistogram;
|
|
29
|
+
_orgRegistry: Map<string, string>;
|
|
30
|
+
readonly metrics: Metrics;
|
|
31
|
+
handler(req: any, type: any, name: any, alias: any, extra: any): Promise<{
|
|
32
|
+
_cacheControl: string;
|
|
33
|
+
_statusCode: number;
|
|
34
|
+
_mimeType: string;
|
|
35
|
+
_location: string;
|
|
36
|
+
_stream: any;
|
|
37
|
+
_body: any;
|
|
38
|
+
_etag: string;
|
|
39
|
+
cacheControl: string;
|
|
40
|
+
statusCode: number;
|
|
41
|
+
location: string;
|
|
42
|
+
mimeType: string;
|
|
43
|
+
stream: any;
|
|
44
|
+
body: any;
|
|
45
|
+
etag: string;
|
|
46
|
+
readonly [Symbol.toStringTag]: string;
|
|
47
|
+
}>;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
import abslog from "abslog";
|
|
51
|
+
import Metrics from "@metrics/client";
|
package/types/main.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ declare namespace http {
|
|
|
11
11
|
export { AliasPost };
|
|
12
12
|
export { AliasPut };
|
|
13
13
|
export { AliasGet };
|
|
14
|
+
export { AliasGetV2 };
|
|
14
15
|
export { AliasDel };
|
|
15
16
|
export { AuthPost };
|
|
16
17
|
export { PkgLog };
|
|
@@ -35,6 +36,7 @@ import VersionsGet from "./handlers/versions.get.js";
|
|
|
35
36
|
import AliasPost from "./handlers/alias.post.js";
|
|
36
37
|
import AliasPut from "./handlers/alias.put.js";
|
|
37
38
|
import AliasGet from "./handlers/alias.get.js";
|
|
39
|
+
import AliasGetV2 from "./handlers/alias.get-v2.js";
|
|
38
40
|
import AliasDel from "./handlers/alias.delete.js";
|
|
39
41
|
import AuthPost from "./handlers/auth.post.js";
|
|
40
42
|
import PkgLog from "./handlers/pkg.log.js";
|