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