@eik/core 1.3.46 → 1.3.48

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 CHANGED
@@ -1,3 +1,17 @@
1
+ ## [1.3.48](https://github.com/eik-lib/core/compare/v1.3.47...v1.3.48) (2024-07-29)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * migrate to using sink modules ([0101d50](https://github.com/eik-lib/core/commit/0101d502365e304baa5e5583e13c29ca7b345b67))
7
+
8
+ ## [1.3.47](https://github.com/eik-lib/core/compare/v1.3.46...v1.3.47) (2024-07-06)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **deps:** update dependency rimraf to v5.0.8 ([daf2655](https://github.com/eik-lib/core/commit/daf26550d1d38d1b715c78213cde885e272a3893))
14
+
1
15
  ## [1.3.46](https://github.com/eik-lib/core/compare/v1.3.45...v1.3.46) (2024-07-03)
2
16
 
3
17
 
package/lib/main.js CHANGED
@@ -1,3 +1,6 @@
1
+ import FS from '@eik/sink-file-system';
2
+ import MEM from '@eik/sink-memory';
3
+
1
4
  import VersionsGet from './handlers/versions.get.js';
2
5
  import AliasPost from './handlers/alias.post.js';
3
6
  import AliasPut from './handlers/alias.put.js';
@@ -11,8 +14,6 @@ import MapGet from './handlers/map.get.js';
11
14
  import MapPut from './handlers/map.put.js';
12
15
 
13
16
  import TEST from './sinks/test.js';
14
- import MEM from './sinks/mem.js';
15
- import FS from './sinks/fs.js';
16
17
 
17
18
  import HealthCheck from './utils/healthcheck.js';
18
19
  import globals from './utils/globals.js';
@@ -31,9 +32,23 @@ const http = {
31
32
  MapPut,
32
33
  };
33
34
 
35
+ /**
36
+ * @deprecated The built-in sinks will be removed in a future version of core.
37
+ * Install the sink you want as a dependency and pass it as an option when constructing the Service.
38
+ * Ex: sink.MEM is replaced by eik/sink-memory. sink.FS is replaced by eik/sink-file-system.
39
+ */
34
40
  const sink = {
41
+ /**
42
+ * @deprecated Import eik/sink-memory or implement your own and pass it to the Service instead.
43
+ */
35
44
  TEST,
45
+ /**
46
+ * @deprecated Import eik/sink-memory and pass it to the Service instead
47
+ */
36
48
  MEM,
49
+ /**
50
+ * @deprecated Import eik/sink-file-system and pass it to the Service instead
51
+ */
37
52
  FS,
38
53
  };
39
54
 
@@ -49,4 +64,4 @@ export default {
49
64
  http,
50
65
  sink,
51
66
  prop,
52
- }
67
+ };
package/lib/sinks/test.js CHANGED
@@ -9,7 +9,10 @@ import Entry from './mem-entry.js';
9
9
 
10
10
  const DEFAULT_ROOT_PATH = '/eik';
11
11
 
12
- const SinkTest = class SinkTest extends Sink {
12
+ /**
13
+ * @deprecated Use eik/sink-memory or implement your own. This class will be removed in a future version of core.
14
+ */
15
+ export default class SinkTest extends Sink {
13
16
  constructor({ rootPath = DEFAULT_ROOT_PATH } = {}) {
14
17
  super();
15
18
  this._rootPath = rootPath;
@@ -134,10 +137,10 @@ const SinkTest = class SinkTest extends Sink {
134
137
 
135
138
  this._state.set(pathname, entry);
136
139
 
137
- this._counter.inc({ labels: {
138
- success: true,
139
- access: true,
140
- operation
140
+ this._counter.inc({ labels: {
141
+ success: true,
142
+ access: true,
143
+ operation
141
144
  } });
142
145
  });
143
146
 
@@ -189,10 +192,10 @@ const SinkTest = class SinkTest extends Sink {
189
192
  });
190
193
 
191
194
  file.stream.on('end', () => {
192
- this._counter.inc({ labels: {
193
- success: true,
194
- access: true,
195
- operation
195
+ this._counter.inc({ labels: {
196
+ success: true,
197
+ access: true,
198
+ operation
196
199
  } });
197
200
  });
198
201
 
@@ -227,10 +230,10 @@ const SinkTest = class SinkTest extends Sink {
227
230
  }
228
231
  });
229
232
 
230
- this._counter.inc({ labels: {
231
- success: true,
232
- access: true,
233
- operation
233
+ this._counter.inc({ labels: {
234
+ success: true,
235
+ access: true,
236
+ operation
234
237
  } });
235
238
 
236
239
  resolve();
@@ -257,10 +260,10 @@ const SinkTest = class SinkTest extends Sink {
257
260
  return;
258
261
  }
259
262
 
260
- this._counter.inc({ labels: {
261
- success: true,
262
- access: true,
263
- operation
263
+ this._counter.inc({ labels: {
264
+ success: true,
265
+ access: true,
266
+ operation
264
267
  } });
265
268
 
266
269
  if (this._state.has(pathname)) {
@@ -276,5 +279,3 @@ const SinkTest = class SinkTest extends Sink {
276
279
  return 'SinkTest';
277
280
  }
278
281
  }
279
-
280
- export default SinkTest;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eik/core",
3
- "version": "1.3.46",
3
+ "version": "1.3.48",
4
4
  "description": "Core server package",
5
5
  "main": "lib/main.js",
6
6
  "type": "module",
@@ -21,13 +21,15 @@
21
21
  "dependencies": {
22
22
  "@eik/common": "3.0.1",
23
23
  "@eik/sink": "1.2.1",
24
+ "@eik/sink-file-system": "1.0.1",
25
+ "@eik/sink-memory": "1.1.1",
24
26
  "@metrics/client": "2.5.2",
25
27
  "abslog": "2.4.4",
26
28
  "busboy": "1.6.0",
27
29
  "http-errors": "2.0.0",
28
30
  "mime": "3.0.0",
29
31
  "original-url": "1.2.3",
30
- "rimraf": "5.0.7",
32
+ "rimraf": "5.0.8",
31
33
  "semver": "7.6.2",
32
34
  "ssri": "10.0.6",
33
35
  "tar": "6.2.1",
package/lib/sinks/fs.js DELETED
@@ -1,263 +0,0 @@
1
- import { ReadFile } from '@eik/common';
2
- import { rimraf } from 'rimraf';
3
- import Metrics from '@metrics/client';
4
- import Sink from '@eik/sink';
5
- import mime from 'mime';
6
- import path from 'node:path';
7
- import fs from 'node:fs';
8
-
9
- import { etagFromFsStat } from '../utils/utils.js';
10
- import conf from '../utils/defaults.js';
11
-
12
- /**
13
- * A sink for persisting files to local file system
14
- *
15
- * @class SinkFS
16
- */
17
-
18
- const SinkFS = class SinkFS extends Sink {
19
- constructor(config = {}) {
20
- super();
21
- this._config = { ...conf, ...config};
22
- this._metrics = new Metrics();
23
- this._counter = this._metrics.counter({
24
- name: 'eik_core_sink_fs',
25
- description: 'Counter measuring access to the file system storage sink',
26
- labels: {
27
- operation: 'n/a',
28
- success: false,
29
- access: false,
30
- },
31
- });
32
- }
33
-
34
- get metrics() {
35
- return this._metrics;
36
- }
37
-
38
- write(filePath, contentType) {
39
- return new Promise((resolve, reject) => {
40
- const operation = 'write';
41
-
42
- try {
43
- super.constructor.validateFilePath(filePath);
44
- super.constructor.validateContentType(contentType);
45
- } catch (error) {
46
- this._counter.inc({ labels: { operation } });
47
- reject(error);
48
- return;
49
- }
50
-
51
- const pathname = path.join(this._config.sinkFsRootPath, filePath);
52
-
53
- if (pathname.indexOf(this._config.sinkFsRootPath) !== 0) {
54
- this._counter.inc({ labels: { operation } });
55
- reject(new Error(`Directory traversal - ${filePath}`));
56
- return;
57
- }
58
-
59
- const dir = path.dirname(pathname);
60
-
61
- fs.mkdir(
62
- dir,
63
- {
64
- recursive: true,
65
- },
66
- error => {
67
- if (error) {
68
- this._counter.inc({ labels: { access: true, operation } });
69
- reject(
70
- new Error(`Could not create directory - ${dir}`),
71
- );
72
- return;
73
- }
74
-
75
- const stream = fs.createWriteStream(pathname, {
76
- autoClose: true,
77
- emitClose: true,
78
- });
79
-
80
- this._counter.inc({ labels: {
81
- success: true,
82
- access: true,
83
- operation
84
- } });
85
-
86
- resolve(stream);
87
- },
88
- );
89
- });
90
- }
91
-
92
- read(filePath) {
93
- return new Promise((resolve, reject) => {
94
- const operation = 'read';
95
-
96
- try {
97
- super.constructor.validateFilePath(filePath);
98
- } catch (error) {
99
- this._counter.inc({ labels: { operation } });
100
- reject(error);
101
- return;
102
- }
103
-
104
- const pathname = path.join(this._config.sinkFsRootPath, filePath);
105
-
106
- if (pathname.indexOf(this._config.sinkFsRootPath) !== 0) {
107
- this._counter.inc({ labels: { operation } });
108
- reject(new Error(`Directory traversal - ${filePath}`));
109
- return;
110
- }
111
-
112
- const closeFd = fd => {
113
- fs.close(fd, (error) => {
114
- if (error) {
115
- this._counter.inc({ labels: {
116
- access: true,
117
- operation
118
- } });
119
- return;
120
- }
121
- this._counter.inc({ labels: {
122
- success: true,
123
- access: true,
124
- operation
125
- } });
126
- });
127
- }
128
-
129
- fs.open(pathname, 'r', (error, fd) => {
130
- if (error) {
131
- this._counter.inc({ labels: {
132
- access: true,
133
- operation
134
- } });
135
- reject(error);
136
- return;
137
- };
138
-
139
- fs.fstat(fd, (err, stat) => {
140
- if (err) {
141
- closeFd(fd);
142
- reject(err);
143
- return;
144
- };
145
-
146
- if (!stat.isFile()) {
147
- closeFd(fd);
148
- reject(new Error(`Not a file - ${pathname}`));
149
- return;
150
- }
151
-
152
- const mimeType = mime.getType(pathname) || 'application/octet-stream';
153
- const etag = etagFromFsStat(stat);
154
-
155
- const obj = new ReadFile({
156
- mimeType,
157
- etag,
158
- });
159
-
160
- obj.stream = fs.createReadStream(pathname, {
161
- autoClose: true,
162
- fd,
163
- });
164
-
165
- obj.stream.on('error', () => {
166
- this._counter.inc({ labels: {
167
- access: true,
168
- operation
169
- } });
170
- });
171
-
172
- obj.stream.on('end', () => {
173
- this._counter.inc({ labels: {
174
- success: true,
175
- access: true,
176
- operation
177
- } });
178
- });
179
-
180
- resolve(obj);
181
- });
182
-
183
- });
184
- });
185
- }
186
-
187
- delete(filePath) {
188
- return new Promise((resolve, reject) => {
189
- const operation = 'delete';
190
-
191
- try {
192
- super.constructor.validateFilePath(filePath);
193
- } catch (error) {
194
- this._counter.inc({ labels: { operation } });
195
- reject(error);
196
- return;
197
- }
198
-
199
- const pathname = path.join(this._config.sinkFsRootPath, filePath);
200
-
201
- if (pathname.indexOf(this._config.sinkFsRootPath) !== 0) {
202
- this._counter.inc({ labels: { operation } });
203
- reject(new Error(`Directory traversal - ${filePath}`));
204
- return;
205
- }
206
-
207
- rimraf(pathname).then(() => {
208
- this._counter.inc({ labels: {
209
- success: true,
210
- access: true,
211
- operation
212
- } });
213
- resolve();
214
- }).catch((error) => {
215
- this._counter.inc({ labels: { access: true, operation } });
216
- reject(error);
217
-
218
- });
219
- });
220
- }
221
-
222
- exist(filePath) {
223
- return new Promise((resolve, reject) => {
224
- const operation = 'exist';
225
-
226
- try {
227
- super.constructor.validateFilePath(filePath);
228
- } catch (error) {
229
- this._counter.inc({ labels: { operation } });
230
- reject(error);
231
- return;
232
- }
233
-
234
- const pathname = path.join(this._config.sinkFsRootPath, filePath);
235
-
236
- if (pathname.indexOf(this._config.sinkFsRootPath) !== 0) {
237
- this._counter.inc({ labels: { operation } });
238
- reject(new Error(`Directory traversal - ${filePath}`));
239
- return;
240
- }
241
-
242
- fs.stat(pathname, (error, stat) => {
243
- this._counter.inc({ labels: { success: true, access: true, operation } });
244
-
245
- if (stat && stat.isFile()) {
246
- resolve();
247
- return;
248
- }
249
-
250
- if (error) {
251
- reject(error);
252
- return;
253
- }
254
- reject();
255
- });
256
- });
257
- }
258
-
259
- get [Symbol.toStringTag]() {
260
- return 'SinkFS';
261
- }
262
- }
263
- export default SinkFS;
package/lib/sinks/mem.js DELETED
@@ -1,210 +0,0 @@
1
- import { Writable, Readable } from 'node:stream';
2
- import { ReadFile } from '@eik/common';
3
- import { join } from 'node:path';
4
- import Metrics from '@metrics/client';
5
- import Sink from '@eik/sink';
6
-
7
- import Entry from './mem-entry.js';
8
-
9
- const DEFAULT_ROOT_PATH = '/eik';
10
-
11
- /**
12
- * A sink for persisting files to memory
13
- *
14
- * @class SinkMem
15
- */
16
-
17
- const SinkMem = class SinkMem extends Sink {
18
- constructor({ rootPath = DEFAULT_ROOT_PATH } = {}) {
19
- super();
20
- this._rootPath = rootPath;
21
- this._metrics = new Metrics();
22
- this._counter = this._metrics.counter({
23
- name: 'eik_core_sink_mem',
24
- description: 'Counter measuring access to the in memory storage sink',
25
- labels: {
26
- operation: 'n/a',
27
- success: false,
28
- access: false,
29
- },
30
- });
31
- this._state = new Map();
32
- }
33
-
34
- get metrics() {
35
- return this._metrics;
36
- }
37
-
38
- write(filePath, contentType) {
39
- return new Promise((resolve, reject) => {
40
- const operation = 'write';
41
-
42
- try {
43
- super.constructor.validateFilePath(filePath);
44
- super.constructor.validateContentType(contentType);
45
- } catch (error) {
46
- this._counter.inc({ labels: { operation } });
47
- reject(error);
48
- return;
49
- }
50
-
51
- const pathname = join(this._rootPath, filePath);
52
-
53
- if (pathname.indexOf(this._rootPath) !== 0) {
54
- reject(new Error(`Directory traversal - ${filePath}`));
55
- this._counter.inc({ labels: { operation } });
56
- return;
57
- }
58
-
59
- const payload = [];
60
- const stream = new Writable({
61
- write(chunk, encoding, cb) {
62
- payload.push(chunk);
63
- cb();
64
- },
65
- });
66
-
67
- stream.on('finish', () => {
68
- const entry = new Entry({
69
- mimeType: contentType,
70
- payload
71
- });
72
-
73
- this._state.set(pathname, entry);
74
-
75
- this._counter.inc({ labels: {
76
- success: true,
77
- access: true,
78
- operation
79
- } });
80
- });
81
-
82
- resolve(stream);
83
- });
84
- }
85
-
86
- read(filePath) {
87
- return new Promise((resolve, reject) => {
88
- const operation = 'read';
89
-
90
- try {
91
- super.constructor.validateFilePath(filePath);
92
- } catch (error) {
93
- this._counter.inc({ labels: { operation } });
94
- reject(error);
95
- return;
96
- }
97
-
98
- const pathname = join(this._rootPath, filePath);
99
-
100
- if (pathname.indexOf(this._rootPath) !== 0) {
101
- this._counter.inc({ labels: { operation } });
102
- reject(new Error(`Directory traversal - ${filePath}`));
103
- return;
104
- }
105
-
106
- const entry = this._state.get(pathname);
107
- const payload = entry.payload || [];
108
- const obj = new ReadFile( {
109
- mimeType: entry.mimeType,
110
- etag: entry.hash,
111
- });
112
-
113
- obj.stream = new Readable({
114
- read() {
115
- payload.forEach(item => {
116
- this.push(item);
117
- });
118
- this.push(null);
119
- },
120
- });
121
-
122
- obj.stream.on('end', () => {
123
- this._counter.inc({ labels: {
124
- success: true,
125
- access: true,
126
- operation
127
- } });
128
- });
129
-
130
- resolve(obj);
131
- });
132
- }
133
-
134
- delete(filePath) {
135
- return new Promise((resolve, reject) => {
136
- const operation = 'delete';
137
-
138
- try {
139
- super.constructor.validateFilePath(filePath);
140
- } catch (error) {
141
- this._counter.inc({ labels: { operation } });
142
- reject(error);
143
- return;
144
- }
145
-
146
- const pathname = join(this._rootPath, filePath);
147
-
148
- if (pathname.indexOf(this._rootPath) !== 0) {
149
- this._counter.inc({ labels: { operation } });
150
- reject(new Error(`Directory traversal - ${filePath}`));
151
- return;
152
- }
153
-
154
- // Delete recursively
155
- Array.from(this._state.keys()).forEach((key) => {
156
- if (key.startsWith(pathname)) {
157
- this._state.delete(key);
158
- }
159
- });
160
-
161
- this._counter.inc({ labels: {
162
- success: true,
163
- access: true,
164
- operation
165
- } });
166
-
167
- resolve();
168
- });
169
- }
170
-
171
- exist(filePath) {
172
- return new Promise((resolve, reject) => {
173
- const operation = 'exist';
174
-
175
- try {
176
- super.constructor.validateFilePath(filePath);
177
- } catch (error) {
178
- this._counter.inc({ labels: { operation } });
179
- reject(error);
180
- return;
181
- }
182
-
183
- const pathname = join(this._rootPath, filePath);
184
-
185
- if (pathname.indexOf(this._rootPath) !== 0) {
186
- this._counter.inc({ labels: { operation } });
187
- reject(new Error(`Directory traversal - ${filePath}`));
188
- return;
189
- }
190
-
191
- this._counter.inc({ labels: {
192
- success: true,
193
- access: true,
194
- operation
195
- } });
196
-
197
- if (this._state.has(pathname)) {
198
- resolve();
199
- return;
200
- }
201
-
202
- reject(new Error('File does not exist'));
203
- });
204
- }
205
-
206
- get [Symbol.toStringTag]() {
207
- return 'SinkMEM';
208
- }
209
- }
210
- export default SinkMem;