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