@eik/service 3.0.0 → 5.0.0

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/lib/main.js CHANGED
@@ -1,15 +1,16 @@
1
- import { PassThrough } from 'stream';
2
- import compression from '@fastify/compress';
3
- import createError from 'http-errors';
4
- import pino from 'pino';
5
- import cors from '@fastify/cors';
6
- import jwt from '@fastify/jwt';
7
- import eik from '@eik/core';
8
- import SinkMemory from '@eik/sink-memory';
9
- import SinkFileSystem from '@eik/sink-file-system';
10
-
11
- import config from './config.js';
12
- import * as utils from './utils.js';
1
+ import { PassThrough } from "stream";
2
+ import compression from "@fastify/compress";
3
+ import createError from "http-errors";
4
+ import pino from "pino";
5
+ import cors from "@fastify/cors";
6
+ import jwt from "@fastify/jwt";
7
+ import eik from "@eik/core";
8
+ import SinkMemory from "@eik/sink-memory";
9
+ import SinkFileSystem from "@eik/sink-file-system";
10
+ import zlib from "node:zlib";
11
+
12
+ import config from "./config.js";
13
+ import * as utils from "./utils.js";
13
14
 
14
15
  /**
15
16
  * @typedef {object} EikServiceOptions
@@ -24,891 +25,833 @@ import * as utils from './utils.js';
24
25
  */
25
26
 
26
27
  const EikService = class EikService {
27
- /**
28
- * @param {EikServiceOptions} [options={}]
29
- */
30
- constructor(options = {}) {
31
- let { sink, logger } = options;
32
- const {
33
- customSink,
34
- notFoundCacheControl,
35
- aliasCacheControl,
36
- pkgMaxFileSize = 10000000,
37
- mapMaxFileSize = 1000000,
38
- imgMaxFileSize = 20000000,
39
- } = options;
40
- this._notFoundCacheControl =
41
- notFoundCacheControl || 'public, max-age=5';
42
-
43
- if (!logger) {
44
- // @ts-expect-error This is in fact callable
45
- logger = pino({
46
- // @ts-ignore
47
- level: config.get('log.level'),
48
- name: config.get('name'),
49
- });
50
- }
51
-
52
- if (sink) {
53
- logger.info(`Using the provided sink ${sink.constructor.name}`);
54
- } else if (customSink) {
55
- logger.warn(
56
- 'The `customSink` option is deprecated and will be removed at a later stage. Use `sink` to remove this warning.',
57
- );
58
- sink = customSink;
59
- } else if (config.get('sink.type') === 'mem') {
60
- logger.info(
61
- `Server is running with a in memory sink. Uploaded files will be lost on restart!`,
62
- );
63
- sink = new SinkMemory();
64
- } else {
65
- logger.info(
66
- `Server is running with the file system sink. Uploaded files will be stored under "${config.get('sink.path')}"`,
67
- );
68
- sink = new SinkFileSystem({
69
- sinkFsRootPath: config.get('sink.path'),
70
- });
71
- }
72
-
73
- // Transform organization config
74
- const organizations = config
75
- .get('organization.hostnames')
76
- .map((hostname) => [hostname, config.get('organization.name')]);
77
-
78
- this._versionsGet = new eik.http.VersionsGet({
79
- organizations,
80
- sink,
81
- logger,
82
- });
83
- this._aliasPost = new eik.http.AliasPost({
84
- organizations,
85
- sink,
86
- logger,
87
- });
88
- this._aliasDel = new eik.http.AliasDel({ organizations, sink, logger });
89
- this._aliasGet = new eik.http.AliasGet({
90
- organizations,
91
- sink,
92
- logger,
93
- cacheControl: aliasCacheControl,
94
- });
95
- this._aliasPut = new eik.http.AliasPut({ organizations, sink, logger });
96
- this._authPost = new eik.http.AuthPost({
97
- organizations,
98
- logger,
99
- authKey: config.get('basicAuth.key'),
100
- });
101
- this._pkgLog = new eik.http.PkgLog({ organizations, sink, logger });
102
- this._pkgGet = new eik.http.PkgGet({ organizations, sink, logger });
103
- this._pkgPut = new eik.http.PkgPut({
104
- organizations,
105
- sink,
106
- logger,
107
- pkgMaxFileSize,
108
- });
109
- this._imgPut = new eik.http.PkgPut({
110
- organizations,
111
- sink,
112
- logger,
113
- pkgMaxFileSize: imgMaxFileSize,
114
- });
115
- this._mapGet = new eik.http.MapGet({ organizations, sink, logger });
116
- this._mapPut = new eik.http.MapPut({
117
- organizations,
118
- sink,
119
- logger,
120
- mapMaxFileSize,
121
- });
122
-
123
- const mergeStreams = (...streams) => {
124
- const str = new PassThrough({ objectMode: true });
125
-
126
- // Avoid hitting the max listeners limit when multiple
127
- // streams is piped into the same stream.
128
- str.on('pipe', () => {
129
- str.setMaxListeners(str.getMaxListeners() + 1);
130
- });
131
-
132
- str.on('unpipe', () => {
133
- str.setMaxListeners(str.getMaxListeners() - 1);
134
- });
135
-
136
- for (const stm of streams) {
137
- stm.on('error', (err) => {
138
- logger.error(err);
139
- });
140
- stm.pipe(str);
141
- }
142
- return str;
143
- };
144
-
145
- // pipe metrics
146
- const metrics = mergeStreams(
147
- this._versionsGet.metrics,
148
- this._aliasPost.metrics,
149
- this._aliasDel.metrics,
150
- this._aliasGet.metrics,
151
- this._aliasPut.metrics,
152
- this._authPost.metrics,
153
- this._pkgLog.metrics,
154
- this._pkgGet.metrics,
155
- this._pkgPut.metrics,
156
- this._mapGet.metrics,
157
- this._mapPut.metrics,
158
- sink.metrics,
159
- );
160
-
161
- metrics.on('error', (err) => {
162
- logger.error(err);
163
- });
164
-
165
- this.metrics = metrics;
166
- this.config = config;
167
- this.logger = logger;
168
- this.sink = sink;
169
-
170
- // Print warnings
171
-
172
- if (
173
- config.get('basicAuth.type') === 'key' &&
174
- config.get('basicAuth.key') === config.default('basicAuth.key')
175
- ) {
176
- logger.warn(
177
- 'Server is running with default basic authorization key configured! For security purposes, it is highly recommended to set a custom value!',
178
- );
179
- }
180
-
181
- if (config.get('jwt.secret') === config.default('jwt.secret')) {
182
- logger.warn(
183
- 'Server is running with default jwt secret configured! For security purposes, it is highly recommended to set a custom value!',
184
- );
185
- }
186
-
187
- // Print info
188
-
189
- const hosts = config.get('organization.hostnames').join(', ');
190
- logger.info(
191
- `Files for "${hosts}" will be stored in the "${config.get('organization.name')}" organization space`,
192
- );
193
- }
194
-
195
- async health() {
196
- const health = new eik.HealthCheck({
197
- logger: this.logger,
198
- sink: this.sink,
199
- });
200
- await health.check();
201
- }
202
-
203
- api() {
204
- /** @param {import('fastify').FastifyInstance} app */
205
- return async (app) => {
206
- if (!app.initialConfig.ignoreTrailingSlash) {
207
- this.logger.warn(
208
- 'Fastify is configured with "ignoreTrailingSlash" set to "false". Its adviced to set "ignoreTrailingSlash" to "true"',
209
- );
210
- }
211
-
212
- app.register(cors);
213
-
214
- // Authentication
215
- app.register(jwt, {
216
- secret: config.get('jwt.secret'),
217
- messages: {
218
- badRequestErrorMessage:
219
- 'Autorization header is malformatted. Format is "Authorization: Bearer [token]"',
220
- noAuthorizationInHeaderMessage:
221
- 'Autorization header is missing!',
222
- authorizationTokenExpiredMessage:
223
- 'Authorization token expired',
224
- authorizationTokenInvalid: 'Authorization token is invalid',
225
- },
226
- });
227
-
228
- app.decorate('authenticate', async (request, reply) => {
229
- try {
230
- await request.jwtVerify();
231
- } catch (error) {
232
- reply.send(error);
233
- }
234
- });
235
-
236
- const authOptions = {
237
- // @ts-expect-error We decorate it above
238
- preValidation: [app.authenticate],
239
- };
240
-
241
- // Handle multipart upload
242
- const _multipart = Symbol('multipart');
243
-
244
- function setMultipart(req, payload, cb) {
245
- req.raw[_multipart] = true;
246
- cb();
247
- }
248
- app.addContentTypeParser('multipart', setMultipart);
249
-
250
- // Compression
251
- await app.register(compression, {
252
- global: config.get('compression.global'),
253
- });
254
-
255
- // 404 handling
256
- app.setNotFoundHandler((request, reply) => {
257
- reply.header('cache-control', this._notFoundCacheControl);
258
- reply.type('text/plain');
259
- reply.code(404);
260
- reply.send('Not found');
261
- });
262
-
263
- // Error handling
264
- app.setErrorHandler((error, request, reply) => {
265
- this.logger.debug(
266
- 'Error occured during request. Error is available on trace log level.',
267
- );
268
- this.logger.trace(error);
269
- reply.header('cache-control', 'no-store');
270
- if (error.statusCode) {
271
- if (error.statusCode === 404) {
272
- reply.header(
273
- 'cache-control',
274
- this._notFoundCacheControl,
275
- );
276
- }
277
- reply.send(error);
278
- return;
279
- }
280
- reply.send(createError(error.statusCode || 500));
281
- });
282
-
283
- //
284
- // Routes
285
- //
286
-
287
- const authPostRoutes = async (request, reply) => {
288
- const outgoing = await this._authPost.handler(request.raw);
289
-
290
- // Workaround due to .jwt.sign() being able to only
291
- // deal with object literals for some reason :/
292
- const body = JSON.parse(JSON.stringify(outgoing.body));
293
-
294
- const token = app.jwt.sign(body, {
295
- expiresIn: config.get('jwt.expire'),
296
- });
297
-
298
- reply.header('cache-control', outgoing.cacheControl);
299
- reply.type(outgoing.mimeType);
300
- reply.code(outgoing.statusCode);
301
- reply.send({ token });
302
- };
303
-
304
- const pkgGetRoute = async (request, reply) => {
305
- const params = utils.sanitizeParameters(request.raw.url);
306
- const outgoing = await this._pkgGet.handler(
307
- request.raw,
308
- params.type,
309
- params.name,
310
- params.version,
311
- params.extras,
312
- );
313
- reply.header('cache-control', outgoing.cacheControl);
314
- reply.header('etag', outgoing.etag);
315
- reply.type(outgoing.mimeType);
316
- reply.code(outgoing.statusCode);
317
- return reply.send(outgoing.stream);
318
- };
319
-
320
- const pkgLogRoute = async (request, reply) => {
321
- const params = utils.sanitizeParameters(request.raw.url);
322
- const outgoing = await this._pkgLog.handler(
323
- request.raw,
324
- params.type,
325
- params.name,
326
- params.version,
327
- );
328
- reply.header('cache-control', outgoing.cacheControl);
329
- reply.header('etag', outgoing.etag);
330
- reply.type(outgoing.mimeType);
331
- reply.code(outgoing.statusCode);
332
- return reply.send(outgoing.stream);
333
- };
334
-
335
- const versionsGetRoute = async (request, reply) => {
336
- const params = utils.sanitizeParameters(request.raw.url);
337
- const outgoing = await this._versionsGet.handler(
338
- request.raw,
339
- params.type,
340
- params.name,
341
- );
342
- reply.header('cache-control', outgoing.cacheControl);
343
- reply.header('etag', outgoing.etag);
344
- reply.type(outgoing.mimeType);
345
- reply.code(outgoing.statusCode);
346
- return reply.send(outgoing.stream);
347
- };
348
-
349
- const pkgPutRoute = async (request, reply) => {
350
- const params = utils.sanitizeParameters(request.raw.url);
351
- const outgoing = await this._pkgPut.handler(
352
- request.raw,
353
- request.user,
354
- params.type,
355
- params.name,
356
- params.version,
357
- );
358
- reply.header('cache-control', outgoing.cacheControl);
359
- reply.type(outgoing.mimeType);
360
- reply.code(outgoing.statusCode);
361
- reply.redirect(outgoing.location);
362
- };
363
-
364
- const imgPutRoute = async (request, reply) => {
365
- const params = utils.sanitizeParameters(request.raw.url);
366
- const outgoing = await this._imgPut.handler(
367
- request.raw,
368
- request.user,
369
- params.type,
370
- params.name,
371
- params.version,
372
- );
373
- reply.header('cache-control', outgoing.cacheControl);
374
- reply.type(outgoing.mimeType);
375
- reply.code(outgoing.statusCode);
376
- reply.redirect(outgoing.location);
377
- };
378
-
379
- const mapGetRoute = async (request, reply) => {
380
- const params = utils.sanitizeParameters(request.raw.url);
381
- const outgoing = await this._mapGet.handler(
382
- request.raw,
383
- params.name,
384
- params.version,
385
- );
386
- reply.header('cache-control', outgoing.cacheControl);
387
- reply.header('etag', outgoing.etag);
388
- reply.type(outgoing.mimeType);
389
- reply.code(outgoing.statusCode);
390
- return reply.send(outgoing.stream);
391
- };
392
-
393
- const mapPutRoute = async (request, reply) => {
394
- const params = utils.sanitizeParameters(request.raw.url);
395
- const outgoing = await this._mapPut.handler(
396
- request.raw,
397
- request.user,
398
- params.name,
399
- params.version,
400
- );
401
- reply.header('cache-control', outgoing.cacheControl);
402
- reply.type(outgoing.mimeType);
403
- reply.code(outgoing.statusCode);
404
- reply.redirect(outgoing.location);
405
- };
406
-
407
- const aliasGetRoute = async (request, reply) => {
408
- const params = utils.sanitizeParameters(request.raw.url);
409
- const outgoing = await this._aliasGet.handler(
410
- request.raw,
411
- params.type,
412
- params.name,
413
- params.alias,
414
- params.extras,
415
- );
416
- reply.header('cache-control', outgoing.cacheControl);
417
- reply.type(outgoing.mimeType);
418
- reply.code(outgoing.statusCode);
419
- reply.redirect(outgoing.location);
420
- };
421
-
422
- const aliasPutRoute = async (request, reply) => {
423
- const params = utils.sanitizeParameters(request.raw.url);
424
- const outgoing = await this._aliasPut.handler(
425
- request.raw,
426
- request.user,
427
- params.type,
428
- params.name,
429
- params.alias,
430
- );
431
- reply.header('cache-control', outgoing.cacheControl);
432
- reply.type(outgoing.mimeType);
433
- reply.code(outgoing.statusCode);
434
- reply.redirect(outgoing.location);
435
- };
436
-
437
- const aliasPostRoute = async (request, reply) => {
438
- const params = utils.sanitizeParameters(request.raw.url);
439
- const outgoing = await this._aliasPost.handler(
440
- request.raw,
441
- request.user,
442
- params.type,
443
- params.name,
444
- params.alias,
445
- );
446
- reply.header('cache-control', outgoing.cacheControl);
447
- reply.type(outgoing.mimeType);
448
- reply.code(outgoing.statusCode);
449
- reply.redirect(outgoing.location);
450
- };
451
-
452
- const aliasDelRoute = async (request, reply) => {
453
- const params = utils.sanitizeParameters(request.raw.url);
454
- const outgoing = await this._aliasDel.handler(
455
- request.raw,
456
- request.user,
457
- params.type,
458
- params.name,
459
- params.alias,
460
- );
461
- reply.header('cache-control', outgoing.cacheControl);
462
- reply.type(outgoing.mimeType);
463
- reply.code(outgoing.statusCode);
464
- reply.send(outgoing.body);
465
- };
466
-
467
- //
468
- // Authentication
469
- //
470
-
471
- // curl -X POST -i -F key=foo http://localhost:4001/auth/login
472
-
473
- app.post(`/${eik.prop.base_auth}/login`, authPostRoutes);
474
-
475
- //
476
- // Packages
477
- //
478
-
479
- // Get public package - scoped
480
- // curl -X GET http://localhost:4001/pkg/@cuz/fuzz/8.4.1/main/index.js
481
- app.get(
482
- `/${eik.prop.base_pkg}/@:scope/:name/:version/*`,
483
- pkgGetRoute,
484
- );
485
-
486
- // Get public package - non-scoped
487
- // curl -X GET http://localhost:4001/pkg/fuzz/8.4.1/main/index.js
488
- app.get(`/${eik.prop.base_pkg}/:name/:version/*`, pkgGetRoute);
489
-
490
- // Get package overview - scoped
491
- // curl -X GET http://localhost:4001/pkg/@cuz/fuzz/8.4.1/
492
- app.get(
493
- `/${eik.prop.base_pkg}/@:scope/:name/:version`,
494
- pkgLogRoute,
495
- );
496
-
497
- // Get package overview - non-scoped
498
- // curl -X GET http://localhost:4001/pkg/fuzz/8.4.1/
499
- app.get(`/${eik.prop.base_pkg}/:name/:version`, pkgLogRoute);
500
-
501
- // Get package versions - scoped
502
- // curl -X GET http://localhost:4001/pkg/@cuz/fuzz/
503
- app.get(`/${eik.prop.base_pkg}/@:scope/:name`, versionsGetRoute);
504
-
505
- // Get package versions - non-scoped
506
- // curl -X GET http://localhost:4001/pkg/fuzz/
507
- app.get(`/${eik.prop.base_pkg}/:name`, versionsGetRoute);
508
-
509
- // Put package - scoped
510
- // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/pkg/@cuz/fuzz/8.4.1/
511
- app.put(
512
- `/${eik.prop.base_pkg}/@:scope/:name/:version`,
513
- authOptions,
514
- pkgPutRoute,
515
- );
516
-
517
- // Put package - non-scoped
518
- // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/pkg/fuzz/8.4.1/
519
- app.put(
520
- `/${eik.prop.base_pkg}/:name/:version`,
521
- authOptions,
522
- pkgPutRoute,
523
- );
524
-
525
- //
526
- // NPM Packages
527
- //
528
-
529
- // Get public NPM package - scoped
530
- // curl -X GET http://localhost:4001/npm/@cuz/fuzz/8.4.1/main/index.js
531
- app.get(
532
- `/${eik.prop.base_npm}/@:scope/:name/:version/*`,
533
- pkgGetRoute,
534
- );
535
-
536
- // Get public NPM package - non-scoped
537
- // curl -X GET http://localhost:4001/npm/fuzz/8.4.1/main/index.js
538
- app.get(`/${eik.prop.base_npm}/:name/:version/*`, pkgGetRoute);
539
-
540
- // Get NPM package overview - scoped
541
- // curl -X GET http://localhost:4001/npm/@cuz/fuzz/8.4.1/
542
- app.get(
543
- `/${eik.prop.base_npm}/@:scope/:name/:version`,
544
- pkgLogRoute,
545
- );
546
-
547
- // Get NPM package overview - non-scoped
548
- // curl -X GET http://localhost:4001/npm/fuzz/8.4.1/
549
- app.get(`/${eik.prop.base_npm}/:name/:version`, pkgLogRoute);
550
-
551
- // Get NPM package versions - scoped
552
- // curl -X GET http://localhost:4001/npm/@cuz/fuzz/
553
- app.get(`/${eik.prop.base_npm}/@:scope/:name`, versionsGetRoute);
554
-
555
- // Get NPM package versions - non-scoped
556
- // curl -X GET http://localhost:4001/npm/fuzz/
557
- app.get(`/${eik.prop.base_npm}/:name`, versionsGetRoute);
558
-
559
- // Put NPM package - scoped
560
- // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/npm/@cuz/fuzz/8.4.1/
561
- app.put(
562
- `/${eik.prop.base_npm}/@:scope/:name/:version`,
563
- authOptions,
564
- pkgPutRoute,
565
- );
566
-
567
- // Put NPM package - non-scoped
568
- // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/npm/fuzz/8.4.1/
569
- app.put(
570
- `/${eik.prop.base_npm}/:name/:version`,
571
- authOptions,
572
- pkgPutRoute,
573
- );
574
-
575
- //
576
- // Image Packages
577
- //
578
-
579
- // Get public IMG package - scoped
580
- // curl -X GET http://localhost:4001/img/@cuz/fuzz/8.4.1/main/picture.jpg
581
- app.get(
582
- `/${eik.prop.base_img}/@:scope/:name/:version/*`,
583
- pkgGetRoute,
584
- );
585
-
586
- // Get public IMG package - non-scoped
587
- // curl -X GET http://localhost:4001/img/fuzz/8.4.1/main/picture.jpg
588
- app.get(`/${eik.prop.base_img}/:name/:version/*`, pkgGetRoute);
589
-
590
- // Get IMG package overview - scoped
591
- // curl -X GET http://localhost:4001/img/@cuz/fuzz/8.4.1/
592
- app.get(
593
- `/${eik.prop.base_img}/@:scope/:name/:version`,
594
- pkgLogRoute,
595
- );
596
-
597
- // Get IMG package overview - non-scoped
598
- // curl -X GET http://localhost:4001/img/fuzz/8.4.1/
599
- app.get(`/${eik.prop.base_img}/:name/:version`, pkgLogRoute);
600
-
601
- // Get IMG package versions - scoped
602
- // curl -X GET http://localhost:4001/img/@cuz/fuzz/
603
- app.get(`/${eik.prop.base_img}/@:scope/:name`, versionsGetRoute);
604
-
605
- // Get IMG package versions - non-scoped
606
- // curl -X GET http://localhost:4001/img/fuzz/
607
- app.get(`/${eik.prop.base_img}/:name`, versionsGetRoute);
608
-
609
- // Put IMG package - scoped
610
- // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/img/@cuz/fuzz/8.4.1/
611
- app.put(
612
- `/${eik.prop.base_img}/@:scope/:name/:version`,
613
- authOptions,
614
- imgPutRoute,
615
- );
616
-
617
- // Put IMG package - non-scoped
618
- // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/img/fuzz/8.4.1/
619
- app.put(
620
- `/${eik.prop.base_img}/:name/:version`,
621
- authOptions,
622
- imgPutRoute,
623
- );
624
-
625
- //
626
- // Import Maps
627
- //
628
-
629
- // Get map - scoped
630
- // curl -X GET http://localhost:4001/map/@cuz/buzz/4.2.2
631
- app.get(
632
- `/${eik.prop.base_map}/@:scope/:name/:version`,
633
- mapGetRoute,
634
- );
635
-
636
- // Get map - non-scoped
637
- // curl -X GET http://localhost:4001/map/buzz/4.2.2
638
- app.get(`/${eik.prop.base_map}/:name/:version`, mapGetRoute);
639
-
640
- // Get map versions - scoped
641
- // curl -X GET http://localhost:4001/map/@cuz/buzz
642
- app.get(`/${eik.prop.base_map}/@:scope/:name`, versionsGetRoute);
643
-
644
- // Get map versions - non-scoped
645
- // curl -X GET http://localhost:4001/map/buzz
646
- app.get(`/${eik.prop.base_map}/:name`, versionsGetRoute);
647
-
648
- // Put map - scoped
649
- // curl -X PUT -i -F map=@import-map.json http://localhost:4001/map/@cuz/buzz/4.2.2
650
- app.put(
651
- `/${eik.prop.base_map}/@:scope/:name/:version`,
652
- authOptions,
653
- mapPutRoute,
654
- );
655
-
656
- // Put map - non-scoped
657
- // curl -X PUT -i -F map=@import-map.json http://localhost:4001/map/buzz/4.2.2
658
- app.put(
659
- `/${eik.prop.base_map}/:name/:version`,
660
- authOptions,
661
- mapPutRoute,
662
- );
663
-
664
- //
665
- // Alias Packages
666
- //
667
-
668
- // curl -X GET -L http://localhost:4001/pkg/@cuz/fuzz/v8
669
- app.get(
670
- `/${eik.prop.base_pkg}/@:scope/:name/v:alias`,
671
- aliasGetRoute,
672
- );
673
-
674
- // curl -X GET -L http://localhost:4001/pkg/fuzz/v8
675
- app.get(`/${eik.prop.base_pkg}/:name/v:alias`, aliasGetRoute);
676
-
677
- // curl -X GET -L http://localhost:4001/pkg/@cuz/fuzz/v8/main/index.js
678
- app.get(
679
- `/${eik.prop.base_pkg}/@:scope/:name/v:alias/*`,
680
- aliasGetRoute,
681
- );
682
-
683
- // curl -X GET -L http://localhost:4001/pkg/fuzz/v8/main/index.js
684
- app.get(`/${eik.prop.base_pkg}/:name/v:alias/*`, aliasGetRoute);
685
-
686
- // curl -X PUT -i -F version=8.4.1 http://localhost:4001/pkg/@cuz/fuzz/v8
687
- app.put(
688
- `/${eik.prop.base_pkg}/@:scope/:name/v:alias`,
689
- authOptions,
690
- aliasPutRoute,
691
- );
692
-
693
- // curl -X PUT -i -F version=8.4.1 http://localhost:4001/pkg/fuzz/v8
694
- app.put(
695
- `/${eik.prop.base_pkg}/:name/v:alias`,
696
- authOptions,
697
- aliasPutRoute,
698
- );
699
-
700
- // curl -X POST -i -F version=8.4.1 http://localhost:4001/pkg/@cuz/lit-html/v8
701
- app.post(
702
- `/${eik.prop.base_pkg}/@:scope/:name/v:alias`,
703
- authOptions,
704
- aliasPostRoute,
705
- );
706
-
707
- // curl -X POST -i -F version=8.4.1 http://localhost:4001/pkg/lit-html/v8
708
- app.post(
709
- `/${eik.prop.base_pkg}/:name/v:alias`,
710
- authOptions,
711
- aliasPostRoute,
712
- );
713
-
714
- // curl -X DELETE http://localhost:4001/pkg/@cuz/fuzz/v8
715
- app.delete(
716
- `/${eik.prop.base_pkg}/@:scope/:name/v:alias`,
717
- authOptions,
718
- aliasDelRoute,
719
- );
720
-
721
- // curl -X DELETE http://localhost:4001/pkg/fuzz/v8
722
- app.delete(
723
- `/${eik.prop.base_pkg}/:name/v:alias`,
724
- authOptions,
725
- aliasDelRoute,
726
- );
727
-
728
- //
729
- // Alias NPM Packages
730
- //
731
-
732
- // curl -X GET -L http://localhost:4001/npm/@cuz/fuzz/v8
733
- app.get(
734
- `/${eik.prop.base_npm}/@:scope/:name/v:alias`,
735
- aliasGetRoute,
736
- );
737
-
738
- // curl -X GET -L http://localhost:4001/npm/fuzz/v8
739
- app.get(`/${eik.prop.base_npm}/:name/v:alias`, aliasGetRoute);
740
-
741
- // curl -X GET -L http://localhost:4001/npm/@cuz/fuzz/v8/main/index.js
742
- app.get(
743
- `/${eik.prop.base_npm}/@:scope/:name/v:alias/*`,
744
- aliasGetRoute,
745
- );
746
-
747
- // curl -X GET -L http://localhost:4001/npm/fuzz/v8/main/index.js
748
- app.get(`/${eik.prop.base_npm}/:name/v:alias/*`, aliasGetRoute);
749
-
750
- // curl -X PUT -i -F version=8.4.1 http://localhost:4001/npm/@cuz/fuzz/v8
751
- app.put(
752
- `/${eik.prop.base_npm}/@:scope/:name/v:alias`,
753
- authOptions,
754
- aliasPutRoute,
755
- );
756
-
757
- // curl -X PUT -i -F version=8.4.1 http://localhost:4001/npm/fuzz/v8
758
- app.put(
759
- `/${eik.prop.base_npm}/:name/v:alias`,
760
- authOptions,
761
- aliasPutRoute,
762
- );
763
-
764
- // curl -X POST -i -F version=8.4.1 http://localhost:4001/npm/@cuz/lit-html/v8
765
- app.post(
766
- `/${eik.prop.base_npm}/@:scope/:name/v:alias`,
767
- authOptions,
768
- aliasPostRoute,
769
- );
770
-
771
- // curl -X POST -i -F version=8.4.1 http://localhost:4001/npm/lit-html/v8
772
- app.post(
773
- `/${eik.prop.base_npm}/:name/v:alias`,
774
- authOptions,
775
- aliasPostRoute,
776
- );
777
-
778
- // curl -X DELETE http://localhost:4001/npm/@cuz/fuzz/v8
779
- app.delete(
780
- `/${eik.prop.base_npm}/@:scope/:name/v:alias`,
781
- authOptions,
782
- aliasDelRoute,
783
- );
784
-
785
- // curl -X DELETE http://localhost:4001/npm/fuzz/v8
786
- app.delete(
787
- `/${eik.prop.base_npm}/:name/v:alias`,
788
- authOptions,
789
- aliasDelRoute,
790
- );
791
-
792
- //
793
- // Alias Image Packages
794
- //
795
-
796
- // curl -X GET -L http://localhost:4001/img/@cuz/fuzz/v8
797
- app.get(
798
- `/${eik.prop.base_img}/@:scope/:name/v:alias`,
799
- aliasGetRoute,
800
- );
801
-
802
- // curl -X GET -L http://localhost:4001/img/fuzz/v8
803
- app.get(`/${eik.prop.base_img}/:name/v:alias`, aliasGetRoute);
804
-
805
- // curl -X GET -L http://localhost:4001/img/@cuz/fuzz/v8/main/index.js
806
- app.get(
807
- `/${eik.prop.base_img}/@:scope/:name/v:alias/*`,
808
- aliasGetRoute,
809
- );
810
-
811
- // curl -X GET -L http://localhost:4001/img/fuzz/v8/main/index.js
812
- app.get(`/${eik.prop.base_img}/:name/v:alias/*`, aliasGetRoute);
813
-
814
- // curl -X PUT -i -F version=8.4.1 http://localhost:4001/img/@cuz/fuzz/v8
815
- app.put(
816
- `/${eik.prop.base_img}/@:scope/:name/v:alias`,
817
- authOptions,
818
- aliasPutRoute,
819
- );
820
-
821
- // curl -X PUT -i -F version=8.4.1 http://localhost:4001/img/fuzz/v8
822
- app.put(
823
- `/${eik.prop.base_img}/:name/v:alias`,
824
- authOptions,
825
- aliasPutRoute,
826
- );
827
-
828
- // curl -X POST -i -F version=8.4.1 http://localhost:4001/img/@cuz/lit-html/v8
829
- app.post(
830
- `/${eik.prop.base_img}/@:scope/:name/v:alias`,
831
- authOptions,
832
- aliasPostRoute,
833
- );
834
-
835
- // curl -X POST -i -F version=8.4.1 http://localhost:4001/img/lit-html/v8
836
- app.post(
837
- `/${eik.prop.base_img}/:name/v:alias`,
838
- authOptions,
839
- aliasPostRoute,
840
- );
841
-
842
- // curl -X DELETE http://localhost:4001/img/@cuz/fuzz/v8
843
- app.delete(
844
- `/${eik.prop.base_img}/@:scope/:name/v:alias`,
845
- authOptions,
846
- aliasDelRoute,
847
- );
848
-
849
- // curl -X DELETE http://localhost:4001/img/fuzz/v8
850
- app.delete(
851
- `/${eik.prop.base_img}/:name/v:alias`,
852
- authOptions,
853
- aliasDelRoute,
854
- );
855
-
856
- //
857
- // Alias Import Maps
858
- //
859
-
860
- // curl -X GET -L http://localhost:4001/map/@cuz/buzz/v4
861
- app.get(
862
- `/${eik.prop.base_map}/@:scope/:name/v:alias`,
863
- aliasGetRoute,
864
- );
865
-
866
- // curl -X GET -L http://localhost:4001/map/buzz/v4
867
- app.get(`/${eik.prop.base_map}/:name/v:alias`, aliasGetRoute);
868
-
869
- // curl -X PUT -i -F version=4.2.2 http://localhost:4001/map/@cuz/buzz/v4
870
- app.put(
871
- `/${eik.prop.base_map}/@:scope/:name/v:alias`,
872
- authOptions,
873
- aliasPutRoute,
874
- );
875
-
876
- // curl -X PUT -i -F version=4.2.2 http://localhost:4001/map/buzz/v4
877
- app.put(
878
- `/${eik.prop.base_map}/:name/v:alias`,
879
- authOptions,
880
- aliasPutRoute,
881
- );
882
-
883
- // curl -X POST -i -F version=4.4.2 http://localhost:4001/map/@cuz/buzz/v4
884
- app.post(
885
- `/${eik.prop.base_map}/@:scope/:name/v:alias`,
886
- authOptions,
887
- aliasPostRoute,
888
- );
889
-
890
- // curl -X POST -i -F version=4.4.2 http://localhost:4001/map/buzz/v4
891
- app.post(
892
- `/${eik.prop.base_map}/:name/v:alias`,
893
- authOptions,
894
- aliasPostRoute,
895
- );
896
-
897
- // curl -X DELETE http://localhost:4001/map/@cuz/buzz/v4
898
- app.delete(
899
- `/${eik.prop.base_map}/@:scope/:name/v:alias`,
900
- authOptions,
901
- aliasDelRoute,
902
- );
903
-
904
- // curl -X DELETE http://localhost:4001/map/buzz/v4
905
- app.delete(
906
- `/${eik.prop.base_map}/:name/v:alias`,
907
- authOptions,
908
- aliasDelRoute,
909
- );
910
- };
911
- }
28
+ /**
29
+ * @param {EikServiceOptions} [options={}]
30
+ */
31
+ constructor(options = {}) {
32
+ let { sink, logger } = options;
33
+ const {
34
+ customSink,
35
+ notFoundCacheControl,
36
+ aliasCacheControl,
37
+ pkgMaxFileSize = 10000000,
38
+ mapMaxFileSize = 1000000,
39
+ imgMaxFileSize = 20000000,
40
+ } = options;
41
+ this._notFoundCacheControl = notFoundCacheControl || "public, max-age=5";
42
+
43
+ if (!logger) {
44
+ // @ts-expect-error This is in fact callable
45
+ logger = pino({
46
+ // @ts-ignore
47
+ level: config.get("log.level"),
48
+ name: config.get("name"),
49
+ });
50
+ }
51
+
52
+ if (sink) {
53
+ logger.info(`Using the provided sink ${sink.constructor.name}`);
54
+ } else if (customSink) {
55
+ logger.warn(
56
+ "The `customSink` option is deprecated and will be removed at a later stage. Use `sink` to remove this warning.",
57
+ );
58
+ sink = customSink;
59
+ } else if (config.get("sink.type") === "mem") {
60
+ logger.info(
61
+ `Server is running with a in memory sink. Uploaded files will be lost on restart!`,
62
+ );
63
+ sink = new SinkMemory();
64
+ } else {
65
+ logger.info(
66
+ `Server is running with the file system sink. Uploaded files will be stored under "${config.get("sink.path")}"`,
67
+ );
68
+ sink = new SinkFileSystem({
69
+ sinkFsRootPath: config.get("sink.path"),
70
+ });
71
+ }
72
+
73
+ // Transform organization config
74
+ const organizations = config
75
+ .get("organization.hostnames")
76
+ .map((hostname) => [hostname, config.get("organization.name")]);
77
+
78
+ this._versionsGet = new eik.http.VersionsGet({
79
+ organizations,
80
+ sink,
81
+ logger,
82
+ });
83
+ this._aliasPost = new eik.http.AliasPost({
84
+ organizations,
85
+ sink,
86
+ logger,
87
+ });
88
+ this._aliasDel = new eik.http.AliasDel({ organizations, sink, logger });
89
+ this._aliasGet = new eik.http.AliasGet({
90
+ organizations,
91
+ sink,
92
+ logger,
93
+ cacheControl: aliasCacheControl,
94
+ });
95
+ this._aliasPut = new eik.http.AliasPut({ organizations, sink, logger });
96
+ this._authPost = new eik.http.AuthPost({
97
+ organizations,
98
+ logger,
99
+ authKey: config.get("basicAuth.key"),
100
+ });
101
+ this._pkgLog = new eik.http.PkgLog({ organizations, sink, logger });
102
+ this._pkgGet = new eik.http.PkgGet({ organizations, sink, logger });
103
+ this._pkgPut = new eik.http.PkgPut({
104
+ organizations,
105
+ sink,
106
+ logger,
107
+ pkgMaxFileSize,
108
+ });
109
+ this._imgPut = new eik.http.PkgPut({
110
+ organizations,
111
+ sink,
112
+ logger,
113
+ pkgMaxFileSize: imgMaxFileSize,
114
+ });
115
+ this._mapGet = new eik.http.MapGet({ organizations, sink, logger });
116
+ this._mapPut = new eik.http.MapPut({
117
+ organizations,
118
+ sink,
119
+ logger,
120
+ mapMaxFileSize,
121
+ });
122
+
123
+ const mergeStreams = (...streams) => {
124
+ const str = new PassThrough({ objectMode: true });
125
+
126
+ // Avoid hitting the max listeners limit when multiple
127
+ // streams is piped into the same stream.
128
+ str.on("pipe", () => {
129
+ str.setMaxListeners(str.getMaxListeners() + 1);
130
+ });
131
+
132
+ str.on("unpipe", () => {
133
+ str.setMaxListeners(str.getMaxListeners() - 1);
134
+ });
135
+
136
+ for (const stm of streams) {
137
+ stm.on("error", (err) => {
138
+ logger.error(err);
139
+ });
140
+ stm.pipe(str);
141
+ }
142
+ return str;
143
+ };
144
+
145
+ // pipe metrics
146
+ const metrics = mergeStreams(
147
+ this._versionsGet.metrics,
148
+ this._aliasPost.metrics,
149
+ this._aliasDel.metrics,
150
+ this._aliasGet.metrics,
151
+ this._aliasPut.metrics,
152
+ this._authPost.metrics,
153
+ this._pkgLog.metrics,
154
+ this._pkgGet.metrics,
155
+ this._pkgPut.metrics,
156
+ this._mapGet.metrics,
157
+ this._mapPut.metrics,
158
+ sink.metrics,
159
+ );
160
+
161
+ metrics.on("error", (err) => {
162
+ logger.error(err);
163
+ });
164
+
165
+ this.metrics = metrics;
166
+ this.config = config;
167
+ this.logger = logger;
168
+ this.sink = sink;
169
+
170
+ // Print warnings
171
+
172
+ if (
173
+ config.get("basicAuth.type") === "key" &&
174
+ config.get("basicAuth.key") === config.default("basicAuth.key")
175
+ ) {
176
+ logger.warn(
177
+ "Server is running with default basic authorization key configured! For security purposes, it is highly recommended to set a custom value!",
178
+ );
179
+ }
180
+
181
+ if (config.get("jwt.secret") === config.default("jwt.secret")) {
182
+ logger.warn(
183
+ "Server is running with default jwt secret configured! For security purposes, it is highly recommended to set a custom value!",
184
+ );
185
+ }
186
+
187
+ // Print info
188
+
189
+ const hosts = config.get("organization.hostnames").join(", ");
190
+ logger.info(
191
+ `Files for "${hosts}" will be stored in the "${config.get("organization.name")}" organization space`,
192
+ );
193
+ }
194
+
195
+ async health() {
196
+ const health = new eik.HealthCheck({
197
+ logger: this.logger,
198
+ sink: this.sink,
199
+ });
200
+ await health.check();
201
+ }
202
+
203
+ api() {
204
+ /** @param {import('fastify').FastifyInstance} app */
205
+ return async (app) => {
206
+ if (!app.initialConfig.ignoreTrailingSlash) {
207
+ this.logger.warn(
208
+ 'Fastify is configured with "ignoreTrailingSlash" set to "false". Its adviced to set "ignoreTrailingSlash" to "true"',
209
+ );
210
+ }
211
+
212
+ await app.register(cors);
213
+
214
+ // Authentication
215
+ app.register(jwt, {
216
+ secret: config.get("jwt.secret"),
217
+ messages: {
218
+ badRequestErrorMessage:
219
+ 'Autorization header is malformatted. Format is "Authorization: Bearer [token]"',
220
+ noAuthorizationInHeaderMessage: "Autorization header is missing!",
221
+ authorizationTokenExpiredMessage: "Authorization token expired",
222
+ authorizationTokenInvalid: "Authorization token is invalid",
223
+ },
224
+ });
225
+
226
+ app.decorate("authenticate", async (request, reply) => {
227
+ try {
228
+ await request.jwtVerify();
229
+ } catch (error) {
230
+ reply.send(error);
231
+ }
232
+ });
233
+
234
+ const authOptions = {
235
+ // @ts-expect-error We decorate it above
236
+ preValidation: [app.authenticate],
237
+ };
238
+
239
+ // Handle multipart upload
240
+ const _multipart = Symbol("multipart");
241
+
242
+ function setMultipart(req, payload, cb) {
243
+ req.raw[_multipart] = true;
244
+ cb();
245
+ }
246
+ app.addContentTypeParser("multipart/form-data", setMultipart);
247
+
248
+ // Compression
249
+ await app.register(compression, {
250
+ global: config.get("compression.global"),
251
+ brotliOptions: {
252
+ // The default is 4 (was 11 before @fastify/compress@^7.0.0).
253
+ // 5 sees benefits for file sizes above 64Kb, of which we have several.
254
+ // https://github.com/fastify/fastify-compress/pull/278#issuecomment-1914778795
255
+ [zlib.constants.BROTLI_PARAM_QUALITY]: 5,
256
+ },
257
+ });
258
+
259
+ // 404 handling
260
+ app.setNotFoundHandler((request, reply) => {
261
+ reply.header("cache-control", this._notFoundCacheControl);
262
+ reply.type("text/plain");
263
+ reply.code(404);
264
+ reply.send("Not found");
265
+ });
266
+
267
+ // Error handling
268
+ app.setErrorHandler((error, request, reply) => {
269
+ this.logger.debug(
270
+ "Error occured during request. Error is available on trace log level.",
271
+ );
272
+ this.logger.trace(error);
273
+ reply.header("cache-control", "no-store");
274
+ if (error.statusCode) {
275
+ if (error.statusCode === 404) {
276
+ reply.header("cache-control", this._notFoundCacheControl);
277
+ }
278
+ reply.send(error);
279
+ return;
280
+ }
281
+ reply.send(createError(error.statusCode || 500));
282
+ });
283
+
284
+ //
285
+ // Routes
286
+ //
287
+
288
+ const authPostRoutes = async (request, reply) => {
289
+ const outgoing = await this._authPost.handler(request.raw);
290
+
291
+ // Workaround due to .jwt.sign() being able to only
292
+ // deal with object literals for some reason :/
293
+ const body = JSON.parse(JSON.stringify(outgoing.body));
294
+
295
+ const token = app.jwt.sign(body, {
296
+ expiresIn: config.get("jwt.expire"),
297
+ });
298
+
299
+ reply.header("cache-control", outgoing.cacheControl);
300
+ reply.type(outgoing.mimeType);
301
+ reply.code(outgoing.statusCode);
302
+ reply.send({ token });
303
+ };
304
+
305
+ const pkgGetRoute = async (request, reply) => {
306
+ const params = utils.sanitizeParameters(request.raw.url);
307
+ const outgoing = await this._pkgGet.handler(
308
+ request.raw,
309
+ params.type,
310
+ params.name,
311
+ params.version,
312
+ params.extras,
313
+ );
314
+ reply.header("cache-control", outgoing.cacheControl);
315
+ reply.header("etag", outgoing.etag);
316
+ reply.type(outgoing.mimeType);
317
+ reply.code(outgoing.statusCode);
318
+ return reply.send(outgoing.stream);
319
+ };
320
+
321
+ const pkgLogRoute = async (request, reply) => {
322
+ const params = utils.sanitizeParameters(request.raw.url);
323
+ const outgoing = await this._pkgLog.handler(
324
+ request.raw,
325
+ params.type,
326
+ params.name,
327
+ params.version,
328
+ );
329
+ reply.header("cache-control", outgoing.cacheControl);
330
+ reply.header("etag", outgoing.etag);
331
+ reply.type(outgoing.mimeType);
332
+ reply.code(outgoing.statusCode);
333
+ return reply.send(outgoing.stream);
334
+ };
335
+
336
+ const versionsGetRoute = async (request, reply) => {
337
+ const params = utils.sanitizeParameters(request.raw.url);
338
+ const outgoing = await this._versionsGet.handler(
339
+ request.raw,
340
+ params.type,
341
+ params.name,
342
+ );
343
+ reply.header("cache-control", outgoing.cacheControl);
344
+ reply.header("etag", outgoing.etag);
345
+ reply.type(outgoing.mimeType);
346
+ reply.code(outgoing.statusCode);
347
+ return reply.send(outgoing.stream);
348
+ };
349
+
350
+ const pkgPutRoute = async (request, reply) => {
351
+ const params = utils.sanitizeParameters(request.raw.url);
352
+ const outgoing = await this._pkgPut.handler(
353
+ request.raw,
354
+ request.user,
355
+ params.type,
356
+ params.name,
357
+ params.version,
358
+ );
359
+ reply.header("cache-control", outgoing.cacheControl);
360
+ reply.type(outgoing.mimeType);
361
+ reply.code(outgoing.statusCode);
362
+ reply.redirect(outgoing.location);
363
+ };
364
+
365
+ const imgPutRoute = async (request, reply) => {
366
+ const params = utils.sanitizeParameters(request.raw.url);
367
+ const outgoing = await this._imgPut.handler(
368
+ request.raw,
369
+ request.user,
370
+ params.type,
371
+ params.name,
372
+ params.version,
373
+ );
374
+ reply.header("cache-control", outgoing.cacheControl);
375
+ reply.type(outgoing.mimeType);
376
+ reply.code(outgoing.statusCode);
377
+ reply.redirect(outgoing.location);
378
+ };
379
+
380
+ const mapGetRoute = async (request, reply) => {
381
+ const params = utils.sanitizeParameters(request.raw.url);
382
+ const outgoing = await this._mapGet.handler(
383
+ request.raw,
384
+ params.name,
385
+ params.version,
386
+ );
387
+ reply.header("cache-control", outgoing.cacheControl);
388
+ reply.header("etag", outgoing.etag);
389
+ reply.type(outgoing.mimeType);
390
+ reply.code(outgoing.statusCode);
391
+ return reply.send(outgoing.stream);
392
+ };
393
+
394
+ const mapPutRoute = async (request, reply) => {
395
+ const params = utils.sanitizeParameters(request.raw.url);
396
+ const outgoing = await this._mapPut.handler(
397
+ request.raw,
398
+ request.user,
399
+ params.name,
400
+ params.version,
401
+ );
402
+ reply.header("cache-control", outgoing.cacheControl);
403
+ reply.type(outgoing.mimeType);
404
+ reply.code(outgoing.statusCode);
405
+ reply.redirect(outgoing.location);
406
+ };
407
+
408
+ const aliasGetRoute = async (request, reply) => {
409
+ const params = utils.sanitizeParameters(request.raw.url);
410
+ const outgoing = await this._aliasGet.handler(
411
+ request.raw,
412
+ params.type,
413
+ params.name,
414
+ params.alias,
415
+ params.extras,
416
+ );
417
+ reply.header("cache-control", outgoing.cacheControl);
418
+ reply.type(outgoing.mimeType);
419
+ reply.code(outgoing.statusCode);
420
+ reply.redirect(outgoing.location);
421
+ };
422
+
423
+ const aliasPutRoute = async (request, reply) => {
424
+ const params = utils.sanitizeParameters(request.raw.url);
425
+ const outgoing = await this._aliasPut.handler(
426
+ request.raw,
427
+ request.user,
428
+ params.type,
429
+ params.name,
430
+ params.alias,
431
+ );
432
+ reply.header("cache-control", outgoing.cacheControl);
433
+ reply.type(outgoing.mimeType);
434
+ reply.code(outgoing.statusCode);
435
+ reply.redirect(outgoing.location);
436
+ };
437
+
438
+ const aliasPostRoute = async (request, reply) => {
439
+ const params = utils.sanitizeParameters(request.raw.url);
440
+ const outgoing = await this._aliasPost.handler(
441
+ request.raw,
442
+ request.user,
443
+ params.type,
444
+ params.name,
445
+ params.alias,
446
+ );
447
+ reply.header("cache-control", outgoing.cacheControl);
448
+ reply.type(outgoing.mimeType);
449
+ reply.code(outgoing.statusCode);
450
+ reply.redirect(outgoing.location);
451
+ };
452
+
453
+ const aliasDelRoute = async (request, reply) => {
454
+ const params = utils.sanitizeParameters(request.raw.url);
455
+ const outgoing = await this._aliasDel.handler(
456
+ request.raw,
457
+ request.user,
458
+ params.type,
459
+ params.name,
460
+ params.alias,
461
+ );
462
+ reply.header("cache-control", outgoing.cacheControl);
463
+ reply.type(outgoing.mimeType);
464
+ reply.code(outgoing.statusCode);
465
+ reply.send(outgoing.body);
466
+ };
467
+
468
+ //
469
+ // Authentication
470
+ //
471
+
472
+ // curl -X POST -i -F key=foo http://localhost:4001/auth/login
473
+
474
+ app.post(`/${eik.prop.base_auth}/login`, authPostRoutes);
475
+
476
+ //
477
+ // Packages
478
+ //
479
+
480
+ // Get public package - scoped
481
+ // curl -X GET http://localhost:4001/pkg/@cuz/fuzz/8.4.1/main/index.js
482
+ app.get(`/${eik.prop.base_pkg}/@:scope/:name/:version/*`, pkgGetRoute);
483
+
484
+ // Get public package - non-scoped
485
+ // curl -X GET http://localhost:4001/pkg/fuzz/8.4.1/main/index.js
486
+ app.get(`/${eik.prop.base_pkg}/:name/:version/*`, pkgGetRoute);
487
+
488
+ // Get package overview - scoped
489
+ // curl -X GET http://localhost:4001/pkg/@cuz/fuzz/8.4.1/
490
+ app.get(`/${eik.prop.base_pkg}/@:scope/:name/:version`, pkgLogRoute);
491
+
492
+ // Get package overview - non-scoped
493
+ // curl -X GET http://localhost:4001/pkg/fuzz/8.4.1/
494
+ app.get(`/${eik.prop.base_pkg}/:name/:version`, pkgLogRoute);
495
+
496
+ // Get package versions - scoped
497
+ // curl -X GET http://localhost:4001/pkg/@cuz/fuzz/
498
+ app.get(`/${eik.prop.base_pkg}/@:scope/:name`, versionsGetRoute);
499
+
500
+ // Get package versions - non-scoped
501
+ // curl -X GET http://localhost:4001/pkg/fuzz/
502
+ app.get(`/${eik.prop.base_pkg}/:name`, versionsGetRoute);
503
+
504
+ // Put package - scoped
505
+ // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/pkg/@cuz/fuzz/8.4.1/
506
+ app.put(
507
+ `/${eik.prop.base_pkg}/@:scope/:name/:version`,
508
+ authOptions,
509
+ pkgPutRoute,
510
+ );
511
+
512
+ // Put package - non-scoped
513
+ // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/pkg/fuzz/8.4.1/
514
+ app.put(`/${eik.prop.base_pkg}/:name/:version`, authOptions, pkgPutRoute);
515
+
516
+ //
517
+ // NPM Packages
518
+ //
519
+
520
+ // Get public NPM package - scoped
521
+ // curl -X GET http://localhost:4001/npm/@cuz/fuzz/8.4.1/main/index.js
522
+ app.get(`/${eik.prop.base_npm}/@:scope/:name/:version/*`, pkgGetRoute);
523
+
524
+ // Get public NPM package - non-scoped
525
+ // curl -X GET http://localhost:4001/npm/fuzz/8.4.1/main/index.js
526
+ app.get(`/${eik.prop.base_npm}/:name/:version/*`, pkgGetRoute);
527
+
528
+ // Get NPM package overview - scoped
529
+ // curl -X GET http://localhost:4001/npm/@cuz/fuzz/8.4.1/
530
+ app.get(`/${eik.prop.base_npm}/@:scope/:name/:version`, pkgLogRoute);
531
+
532
+ // Get NPM package overview - non-scoped
533
+ // curl -X GET http://localhost:4001/npm/fuzz/8.4.1/
534
+ app.get(`/${eik.prop.base_npm}/:name/:version`, pkgLogRoute);
535
+
536
+ // Get NPM package versions - scoped
537
+ // curl -X GET http://localhost:4001/npm/@cuz/fuzz/
538
+ app.get(`/${eik.prop.base_npm}/@:scope/:name`, versionsGetRoute);
539
+
540
+ // Get NPM package versions - non-scoped
541
+ // curl -X GET http://localhost:4001/npm/fuzz/
542
+ app.get(`/${eik.prop.base_npm}/:name`, versionsGetRoute);
543
+
544
+ // Put NPM package - scoped
545
+ // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/npm/@cuz/fuzz/8.4.1/
546
+ app.put(
547
+ `/${eik.prop.base_npm}/@:scope/:name/:version`,
548
+ authOptions,
549
+ pkgPutRoute,
550
+ );
551
+
552
+ // Put NPM package - non-scoped
553
+ // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/npm/fuzz/8.4.1/
554
+ app.put(`/${eik.prop.base_npm}/:name/:version`, authOptions, pkgPutRoute);
555
+
556
+ //
557
+ // Image Packages
558
+ //
559
+
560
+ // Get public IMG package - scoped
561
+ // curl -X GET http://localhost:4001/img/@cuz/fuzz/8.4.1/main/picture.jpg
562
+ app.get(`/${eik.prop.base_img}/@:scope/:name/:version/*`, pkgGetRoute);
563
+
564
+ // Get public IMG package - non-scoped
565
+ // curl -X GET http://localhost:4001/img/fuzz/8.4.1/main/picture.jpg
566
+ app.get(`/${eik.prop.base_img}/:name/:version/*`, pkgGetRoute);
567
+
568
+ // Get IMG package overview - scoped
569
+ // curl -X GET http://localhost:4001/img/@cuz/fuzz/8.4.1/
570
+ app.get(`/${eik.prop.base_img}/@:scope/:name/:version`, pkgLogRoute);
571
+
572
+ // Get IMG package overview - non-scoped
573
+ // curl -X GET http://localhost:4001/img/fuzz/8.4.1/
574
+ app.get(`/${eik.prop.base_img}/:name/:version`, pkgLogRoute);
575
+
576
+ // Get IMG package versions - scoped
577
+ // curl -X GET http://localhost:4001/img/@cuz/fuzz/
578
+ app.get(`/${eik.prop.base_img}/@:scope/:name`, versionsGetRoute);
579
+
580
+ // Get IMG package versions - non-scoped
581
+ // curl -X GET http://localhost:4001/img/fuzz/
582
+ app.get(`/${eik.prop.base_img}/:name`, versionsGetRoute);
583
+
584
+ // Put IMG package - scoped
585
+ // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/img/@cuz/fuzz/8.4.1/
586
+ app.put(
587
+ `/${eik.prop.base_img}/@:scope/:name/:version`,
588
+ authOptions,
589
+ imgPutRoute,
590
+ );
591
+
592
+ // Put IMG package - non-scoped
593
+ // curl -X PUT -i -F filedata=@archive.tgz http://localhost:4001/img/fuzz/8.4.1/
594
+ app.put(`/${eik.prop.base_img}/:name/:version`, authOptions, imgPutRoute);
595
+
596
+ //
597
+ // Import Maps
598
+ //
599
+
600
+ // Get map - scoped
601
+ // curl -X GET http://localhost:4001/map/@cuz/buzz/4.2.2
602
+ app.get(`/${eik.prop.base_map}/@:scope/:name/:version`, mapGetRoute);
603
+
604
+ // Get map - non-scoped
605
+ // curl -X GET http://localhost:4001/map/buzz/4.2.2
606
+ app.get(`/${eik.prop.base_map}/:name/:version`, mapGetRoute);
607
+
608
+ // Get map versions - scoped
609
+ // curl -X GET http://localhost:4001/map/@cuz/buzz
610
+ app.get(`/${eik.prop.base_map}/@:scope/:name`, versionsGetRoute);
611
+
612
+ // Get map versions - non-scoped
613
+ // curl -X GET http://localhost:4001/map/buzz
614
+ app.get(`/${eik.prop.base_map}/:name`, versionsGetRoute);
615
+
616
+ // Put map - scoped
617
+ // curl -X PUT -i -F map=@import-map.json http://localhost:4001/map/@cuz/buzz/4.2.2
618
+ app.put(
619
+ `/${eik.prop.base_map}/@:scope/:name/:version`,
620
+ authOptions,
621
+ mapPutRoute,
622
+ );
623
+
624
+ // Put map - non-scoped
625
+ // curl -X PUT -i -F map=@import-map.json http://localhost:4001/map/buzz/4.2.2
626
+ app.put(`/${eik.prop.base_map}/:name/:version`, authOptions, mapPutRoute);
627
+
628
+ //
629
+ // Alias Packages
630
+ //
631
+
632
+ // curl -X GET -L http://localhost:4001/pkg/@cuz/fuzz/v8
633
+ app.get(`/${eik.prop.base_pkg}/@:scope/:name/v:alias`, aliasGetRoute);
634
+
635
+ // curl -X GET -L http://localhost:4001/pkg/fuzz/v8
636
+ app.get(`/${eik.prop.base_pkg}/:name/v:alias`, aliasGetRoute);
637
+
638
+ // curl -X GET -L http://localhost:4001/pkg/@cuz/fuzz/v8/main/index.js
639
+ app.get(`/${eik.prop.base_pkg}/@:scope/:name/v:alias/*`, aliasGetRoute);
640
+
641
+ // curl -X GET -L http://localhost:4001/pkg/fuzz/v8/main/index.js
642
+ app.get(`/${eik.prop.base_pkg}/:name/v:alias/*`, aliasGetRoute);
643
+
644
+ // curl -X PUT -i -F version=8.4.1 http://localhost:4001/pkg/@cuz/fuzz/v8
645
+ app.put(
646
+ `/${eik.prop.base_pkg}/@:scope/:name/v:alias`,
647
+ authOptions,
648
+ aliasPutRoute,
649
+ );
650
+
651
+ // curl -X PUT -i -F version=8.4.1 http://localhost:4001/pkg/fuzz/v8
652
+ app.put(
653
+ `/${eik.prop.base_pkg}/:name/v:alias`,
654
+ authOptions,
655
+ aliasPutRoute,
656
+ );
657
+
658
+ // curl -X POST -i -F version=8.4.1 http://localhost:4001/pkg/@cuz/lit-html/v8
659
+ app.post(
660
+ `/${eik.prop.base_pkg}/@:scope/:name/v:alias`,
661
+ authOptions,
662
+ aliasPostRoute,
663
+ );
664
+
665
+ // curl -X POST -i -F version=8.4.1 http://localhost:4001/pkg/lit-html/v8
666
+ app.post(
667
+ `/${eik.prop.base_pkg}/:name/v:alias`,
668
+ authOptions,
669
+ aliasPostRoute,
670
+ );
671
+
672
+ // curl -X DELETE http://localhost:4001/pkg/@cuz/fuzz/v8
673
+ app.delete(
674
+ `/${eik.prop.base_pkg}/@:scope/:name/v:alias`,
675
+ authOptions,
676
+ aliasDelRoute,
677
+ );
678
+
679
+ // curl -X DELETE http://localhost:4001/pkg/fuzz/v8
680
+ app.delete(
681
+ `/${eik.prop.base_pkg}/:name/v:alias`,
682
+ authOptions,
683
+ aliasDelRoute,
684
+ );
685
+
686
+ //
687
+ // Alias NPM Packages
688
+ //
689
+
690
+ // curl -X GET -L http://localhost:4001/npm/@cuz/fuzz/v8
691
+ app.get(`/${eik.prop.base_npm}/@:scope/:name/v:alias`, aliasGetRoute);
692
+
693
+ // curl -X GET -L http://localhost:4001/npm/fuzz/v8
694
+ app.get(`/${eik.prop.base_npm}/:name/v:alias`, aliasGetRoute);
695
+
696
+ // curl -X GET -L http://localhost:4001/npm/@cuz/fuzz/v8/main/index.js
697
+ app.get(`/${eik.prop.base_npm}/@:scope/:name/v:alias/*`, aliasGetRoute);
698
+
699
+ // curl -X GET -L http://localhost:4001/npm/fuzz/v8/main/index.js
700
+ app.get(`/${eik.prop.base_npm}/:name/v:alias/*`, aliasGetRoute);
701
+
702
+ // curl -X PUT -i -F version=8.4.1 http://localhost:4001/npm/@cuz/fuzz/v8
703
+ app.put(
704
+ `/${eik.prop.base_npm}/@:scope/:name/v:alias`,
705
+ authOptions,
706
+ aliasPutRoute,
707
+ );
708
+
709
+ // curl -X PUT -i -F version=8.4.1 http://localhost:4001/npm/fuzz/v8
710
+ app.put(
711
+ `/${eik.prop.base_npm}/:name/v:alias`,
712
+ authOptions,
713
+ aliasPutRoute,
714
+ );
715
+
716
+ // curl -X POST -i -F version=8.4.1 http://localhost:4001/npm/@cuz/lit-html/v8
717
+ app.post(
718
+ `/${eik.prop.base_npm}/@:scope/:name/v:alias`,
719
+ authOptions,
720
+ aliasPostRoute,
721
+ );
722
+
723
+ // curl -X POST -i -F version=8.4.1 http://localhost:4001/npm/lit-html/v8
724
+ app.post(
725
+ `/${eik.prop.base_npm}/:name/v:alias`,
726
+ authOptions,
727
+ aliasPostRoute,
728
+ );
729
+
730
+ // curl -X DELETE http://localhost:4001/npm/@cuz/fuzz/v8
731
+ app.delete(
732
+ `/${eik.prop.base_npm}/@:scope/:name/v:alias`,
733
+ authOptions,
734
+ aliasDelRoute,
735
+ );
736
+
737
+ // curl -X DELETE http://localhost:4001/npm/fuzz/v8
738
+ app.delete(
739
+ `/${eik.prop.base_npm}/:name/v:alias`,
740
+ authOptions,
741
+ aliasDelRoute,
742
+ );
743
+
744
+ //
745
+ // Alias Image Packages
746
+ //
747
+
748
+ // curl -X GET -L http://localhost:4001/img/@cuz/fuzz/v8
749
+ app.get(`/${eik.prop.base_img}/@:scope/:name/v:alias`, aliasGetRoute);
750
+
751
+ // curl -X GET -L http://localhost:4001/img/fuzz/v8
752
+ app.get(`/${eik.prop.base_img}/:name/v:alias`, aliasGetRoute);
753
+
754
+ // curl -X GET -L http://localhost:4001/img/@cuz/fuzz/v8/main/index.js
755
+ app.get(`/${eik.prop.base_img}/@:scope/:name/v:alias/*`, aliasGetRoute);
756
+
757
+ // curl -X GET -L http://localhost:4001/img/fuzz/v8/main/index.js
758
+ app.get(`/${eik.prop.base_img}/:name/v:alias/*`, aliasGetRoute);
759
+
760
+ // curl -X PUT -i -F version=8.4.1 http://localhost:4001/img/@cuz/fuzz/v8
761
+ app.put(
762
+ `/${eik.prop.base_img}/@:scope/:name/v:alias`,
763
+ authOptions,
764
+ aliasPutRoute,
765
+ );
766
+
767
+ // curl -X PUT -i -F version=8.4.1 http://localhost:4001/img/fuzz/v8
768
+ app.put(
769
+ `/${eik.prop.base_img}/:name/v:alias`,
770
+ authOptions,
771
+ aliasPutRoute,
772
+ );
773
+
774
+ // curl -X POST -i -F version=8.4.1 http://localhost:4001/img/@cuz/lit-html/v8
775
+ app.post(
776
+ `/${eik.prop.base_img}/@:scope/:name/v:alias`,
777
+ authOptions,
778
+ aliasPostRoute,
779
+ );
780
+
781
+ // curl -X POST -i -F version=8.4.1 http://localhost:4001/img/lit-html/v8
782
+ app.post(
783
+ `/${eik.prop.base_img}/:name/v:alias`,
784
+ authOptions,
785
+ aliasPostRoute,
786
+ );
787
+
788
+ // curl -X DELETE http://localhost:4001/img/@cuz/fuzz/v8
789
+ app.delete(
790
+ `/${eik.prop.base_img}/@:scope/:name/v:alias`,
791
+ authOptions,
792
+ aliasDelRoute,
793
+ );
794
+
795
+ // curl -X DELETE http://localhost:4001/img/fuzz/v8
796
+ app.delete(
797
+ `/${eik.prop.base_img}/:name/v:alias`,
798
+ authOptions,
799
+ aliasDelRoute,
800
+ );
801
+
802
+ //
803
+ // Alias Import Maps
804
+ //
805
+
806
+ // curl -X GET -L http://localhost:4001/map/@cuz/buzz/v4
807
+ app.get(`/${eik.prop.base_map}/@:scope/:name/v:alias`, aliasGetRoute);
808
+
809
+ // curl -X GET -L http://localhost:4001/map/buzz/v4
810
+ app.get(`/${eik.prop.base_map}/:name/v:alias`, aliasGetRoute);
811
+
812
+ // curl -X PUT -i -F version=4.2.2 http://localhost:4001/map/@cuz/buzz/v4
813
+ app.put(
814
+ `/${eik.prop.base_map}/@:scope/:name/v:alias`,
815
+ authOptions,
816
+ aliasPutRoute,
817
+ );
818
+
819
+ // curl -X PUT -i -F version=4.2.2 http://localhost:4001/map/buzz/v4
820
+ app.put(
821
+ `/${eik.prop.base_map}/:name/v:alias`,
822
+ authOptions,
823
+ aliasPutRoute,
824
+ );
825
+
826
+ // curl -X POST -i -F version=4.4.2 http://localhost:4001/map/@cuz/buzz/v4
827
+ app.post(
828
+ `/${eik.prop.base_map}/@:scope/:name/v:alias`,
829
+ authOptions,
830
+ aliasPostRoute,
831
+ );
832
+
833
+ // curl -X POST -i -F version=4.4.2 http://localhost:4001/map/buzz/v4
834
+ app.post(
835
+ `/${eik.prop.base_map}/:name/v:alias`,
836
+ authOptions,
837
+ aliasPostRoute,
838
+ );
839
+
840
+ // curl -X DELETE http://localhost:4001/map/@cuz/buzz/v4
841
+ app.delete(
842
+ `/${eik.prop.base_map}/@:scope/:name/v:alias`,
843
+ authOptions,
844
+ aliasDelRoute,
845
+ );
846
+
847
+ // curl -X DELETE http://localhost:4001/map/buzz/v4
848
+ app.delete(
849
+ `/${eik.prop.base_map}/:name/v:alias`,
850
+ authOptions,
851
+ aliasDelRoute,
852
+ );
853
+ };
854
+ }
912
855
  };
913
856
 
914
857
  export default EikService;