mikroserve 0.0.1 → 0.0.4

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/MikroServe.js CHANGED
@@ -36,6 +36,7 @@ module.exports = __toCommonJS(MikroServe_exports);
36
36
  var import_node_fs = require("fs");
37
37
  var import_node_http = __toESM(require("http"));
38
38
  var import_node_https = __toESM(require("https"));
39
+ var import_mikroconf = require("mikroconf");
39
40
 
40
41
  // src/RateLimiter.ts
41
42
  var RateLimiter = class {
@@ -280,93 +281,137 @@ var Router = class {
280
281
  }
281
282
  };
282
283
 
284
+ // src/utils/getTruthyEnvValue.ts
285
+ function getTruthyEnvValue(value) {
286
+ if (value === "true" || value === true) return true;
287
+ return false;
288
+ }
289
+
290
+ // src/utils/configDefaults.ts
291
+ var configDefaults = () => {
292
+ return {
293
+ port: Number(process.env.PORT) || 3e3,
294
+ host: process.env.HOST || "0.0.0.0",
295
+ useHttps: false,
296
+ sslCert: "",
297
+ sslKey: "",
298
+ sslCa: "",
299
+ debug: getTruthyEnvValue(process.env.DEBUG) || false,
300
+ rateLimit: {
301
+ enabled: true,
302
+ requestsPerMinute: 100
303
+ },
304
+ allowedDomains: ["*"]
305
+ };
306
+ };
307
+
283
308
  // src/MikroServe.ts
284
309
  var MikroServe = class {
285
- config;
286
310
  rateLimiter;
287
311
  router;
288
- useHttps;
289
- sslCert;
290
- sslKey;
291
- sslCa;
292
- debug;
312
+ config;
293
313
  /**
294
314
  * @description Creates a new MikroServe instance.
295
- * @param config - Server configuration options
296
315
  */
297
- constructor(config) {
316
+ constructor(options) {
317
+ const defaults = configDefaults();
318
+ const config = new import_mikroconf.MikroConf({
319
+ configFilePath: "mikroserve.config.json",
320
+ args: process.argv,
321
+ options: [
322
+ { flag: "--port", path: "port", defaultValue: defaults.port },
323
+ { flag: "--host", path: "host", defaultValue: defaults.host },
324
+ { flag: "--https", path: "useHttps", defaultValue: defaults.useHttps, isFlag: true },
325
+ { flag: "--cert", path: "sslCert", defaultValue: defaults.sslCert },
326
+ { flag: "--key", path: "sslKey", defaultValue: defaults.sslKey },
327
+ { flag: "--ca", path: "sslCa", defaultValue: defaults.sslCa },
328
+ {
329
+ flag: "--ratelimit",
330
+ path: "rateLimit.enabled",
331
+ defaultValue: defaults.rateLimit.enabled,
332
+ isFlag: true
333
+ },
334
+ {
335
+ flag: "--rps",
336
+ path: "rateLimit.requestsPerMinute",
337
+ defaultValue: defaults.rateLimit.requestsPerMinute
338
+ },
339
+ {
340
+ flag: "--allowed",
341
+ path: "allowedDomains",
342
+ defaultValue: defaults.allowedDomains,
343
+ parser: import_mikroconf.parsers.array
344
+ },
345
+ { flag: "--debug", path: "debug", defaultValue: defaults.debug, isFlag: true }
346
+ ],
347
+ config: options
348
+ }).get();
349
+ if (config.debug) console.log("Using configuration:", config);
298
350
  this.config = config;
299
- const { useHttps, sslCa, sslCert, sslKey, debug } = config;
300
- const requestsPerMinute = config.rateLimit?.requestsPerMinute || 50;
301
- this.rateLimiter = new RateLimiter(requestsPerMinute, 60);
302
351
  this.router = new Router();
303
- this.useHttps = useHttps || false;
304
- this.sslCert = sslCert;
305
- this.sslKey = sslKey;
306
- this.sslCa = sslCa;
307
- this.debug = debug || false;
308
- if (config.rateLimit?.enabled !== false) this.use(this.rateLimitMiddleware.bind(this));
352
+ const requestsPerMinute = config.rateLimit.requestsPerMinute || defaults.rateLimit.requestsPerMinute;
353
+ this.rateLimiter = new RateLimiter(requestsPerMinute, 60);
354
+ if (config.rateLimit.enabled === true) this.use(this.rateLimitMiddleware.bind(this));
309
355
  }
310
356
  /**
311
- * Register a global middleware
357
+ * @description Register a global middleware.
312
358
  */
313
359
  use(middleware) {
314
360
  this.router.use(middleware);
315
361
  return this;
316
362
  }
317
363
  /**
318
- * Register a GET route
364
+ * @description Register a GET route.
319
365
  */
320
366
  get(path, ...handlers) {
321
367
  this.router.get(path, ...handlers);
322
368
  return this;
323
369
  }
324
370
  /**
325
- * Register a POST route
371
+ * @description Register a POST route.
326
372
  */
327
373
  post(path, ...handlers) {
328
374
  this.router.post(path, ...handlers);
329
375
  return this;
330
376
  }
331
377
  /**
332
- * Register a PUT route
378
+ * @description Register a PUT route.
333
379
  */
334
380
  put(path, ...handlers) {
335
381
  this.router.put(path, ...handlers);
336
382
  return this;
337
383
  }
338
384
  /**
339
- * Register a DELETE route
385
+ * @description Register a DELETE route.
340
386
  */
341
387
  delete(path, ...handlers) {
342
388
  this.router.delete(path, ...handlers);
343
389
  return this;
344
390
  }
345
391
  /**
346
- * Register a PATCH route
392
+ * @description Register a PATCH route.
347
393
  */
348
394
  patch(path, ...handlers) {
349
395
  this.router.patch(path, ...handlers);
350
396
  return this;
351
397
  }
352
398
  /**
353
- * Register an OPTIONS route
399
+ * @description Register an OPTIONS route.
354
400
  */
355
401
  options(path, ...handlers) {
356
402
  this.router.options(path, ...handlers);
357
403
  return this;
358
404
  }
359
405
  /**
360
- * Creates an HTTP/HTTPS server, sets up graceful shutdown, and starts listening.
361
- * @returns Running HTTP/HTTPS server
406
+ * @description Creates an HTTP/HTTPS server, sets up graceful shutdown, and starts listening.
362
407
  */
363
408
  start() {
364
409
  const server = this.createServer();
365
- const { port = 3e3, host = "localhost" } = this.config;
410
+ const { port, host } = this.config;
366
411
  this.setupGracefulShutdown(server);
367
412
  server.listen(port, host, () => {
368
413
  const address = server.address();
369
- const protocol = this.useHttps ? "https" : "http";
414
+ const protocol = this.config.useHttps ? "https" : "http";
370
415
  console.log(
371
416
  `MikroServe running at ${protocol}://${address.address !== "::" ? address.address : "localhost"}:${address.port}`
372
417
  );
@@ -374,19 +419,18 @@ var MikroServe = class {
374
419
  return server;
375
420
  }
376
421
  /**
377
- * Creates and configures a server instance without starting it.
378
- * @returns Configured HTTP or HTTPS server instance
422
+ * @description Creates and configures a server instance without starting it.
379
423
  */
380
424
  createServer() {
381
425
  const boundRequestHandler = this.requestHandler.bind(this);
382
- if (this.useHttps) {
383
- if (!this.sslCert || !this.sslKey)
426
+ if (this.config.useHttps) {
427
+ if (!this.config.sslCert || !this.config.sslKey)
384
428
  throw new Error("SSL certificate and key paths are required when useHttps is true");
385
429
  try {
386
430
  const httpsOptions = {
387
- key: (0, import_node_fs.readFileSync)(this.sslKey),
388
- cert: (0, import_node_fs.readFileSync)(this.sslCert),
389
- ...this.sslCa ? { ca: (0, import_node_fs.readFileSync)(this.sslCa) } : {}
431
+ key: (0, import_node_fs.readFileSync)(this.config.sslKey),
432
+ cert: (0, import_node_fs.readFileSync)(this.config.sslCert),
433
+ ...this.config.sslCa ? { ca: (0, import_node_fs.readFileSync)(this.config.sslCa) } : {}
390
434
  };
391
435
  return import_node_https.default.createServer(httpsOptions, boundRequestHandler);
392
436
  } catch (error) {
@@ -398,7 +442,7 @@ var MikroServe = class {
398
442
  return import_node_http.default.createServer(boundRequestHandler);
399
443
  }
400
444
  /**
401
- * Rate limiting middleware
445
+ * @description Rate limiting middleware.
402
446
  */
403
447
  async rateLimitMiddleware(context, next) {
404
448
  const ip = context.req.socket.remoteAddress || "unknown";
@@ -421,16 +465,17 @@ var MikroServe = class {
421
465
  return next();
422
466
  }
423
467
  /**
424
- * Request handler for HTTP and HTTPS servers.
468
+ * @description Request handler for HTTP and HTTPS servers.
425
469
  */
426
470
  async requestHandler(req, res) {
427
471
  const start = Date.now();
428
472
  const method = req.method || "UNKNOWN";
429
473
  const url = req.url || "/unknown";
474
+ const isDebug = this.config.debug;
430
475
  try {
431
476
  this.setCorsHeaders(res, req);
432
- this.setSecurityHeaders(res, this.useHttps);
433
- if (this.debug) console.log(`${method} ${url}`);
477
+ this.setSecurityHeaders(res, this.config.useHttps);
478
+ if (isDebug) console.log(`${method} ${url}`);
434
479
  if (req.method === "OPTIONS") {
435
480
  res.statusCode = 204;
436
481
  res.end();
@@ -439,9 +484,7 @@ var MikroServe = class {
439
484
  try {
440
485
  req.body = await this.parseBody(req);
441
486
  } catch (error) {
442
- if (this.debug) {
443
- console.error("Body parsing error:", error.message);
444
- }
487
+ if (isDebug) console.error("Body parsing error:", error.message);
445
488
  return this.respond(res, {
446
489
  statusCode: 400,
447
490
  body: {
@@ -465,33 +508,22 @@ var MikroServe = class {
465
508
  statusCode: 500,
466
509
  body: {
467
510
  error: "Internal Server Error",
468
- message: this.debug ? error.message : "An unexpected error occurred"
511
+ message: isDebug ? error.message : "An unexpected error occurred"
469
512
  }
470
513
  });
471
514
  } finally {
472
- if (this.debug) {
473
- this.logDuration(start, method, url);
474
- }
515
+ if (isDebug) this.logDuration(start, method, url);
475
516
  }
476
517
  }
477
518
  /**
478
- * Writes out a clean log to represent the duration of the request.
519
+ * @description Writes out a clean log to represent the duration of the request.
479
520
  */
480
521
  logDuration(start, method, url) {
481
522
  const duration = Date.now() - start;
482
523
  console.log(`${method} ${url} completed in ${duration}ms`);
483
524
  }
484
525
  /**
485
- * Parses the request body based on content type.
486
- * @param req - HTTP request object
487
- * @returns Promise resolving to the parsed body
488
- * @throws Will throw if body cannot be parsed
489
- */
490
- /**
491
- * Parses the request body based on content type.
492
- * @param req - HTTP request object
493
- * @returns Promise resolving to the parsed body
494
- * @throws Will throw if body cannot be parsed
526
+ * @description Parses the request body based on content type.
495
527
  */
496
528
  async parseBody(req) {
497
529
  return new Promise((resolve, reject) => {
@@ -499,17 +531,17 @@ var MikroServe = class {
499
531
  let bodySize = 0;
500
532
  const MAX_BODY_SIZE = 1024 * 1024;
501
533
  let rejected = false;
534
+ const isDebug = this.config.debug;
502
535
  const contentType = req.headers["content-type"] || "";
503
- if (this.debug) {
536
+ if (isDebug) {
504
537
  console.log("Content-Type:", contentType);
505
538
  }
506
539
  req.on("data", (chunk) => {
507
540
  bodySize += chunk.length;
508
- if (this.debug)
509
- console.log(`Received chunk: ${chunk.length} bytes, total size: ${bodySize}`);
541
+ if (isDebug) console.log(`Received chunk: ${chunk.length} bytes, total size: ${bodySize}`);
510
542
  if (bodySize > MAX_BODY_SIZE && !rejected) {
511
543
  rejected = true;
512
- if (this.debug) console.log(`Body size exceeded limit: ${bodySize} > ${MAX_BODY_SIZE}`);
544
+ if (isDebug) console.log(`Body size exceeded limit: ${bodySize} > ${MAX_BODY_SIZE}`);
513
545
  reject(new Error("Request body too large"));
514
546
  return;
515
547
  }
@@ -517,7 +549,7 @@ var MikroServe = class {
517
549
  });
518
550
  req.on("end", () => {
519
551
  if (rejected) return;
520
- if (this.debug) console.log(`Request body complete: ${bodySize} bytes`);
552
+ if (isDebug) console.log(`Request body complete: ${bodySize} bytes`);
521
553
  try {
522
554
  if (bodyChunks.length > 0) {
523
555
  const bodyString = Buffer.concat(bodyChunks).toString("utf8");
@@ -549,17 +581,14 @@ var MikroServe = class {
549
581
  });
550
582
  }
551
583
  /**
552
- * CORS middleware
584
+ * @description CORS middleware.
553
585
  */
554
- // Update the setCorsHeaders method in MikroServe class to handle allowed domains
555
586
  setCorsHeaders(res, req) {
556
587
  const origin = req.headers.origin;
557
588
  const { allowedDomains = ["*"] } = this.config;
558
- if (!origin || allowedDomains.length === 0) {
559
- res.setHeader("Access-Control-Allow-Origin", "*");
560
- } else if (allowedDomains.includes("*")) {
561
- res.setHeader("Access-Control-Allow-Origin", "*");
562
- } else if (allowedDomains.includes(origin)) {
589
+ if (!origin || allowedDomains.length === 0) res.setHeader("Access-Control-Allow-Origin", "*");
590
+ else if (allowedDomains.includes("*")) res.setHeader("Access-Control-Allow-Origin", "*");
591
+ else if (allowedDomains.includes(origin)) {
563
592
  res.setHeader("Access-Control-Allow-Origin", origin);
564
593
  res.setHeader("Vary", "Origin");
565
594
  }
@@ -568,7 +597,7 @@ var MikroServe = class {
568
597
  res.setHeader("Access-Control-Max-Age", "86400");
569
598
  }
570
599
  /**
571
- * Set security headers
600
+ * @description Set security headers.
572
601
  */
573
602
  setSecurityHeaders(res, isHttps = false) {
574
603
  res.setHeader("X-Content-Type-Options", "nosniff");
@@ -581,9 +610,7 @@ var MikroServe = class {
581
610
  res.setHeader("X-XSS-Protection", "1; mode=block");
582
611
  }
583
612
  /**
584
- * Sends a response with appropriate headers.
585
- * @param res - HTTP response object
586
- * @param response - Response data and status code
613
+ * @description Sends a response with appropriate headers.
587
614
  */
588
615
  respond(res, response) {
589
616
  const headers = {
@@ -595,8 +622,7 @@ var MikroServe = class {
595
622
  else res.end(JSON.stringify(response.body));
596
623
  }
597
624
  /**
598
- * Sets up graceful shutdown handlers for a server.
599
- * @param server - The HTTP/HTTPS server to add shutdown handlers to
625
+ * @description Sets up graceful shutdown handlers for a server.
600
626
  */
601
627
  setupGracefulShutdown(server) {
602
628
  const shutdown = (error) => {
@@ -604,9 +630,7 @@ var MikroServe = class {
604
630
  if (error) console.error("Error:", error);
605
631
  server.close(() => {
606
632
  console.log("Server closed successfully");
607
- setImmediate(() => {
608
- process.exit(error ? 1 : 0);
609
- });
633
+ setImmediate(() => process.exit(error ? 1 : 0));
610
634
  });
611
635
  };
612
636
  process.on("SIGINT", () => shutdown());
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  MikroServe
3
- } from "./chunk-GGGGATKH.mjs";
3
+ } from "./chunk-6UXWR6LD.mjs";
4
4
  import "./chunk-ZFBBESGU.mjs";
5
5
  import "./chunk-KJT4SET2.mjs";
6
+ import "./chunk-RP67R3W4.mjs";
7
+ import "./chunk-CQPU7577.mjs";
6
8
  export {
7
9
  MikroServe
8
10
  };