@eik/core 1.3.53 → 1.3.55

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/lib/classes/alias.js +48 -48
  3. package/lib/classes/asset.js +99 -92
  4. package/lib/classes/author.js +20 -20
  5. package/lib/classes/http-incoming.js +52 -52
  6. package/lib/classes/http-outgoing.js +84 -83
  7. package/lib/classes/meta.js +20 -23
  8. package/lib/classes/package.js +73 -70
  9. package/lib/classes/versions.js +62 -60
  10. package/lib/handlers/alias.delete.js +125 -120
  11. package/lib/handlers/alias.get.js +92 -87
  12. package/lib/handlers/alias.post.js +196 -203
  13. package/lib/handlers/alias.put.js +196 -202
  14. package/lib/handlers/auth.post.js +95 -93
  15. package/lib/handlers/map.get.js +110 -111
  16. package/lib/handlers/map.put.js +256 -231
  17. package/lib/handlers/pkg.get.js +120 -122
  18. package/lib/handlers/pkg.log.js +112 -110
  19. package/lib/handlers/pkg.put.js +223 -213
  20. package/lib/handlers/versions.get.js +92 -101
  21. package/lib/main.js +47 -47
  22. package/lib/multipart/form-field.js +20 -23
  23. package/lib/multipart/form-file.js +22 -24
  24. package/lib/multipart/parser.js +231 -217
  25. package/lib/sinks/mem-entry.js +26 -31
  26. package/lib/sinks/test.js +287 -273
  27. package/lib/utils/defaults.js +11 -11
  28. package/lib/utils/globals.js +5 -5
  29. package/lib/utils/healthcheck.js +131 -108
  30. package/lib/utils/path-builders-fs.js +61 -29
  31. package/lib/utils/path-builders-uri.js +26 -18
  32. package/lib/utils/utils.js +76 -79
  33. package/package.json +22 -17
  34. package/types/classes/alias.d.ts +28 -0
  35. package/types/classes/asset.d.ts +48 -0
  36. package/types/classes/author.d.ts +17 -0
  37. package/types/classes/http-incoming.d.ts +37 -0
  38. package/types/classes/http-outgoing.d.ts +20 -0
  39. package/types/classes/meta.d.ts +17 -0
  40. package/types/classes/package.d.ts +40 -0
  41. package/types/classes/versions.d.ts +28 -0
  42. package/types/handlers/alias.delete.d.ts +33 -0
  43. package/types/handlers/alias.get.d.ts +48 -0
  44. package/types/handlers/alias.post.d.ts +83 -0
  45. package/types/handlers/alias.put.d.ts +83 -0
  46. package/types/handlers/auth.post.d.ts +82 -0
  47. package/types/handlers/map.get.d.ts +51 -0
  48. package/types/handlers/map.put.d.ts +78 -0
  49. package/types/handlers/pkg.get.d.ts +51 -0
  50. package/types/handlers/pkg.log.d.ts +51 -0
  51. package/types/handlers/pkg.put.d.ts +107 -0
  52. package/types/handlers/versions.get.d.ts +48 -0
  53. package/types/main.d.ts +44 -0
  54. package/types/multipart/form-field.d.ts +17 -0
  55. package/types/multipart/form-file.d.ts +17 -0
  56. package/types/multipart/parser.d.ts +52 -0
  57. package/types/sinks/mem-entry.d.ts +15 -0
  58. package/types/sinks/test.d.ts +32 -0
  59. package/types/utils/defaults.d.ts +9 -0
  60. package/types/utils/globals.d.ts +8 -0
  61. package/types/utils/healthcheck.d.ts +24 -0
  62. package/types/utils/path-builders-fs.d.ts +41 -0
  63. package/types/utils/path-builders-uri.d.ts +26 -0
  64. package/types/utils/utils.d.ts +6 -0
@@ -1,208 +1,202 @@
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';
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
6
 
7
7
  import {
8
- createFilePathToAlias,
9
- createFilePathToAliasOrigin
10
- } from '../utils/path-builders-fs.js';
11
- import { decodeUriComponent, writeJSON } from '../utils/utils.js';
12
- import { createURIToAlias } from '../utils/path-builders-uri.js';
13
- import MultipartParser from '../multipart/parser.js';
14
- import HttpIncoming from '../classes/http-incoming.js';
15
- import HttpOutgoing from '../classes/http-outgoing.js';
16
- import Author from '../classes/author.js';
17
- import Alias from '../classes/alias.js';
18
- import config from '../utils/defaults.js';
8
+ createFilePathToAlias,
9
+ createFilePathToAliasOrigin,
10
+ } from "../utils/path-builders-fs.js";
11
+ import { decodeUriComponent, writeJSON } from "../utils/utils.js";
12
+ import { createURIToAlias } from "../utils/path-builders-uri.js";
13
+ import MultipartParser from "../multipart/parser.js";
14
+ import HttpIncoming from "../classes/http-incoming.js";
15
+ import HttpOutgoing from "../classes/http-outgoing.js";
16
+ import Author from "../classes/author.js";
17
+ import Alias from "../classes/alias.js";
18
+ import config from "../utils/defaults.js";
19
+
20
+ /**
21
+ * @typedef {object} AliasPutOptions
22
+ * @property {string} [cacheControl]
23
+ * @property {Array<[string, string]>} [organizations] List of key-value pairs [hostname, organization]
24
+ * @property {import("@eik/sink").default} [sink]
25
+ * @property {import("abslog").AbstractLoggerOptions} [logger]
26
+ */
19
27
 
20
28
  const AliasPut = class AliasPut {
21
- constructor({
22
- organizations,
23
- cacheControl,
24
- logger,
25
- sink,
26
- } = {}) {
27
- this._organizations = organizations || config.organizations;
28
- this._cacheControl = cacheControl;
29
- this._sink = sink;
30
- this._log = abslog(logger);
31
- this._metrics = new Metrics();
32
- this._histogram = this._metrics.histogram({
33
- name: 'eik_core_alias_put_handler',
34
- description:
35
- 'Histogram measuring time taken in @eik/core AliasPut handler method',
36
- labels: {
37
- success: true,
38
- type: 'unknown',
39
- },
40
- buckets: [
41
- 0.005,
42
- 0.01,
43
- 0.06,
44
- 0.1,
45
- 0.6,
46
- 1.0,
47
- 2.0,
48
- 4.0,
49
- ],
50
- });
51
- this._orgRegistry = new Map(this._organizations);
52
-
53
- this._multipart = new MultipartParser({
54
- pkgMaxFileSize: this._pkgMaxFileSize,
55
- legalFields: ['version'],
56
- sink: this._sink,
57
- });
58
- }
59
-
60
- get metrics() {
61
- return this._metrics;
62
- }
63
-
64
- _parser(incoming) {
65
- return new Promise((resolve, reject) => {
66
- this._multipart
67
- .parse(incoming)
68
- .then((result) => {
69
- const obj = result[0];
70
- if (obj && obj.constructor.name === 'FormField') {
71
- try {
72
- validators.version(obj.value);
73
- } catch (error) {
74
- this._log.error(
75
- `alias:put - Input field could not be validated - Name: ${obj.name} - Value: ${obj.value}`,
76
- );
77
- this._log.trace(error);
78
- throw new HttpError.BadRequest();
79
- }
80
- const alias = new Alias(incoming);
81
- alias.version = obj.value;
82
- return alias;
83
- }
84
-
85
- throw new HttpError.BadRequest();
86
- })
87
- .then(async (alias) => {
88
- try {
89
- const path = createFilePathToAliasOrigin({
90
- org: alias.org,
91
- type: alias.type,
92
- name: alias.name,
93
- version: alias.version,
94
- })
95
- await this._sink.read(path);
96
- } catch (error) {
97
- this._log.error(
98
- `alias:post - Unable to locate requested published package version - Version ${alias.name}@${alias.version}`,
99
- );
100
- this._log.trace(error);
101
- throw new HttpError.NotFound();
102
- }
103
- return alias;
104
- })
105
- .then(async (alias) => {
106
- const path = createFilePathToAlias(incoming);
107
-
108
- this._log.info(
109
- `alias:put - Start writing alias to sink - Pathname: ${path}`,
110
- );
111
-
112
- try {
113
- await writeJSON(
114
- this._sink,
115
- path,
116
- alias,
117
- 'application/json',
118
- );
119
- } catch (error) {
120
- this._log.error(
121
- `alias:put - Failed writing alias to sink - Pathname: ${path}`,
122
- );
123
- this._log.trace(error);
124
- throw new HttpError.BadGateway();
125
- }
126
-
127
- this._log.info(
128
- `alias:put - Successfully wrote alias to sink - Pathname: ${path}`,
129
- );
130
-
131
- resolve(alias);
132
- })
133
- .catch((error) => {
134
- reject(error);
135
- });
136
- });
137
- }
138
-
139
- async _exist (incoming) {
140
- try {
141
- const path = createFilePathToAlias(incoming);
142
- await this._sink.exist(path);
143
- return true;
144
- } catch (error) {
145
- return false;
146
- }
147
- }
148
-
149
- async handler(req, user, type, name, alias) {
150
- const end = this._histogram.timer();
151
-
152
- const pAlias = decodeUriComponent(alias);
153
- const pName = decodeUriComponent(name);
154
-
155
- try {
156
- validators.alias(pAlias);
157
- validators.name(pName);
158
- validators.type(type);
159
- } catch (error) {
160
- this._log.info(`alias:put - Validation failed - ${error.message}`);
161
- const e = new HttpError.BadRequest();
162
- end({ labels: { success: false, status: e.status } });
163
- throw e;
164
- }
165
-
166
- const url = originalUrl(req);
167
- const org = this._orgRegistry.get(url.hostname);
168
-
169
- if (!org) {
170
- this._log.info(`alias:put - Hostname does not match a configured organization - ${url.hostname}`);
171
- const e = new HttpError.BadRequest();
172
- end({ labels: { success: false, status: e.status, type } });
173
- throw e;
174
- }
175
-
176
- const author = new Author(user);
177
-
178
- const incoming = new HttpIncoming(req, {
179
- author,
180
- alias: pAlias,
181
- name: pName,
182
- type,
183
- org,
184
- });
185
-
186
- const exist = await this._exist(incoming);
187
- if (exist) {
188
- this._log.info(
189
- `alias:put - Alias exists - Org: ${org} - Type: ${type} - Name: ${pName} - Alias: ${pAlias}`,
190
- );
191
- const e = new HttpError.Conflict();
192
- end({ labels: { success: false, status: e.status, type } });
193
- throw e;
194
- }
195
-
196
- await this._parser(incoming);
197
-
198
- const outgoing = new HttpOutgoing();
199
- outgoing.cacheControl = this._cacheControl;
200
- outgoing.statusCode = 303;
201
- outgoing.location = createURIToAlias(incoming);
202
-
203
- end({ labels: { status: outgoing.statusCode, type } });
204
-
205
- return outgoing;
206
- }
29
+ /**
30
+ * @param {AliasPutOptions} options
31
+ */
32
+ constructor({ organizations, cacheControl, logger, sink } = {}) {
33
+ this._organizations = organizations || config.organizations;
34
+ this._cacheControl = cacheControl;
35
+ this._sink = sink;
36
+ this._log = abslog(logger);
37
+ this._metrics = new Metrics();
38
+ this._histogram = this._metrics.histogram({
39
+ name: "eik_core_alias_put_handler",
40
+ description:
41
+ "Histogram measuring time taken in @eik/core AliasPut 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
+ this._multipart = new MultipartParser({
51
+ legalFields: ["version"],
52
+ sink: this._sink,
53
+ });
54
+ }
55
+
56
+ get metrics() {
57
+ return this._metrics;
58
+ }
59
+
60
+ _parser(incoming) {
61
+ return new Promise((resolve, reject) => {
62
+ this._multipart
63
+ .parse(incoming)
64
+ .then((result) => {
65
+ const obj = result[0];
66
+ if (obj && obj.constructor.name === "FormField") {
67
+ try {
68
+ validators.version(obj.value);
69
+ } catch (error) {
70
+ this._log.error(
71
+ `alias:put - Input field could not be validated - Name: ${obj.name} - Value: ${obj.value}`,
72
+ );
73
+ this._log.trace(error);
74
+ throw new HttpError.BadRequest();
75
+ }
76
+ const alias = new Alias(incoming);
77
+ alias.version = obj.value;
78
+ return alias;
79
+ }
80
+
81
+ throw new HttpError.BadRequest();
82
+ })
83
+ .then(async (alias) => {
84
+ try {
85
+ const path = createFilePathToAliasOrigin({
86
+ org: alias.org,
87
+ type: alias.type,
88
+ name: alias.name,
89
+ version: alias.version,
90
+ });
91
+ await this._sink.read(path);
92
+ } catch (error) {
93
+ this._log.error(
94
+ `alias:post - Unable to locate requested published package version - Version ${alias.name}@${alias.version}`,
95
+ );
96
+ this._log.trace(error);
97
+ throw new HttpError.NotFound();
98
+ }
99
+ return alias;
100
+ })
101
+ .then(async (alias) => {
102
+ const path = createFilePathToAlias(incoming);
103
+
104
+ this._log.info(
105
+ `alias:put - Start writing alias to sink - Pathname: ${path}`,
106
+ );
107
+
108
+ try {
109
+ await writeJSON(this._sink, path, alias, "application/json");
110
+ } catch (error) {
111
+ this._log.error(
112
+ `alias:put - Failed writing alias to sink - Pathname: ${path}`,
113
+ );
114
+ this._log.trace(error);
115
+ throw new HttpError.BadGateway();
116
+ }
117
+
118
+ this._log.info(
119
+ `alias:put - Successfully wrote alias to sink - Pathname: ${path}`,
120
+ );
121
+
122
+ resolve(alias);
123
+ })
124
+ .catch((error) => {
125
+ reject(error);
126
+ });
127
+ });
128
+ }
129
+
130
+ async _exist(incoming) {
131
+ try {
132
+ const path = createFilePathToAlias(incoming);
133
+ await this._sink.exist(path);
134
+ return true;
135
+ // eslint-disable-next-line no-unused-vars
136
+ } catch (error) {
137
+ return false;
138
+ }
139
+ }
140
+
141
+ async handler(req, user, type, name, alias) {
142
+ const end = this._histogram.timer();
143
+
144
+ const pAlias = decodeUriComponent(alias);
145
+ const pName = decodeUriComponent(name);
146
+
147
+ try {
148
+ validators.alias(pAlias);
149
+ validators.name(pName);
150
+ validators.type(type);
151
+ } catch (error) {
152
+ this._log.info(`alias:put - Validation failed - ${error.message}`);
153
+ const e = new HttpError.BadRequest();
154
+ end({ labels: { success: false, status: e.status } });
155
+ throw e;
156
+ }
157
+
158
+ const url = originalUrl(req);
159
+ const org = this._orgRegistry.get(url.hostname);
160
+
161
+ if (!org) {
162
+ this._log.info(
163
+ `alias:put - Hostname does not match a configured organization - ${url.hostname}`,
164
+ );
165
+ const e = new HttpError.BadRequest();
166
+ end({ labels: { success: false, status: e.status, type } });
167
+ throw e;
168
+ }
169
+
170
+ const author = new Author(user);
171
+
172
+ const incoming = new HttpIncoming(req, {
173
+ author,
174
+ alias: pAlias,
175
+ name: pName,
176
+ type,
177
+ org,
178
+ });
179
+
180
+ const exist = await this._exist(incoming);
181
+ if (exist) {
182
+ this._log.info(
183
+ `alias:put - Alias exists - Org: ${org} - Type: ${type} - Name: ${pName} - Alias: ${pAlias}`,
184
+ );
185
+ const e = new HttpError.Conflict();
186
+ end({ labels: { success: false, status: e.status, type } });
187
+ throw e;
188
+ }
189
+
190
+ await this._parser(incoming);
191
+
192
+ const outgoing = new HttpOutgoing();
193
+ outgoing.cacheControl = this._cacheControl;
194
+ outgoing.statusCode = 303;
195
+ outgoing.location = createURIToAlias(incoming);
196
+
197
+ end({ labels: { status: outgoing.statusCode, type } });
198
+
199
+ return outgoing;
200
+ }
207
201
  };
208
202
  export default AliasPut;
@@ -1,109 +1,111 @@
1
- import originalUrl from 'original-url';
2
- import HttpError from 'http-errors';
3
- import Metrics from '@metrics/client';
4
- import abslog from 'abslog';
1
+ import originalUrl from "original-url";
2
+ import HttpError from "http-errors";
3
+ import Metrics from "@metrics/client";
4
+ import abslog from "abslog";
5
5
 
6
- import MultipartParser from '../multipart/parser.js';
7
- import HttpIncoming from '../classes/http-incoming.js';
8
- import HttpOutgoing from '../classes/http-outgoing.js';
9
- import Author from '../classes/author.js';
10
- import config from '../utils/defaults.js';
6
+ import MultipartParser from "../multipart/parser.js";
7
+ import HttpIncoming from "../classes/http-incoming.js";
8
+ import HttpOutgoing from "../classes/http-outgoing.js";
9
+ import Author from "../classes/author.js";
10
+ import config from "../utils/defaults.js";
11
+
12
+ /**
13
+ * @typedef {object} AuthPostOptions
14
+ * @property {string} [authKey]
15
+ * @property {string} [cacheControl]
16
+ * @property {Array<[string, string]>} [organizations] List of key-value pairs [hostname, organization]
17
+ * @property {import("abslog").AbstractLoggerOptions} [logger]
18
+ */
11
19
 
12
20
  const AuthPost = class AuthPost {
13
- constructor({
14
- organizations,
15
- cacheControl,
16
- authKey,
17
- logger,
18
- } = {}) {
19
- this._organizations = organizations || config.organizations;
20
- this._cacheControl = cacheControl;
21
- this._authKey = authKey || config.authKey;
22
- this._log = abslog(logger);
23
- this._metrics = new Metrics();
24
- this._histogram = this._metrics.histogram({
25
- name: 'eik_core_auth_post_handler',
26
- description:
27
- 'Histogram measuring time taken in @eik/core AuthPost handler method',
28
- labels: {
29
- success: true,
30
- type: 'unknown',
31
- },
32
- buckets: [
33
- 0.005,
34
- 0.01,
35
- 0.06,
36
- 0.1,
37
- 0.6,
38
- 1.0,
39
- 2.0,
40
- 4.0,
41
- ],
42
- });
43
- this._orgRegistry = new Map(this._organizations);
21
+ /**
22
+ * @param {AuthPostOptions} options
23
+ */
24
+ constructor({ organizations, cacheControl, authKey, logger } = {}) {
25
+ this._organizations = organizations || config.organizations;
26
+ this._cacheControl = cacheControl;
27
+ this._authKey = authKey || config.authKey;
28
+ this._log = abslog(logger);
29
+ this._metrics = new Metrics();
30
+ this._histogram = this._metrics.histogram({
31
+ name: "eik_core_auth_post_handler",
32
+ description:
33
+ "Histogram measuring time taken in @eik/core AuthPost handler method",
34
+ labels: {
35
+ success: true,
36
+ type: "unknown",
37
+ },
38
+ buckets: [0.005, 0.01, 0.06, 0.1, 0.6, 1.0, 2.0, 4.0],
39
+ });
40
+ this._orgRegistry = new Map(this._organizations);
44
41
 
45
- this._multipart = new MultipartParser({
46
- pkgMaxFileSize: this._pkgMaxFileSize,
47
- legalFields: ['key'],
48
- sink: this._sink,
49
- });
50
- }
42
+ this._multipart = new MultipartParser({
43
+ legalFields: ["key"],
44
+ });
45
+ }
51
46
 
52
- get metrics() {
53
- return this._metrics;
54
- }
47
+ get metrics() {
48
+ return this._metrics;
49
+ }
55
50
 
56
- _parser(incoming) {
57
- return new Promise((resolve, reject) => {
58
- this._multipart.parse(incoming).then((result) => {
59
- const obj = result[0];
60
- if (obj && obj.constructor.name === 'FormField') {
61
- if (obj.value !== this._authKey) {
62
- this._log.info(`auth:post - Auth submitted an illegal key: ${obj.value}`);
63
- throw new HttpError.Unauthorized();
64
- }
65
- const author = new Author({
66
- user: 'generic_user',
67
- name: 'Generic User',
68
- });
69
- resolve(author);
70
- return;
71
- }
72
- throw new HttpError.BadRequest();
73
- }).catch((error) => {
74
- reject(error);
75
- });
76
- });
77
- }
51
+ _parser(incoming) {
52
+ return new Promise((resolve, reject) => {
53
+ this._multipart
54
+ .parse(incoming)
55
+ .then((result) => {
56
+ const obj = result[0];
57
+ if (obj && obj.constructor.name === "FormField") {
58
+ if (obj.value !== this._authKey) {
59
+ this._log.info(
60
+ `auth:post - Auth submitted an illegal key: ${obj.value}`,
61
+ );
62
+ throw new HttpError.Unauthorized();
63
+ }
64
+ const author = new Author({
65
+ user: "generic_user",
66
+ name: "Generic User",
67
+ });
68
+ resolve(author);
69
+ return;
70
+ }
71
+ throw new HttpError.BadRequest();
72
+ })
73
+ .catch((error) => {
74
+ reject(error);
75
+ });
76
+ });
77
+ }
78
78
 
79
- async handler(req) {
80
- const end = this._histogram.timer();
79
+ async handler(req) {
80
+ const end = this._histogram.timer();
81
81
 
82
- const url = originalUrl(req);
83
- const org = this._orgRegistry.get(url.hostname);
82
+ const url = originalUrl(req);
83
+ const org = this._orgRegistry.get(url.hostname);
84
84
 
85
- if (!org) {
86
- this._log.info(`auth:post - Hostname does not match a configured organization - ${url.hostname}`);
87
- const e = new HttpError.BadRequest();
88
- end({ labels: { success: false, status: e.status, type: 'auth' } });
89
- throw e;
90
- }
85
+ if (!org) {
86
+ this._log.info(
87
+ `auth:post - Hostname does not match a configured organization - ${url.hostname}`,
88
+ );
89
+ const e = new HttpError.BadRequest();
90
+ end({ labels: { success: false, status: e.status, type: "auth" } });
91
+ throw e;
92
+ }
91
93
 
92
- const incoming = new HttpIncoming(req, {
93
- org,
94
- });
94
+ const incoming = new HttpIncoming(req, {
95
+ org,
96
+ });
95
97
 
96
- const obj = await this._parser(incoming);
98
+ const obj = await this._parser(incoming);
97
99
 
98
- const outgoing = new HttpOutgoing();
99
- outgoing.cacheControl = this._cacheControl;
100
- outgoing.statusCode = 200;
101
- outgoing.mimeType = 'application/json';
102
- outgoing.body = obj;
100
+ const outgoing = new HttpOutgoing();
101
+ outgoing.cacheControl = this._cacheControl;
102
+ outgoing.statusCode = 200;
103
+ outgoing.mimeType = "application/json";
104
+ outgoing.body = obj;
103
105
 
104
- end({ labels: { status: outgoing.statusCode, type: 'auth' } });
106
+ end({ labels: { status: outgoing.statusCode, type: "auth" } });
105
107
 
106
- return outgoing;
107
- }
108
+ return outgoing;
109
+ }
108
110
  };
109
111
  export default AuthPost;