@desaubv/quik 0.0.21 → 0.0.81

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/dist/index.cjs CHANGED
@@ -28,11 +28,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ QuikRouter: () => QuikRouter,
34
+ Router: () => Router,
35
+ Server: () => Server,
36
+ ServerInvalidRouteError: () => ServerInvalidRouteError,
33
37
  logger: () => logger
34
38
  });
35
- module.exports = __toCommonJS(index_exports);
39
+ module.exports = __toCommonJS(src_exports);
40
+
41
+ // src/core/errors/serverErrors.ts
42
+ var ServerInvalidRouteError = class extends Error {
43
+ constructor(path3) {
44
+ super(`"${path3}" is not a QuikRouter instance.`);
45
+ }
46
+ };
47
+ var ServerInvalidCronError = class extends Error {
48
+ constructor() {
49
+ super(`Invalid object, must be a QuikCron instance.`);
50
+ }
51
+ };
36
52
 
37
53
  // src/core/logger.ts
38
54
  var import_node_fs = __toESM(require("fs"), 1);
@@ -60,37 +76,122 @@ var colors = Object.fromEntries(
60
76
  );
61
77
 
62
78
  // src/core/time.ts
63
- function dateToString(date, format) {
79
+ function dateToString(date, format, timeZone) {
80
+ const formatter = new Intl.DateTimeFormat("en-US", {
81
+ timeZone,
82
+ year: "numeric",
83
+ month: "2-digit",
84
+ day: "2-digit",
85
+ hour: "2-digit",
86
+ minute: "2-digit",
87
+ second: "2-digit",
88
+ hourCycle: "h23"
89
+ });
90
+ const parts = formatter.formatToParts(date);
91
+ const values = Object.fromEntries(
92
+ parts.filter(({ type }) => type !== "literal").map(({ type, value }) => [type, value])
93
+ );
64
94
  return format.replace(/(YYYY|MM|DD|hh|mm|ss)/g, (match) => {
65
95
  switch (match) {
66
96
  case "YYYY":
67
- return date.getFullYear().toString();
97
+ return values.year || "";
68
98
  case "MM":
69
- return (date.getMonth() + 1).toString().padStart(2, "0");
99
+ return values.month || "";
70
100
  case "DD":
71
- return date.getDate().toString().padStart(2, "0");
101
+ return values.day || "";
72
102
  case "hh":
73
- return date.getHours().toString().padStart(2, "0");
103
+ return values.hour || "";
74
104
  case "mm":
75
- return date.getMinutes().toString().padStart(2, "0");
105
+ return values.minute || "";
76
106
  case "ss":
77
- return date.getSeconds().toString().padStart(2, "0");
107
+ return values.second || "";
78
108
  default:
79
109
  return match;
80
110
  }
81
111
  });
82
112
  }
113
+ function isValidTimeZone(timeZone) {
114
+ try {
115
+ new Intl.DateTimeFormat("en-US", {
116
+ timeZone
117
+ });
118
+ return true;
119
+ } catch {
120
+ return false;
121
+ }
122
+ }
123
+
124
+ // src/locales/en.json
125
+ var en_default = {
126
+ logger: {
127
+ levels: {
128
+ log: "log",
129
+ info: "info",
130
+ warning: "warning",
131
+ error: "error",
132
+ debug: "debug"
133
+ }
134
+ },
135
+ server: {
136
+ name: "server",
137
+ start: "Server running at",
138
+ routers_loaded: "routers loaded",
139
+ crons_loaded: "crons loaded",
140
+ static_loaded: "static dirs loaded",
141
+ static_warn: "directory does not exist"
142
+ },
143
+ time: {
144
+ invalidTimeZone1: "Invalid time zone:",
145
+ invalidTimeZone2: "Using system default time zone."
146
+ }
147
+ };
148
+
149
+ // src/locales/es.json
150
+ var es_default = {
151
+ logger: {
152
+ levels: {
153
+ log: "log",
154
+ info: "info",
155
+ warning: "advertencia",
156
+ error: "error",
157
+ debug: "depuraci\xF3n"
158
+ }
159
+ },
160
+ server: {
161
+ name: "servidor",
162
+ start: "Servidor corriendo en",
163
+ routers_loaded: "rutas cargadas",
164
+ crons_loaded: "crons cargados",
165
+ static_loaded: "carpetas estaticas cargadas",
166
+ static_warn: "no existe el directorio"
167
+ },
168
+ time: {
169
+ invalidTimeZone1: "Zona horaria inv\xE1lida:",
170
+ invalidTimeZone2: "Usando la zona horaria predeterminada del sistema."
171
+ }
172
+ };
173
+
174
+ // src/core/translator.ts
175
+ var locales = {
176
+ en: en_default,
177
+ es: es_default
178
+ };
179
+ function translate(language, key) {
180
+ return locales[language][key];
181
+ }
83
182
 
84
183
  // src/core/logger.ts
85
184
  var defaultConfig = {
185
+ language: "en",
86
186
  save: {
87
187
  logFilePath: null,
88
- errorFilePath: null,
89
- //"logs/error.log",
90
- warningFilePath: null
188
+ infoFilePath: null,
189
+ errorFilePath: "logs/error.log",
190
+ warningFilePath: "logs/warning.log"
91
191
  },
92
192
  color: {
93
193
  logColor: "blue",
194
+ infoColor: "green",
94
195
  errorColor: "red",
95
196
  warningColor: "yellow",
96
197
  debugColor: null
@@ -135,7 +236,17 @@ function write(level, color2, file, ...content) {
135
236
  function parseContent(level, ...body) {
136
237
  let header = "";
137
238
  if (config.format.timestampFormat) {
138
- const timestamp = dateToString(/* @__PURE__ */ new Date(), config.format.timestampFormat);
239
+ const now = /* @__PURE__ */ new Date();
240
+ const timeZone = config.format.timeZone;
241
+ let tz = timeZone;
242
+ if (timeZone && !isValidTimeZone(timeZone)) {
243
+ tz = void 0;
244
+ }
245
+ const timestamp = dateToString(
246
+ now,
247
+ config.format.timestampFormat,
248
+ tz
249
+ );
139
250
  header += `${timestamp} `;
140
251
  }
141
252
  switch (config.format.titleCase) {
@@ -167,6 +278,8 @@ function saveToFile(filePath, content) {
167
278
  }
168
279
  function mergeConfig(current, update) {
169
280
  return {
281
+ ...current,
282
+ ...update,
170
283
  save: {
171
284
  ...current.save,
172
285
  ...update.save
@@ -191,43 +304,435 @@ var logger = {
191
304
  return Object.freeze(structuredClone(config));
192
305
  },
193
306
  log(...content) {
307
+ const messages = translate(config.language, "logger");
194
308
  write(
195
- "log",
309
+ messages.levels.log,
196
310
  config.color.logColor,
197
311
  config.save.logFilePath,
198
312
  ...content
199
313
  );
200
314
  },
315
+ info(...content) {
316
+ const messages = translate(config.language, "logger");
317
+ write(
318
+ messages.levels.info,
319
+ config.color.infoColor,
320
+ config.save.infoFilePath,
321
+ ...content
322
+ );
323
+ },
201
324
  error(...content) {
325
+ const messages = translate(config.language, "logger");
202
326
  write(
203
- "error",
327
+ messages.levels.error,
204
328
  config.color.errorColor,
205
329
  config.save.errorFilePath,
206
330
  ...content
207
331
  );
208
332
  },
209
333
  warning(...content) {
334
+ const messages = translate(config.language, "logger");
210
335
  write(
211
- "warning",
336
+ messages.levels.warning,
212
337
  config.color.warningColor,
213
338
  config.save.warningFilePath,
214
339
  ...content
215
340
  );
216
341
  },
217
342
  debug(...content) {
343
+ const messages = translate(config.language, "logger");
218
344
  write(
219
- "debug",
345
+ messages.levels.debug,
220
346
  config.color.debugColor,
221
347
  null,
222
348
  ...content
223
349
  );
224
350
  },
351
+ clear() {
352
+ console.clear();
353
+ },
225
354
  custom(level, color2, file, ...content) {
226
355
  write(level, color2, file, ...content);
227
356
  }
228
357
  };
358
+
359
+ // src/core/router.ts
360
+ var import_express = require("express");
361
+ var QuikRouter = class {
362
+ router;
363
+ pendingMiddleware = [];
364
+ currentPath = "";
365
+ constructor() {
366
+ this.router = (0, import_express.Router)();
367
+ }
368
+ middleware(...handlers) {
369
+ this.pendingMiddleware.push(...handlers);
370
+ return this;
371
+ }
372
+ path(path3) {
373
+ this.currentPath = path3;
374
+ return this;
375
+ }
376
+ register(method, handler) {
377
+ this.router[method](
378
+ this.currentPath,
379
+ ...this.pendingMiddleware,
380
+ async (req, res, next) => {
381
+ try {
382
+ await handler(req, res, next);
383
+ } catch (err) {
384
+ next(err);
385
+ }
386
+ }
387
+ );
388
+ this.pendingMiddleware = [];
389
+ this.currentPath = "";
390
+ return this;
391
+ }
392
+ get(handler) {
393
+ return this.register("get", handler);
394
+ }
395
+ post(handler) {
396
+ return this.register("post", handler);
397
+ }
398
+ put(handler) {
399
+ return this.register("put", handler);
400
+ }
401
+ patch(handler) {
402
+ return this.register("patch", handler);
403
+ }
404
+ delete(handler) {
405
+ return this.register("delete", handler);
406
+ }
407
+ };
408
+ function Router() {
409
+ return new QuikRouter();
410
+ }
411
+
412
+ // src/core/server.ts
413
+ var import_express2 = __toESM(require("express"), 1);
414
+ var import_node_http = __toESM(require("http"), 1);
415
+ var import_node_path2 = __toESM(require("path"), 1);
416
+ var import_node_fs2 = __toESM(require("fs"), 1);
417
+
418
+ // src/cron/cron.ts
419
+ var import_node_cron = __toESM(require("node-cron"), 1);
420
+ var import_node_cron2 = require("node-cron");
421
+
422
+ // src/http/status.ts
423
+ var Status = {
424
+ // 1xx Informational
425
+ CONTINUE: 100,
426
+ SWITCHING_PROTOCOLS: 101,
427
+ PROCESSING: 102,
428
+ EARLY_HINTS: 103,
429
+ // 2xx Success
430
+ OK: 200,
431
+ CREATED: 201,
432
+ ACCEPTED: 202,
433
+ NON_AUTHORITATIVE_INFORMATION: 203,
434
+ NO_CONTENT: 204,
435
+ RESET_CONTENT: 205,
436
+ PARTIAL_CONTENT: 206,
437
+ MULTI_STATUS: 207,
438
+ ALREADY_REPORTED: 208,
439
+ IM_USED: 226,
440
+ // 3xx Redirection
441
+ MULTIPLE_CHOICES: 300,
442
+ MOVED_PERMANENTLY: 301,
443
+ FOUND: 302,
444
+ SEE_OTHER: 303,
445
+ NOT_MODIFIED: 304,
446
+ TEMPORARY_REDIRECT: 307,
447
+ PERMANENT_REDIRECT: 308,
448
+ // 4xx Client Errors
449
+ BAD_REQUEST: 400,
450
+ UNAUTHORIZED: 401,
451
+ PAYMENT_REQUIRED: 402,
452
+ FORBIDDEN: 403,
453
+ NOT_FOUND: 404,
454
+ METHOD_NOT_ALLOWED: 405,
455
+ NOT_ACCEPTABLE: 406,
456
+ PROXY_AUTHENTICATION_REQUIRED: 407,
457
+ REQUEST_TIMEOUT: 408,
458
+ CONFLICT: 409,
459
+ GONE: 410,
460
+ LENGTH_REQUIRED: 411,
461
+ PRECONDITION_FAILED: 412,
462
+ PAYLOAD_TOO_LARGE: 413,
463
+ URI_TOO_LONG: 414,
464
+ UNSUPPORTED_MEDIA_TYPE: 415,
465
+ RANGE_NOT_SATISFIABLE: 416,
466
+ EXPECTATION_FAILED: 417,
467
+ IM_A_TEAPOT: 418,
468
+ MISDIRECTED_REQUEST: 421,
469
+ UNPROCESSABLE_CONTENT: 422,
470
+ LOCKED: 423,
471
+ FAILED_DEPENDENCY: 424,
472
+ UPGRADE_REQUIRED: 426,
473
+ PRECONDITION_REQUIRED: 428,
474
+ TOO_MANY_REQUESTS: 429,
475
+ REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
476
+ UNAVAILABLE_FOR_LEGAL_REASONS: 451,
477
+ // 5xx Server Errors
478
+ INTERNAL_SERVER_ERROR: 500,
479
+ NOT_IMPLEMENTED: 501,
480
+ BAD_GATEWAY: 502,
481
+ SERVICE_UNAVAILABLE: 503,
482
+ GATEWAY_TIMEOUT: 504,
483
+ HTTP_VERSION_NOT_SUPPORTED: 505,
484
+ VARIANT_ALSO_NEGOTIATES: 506,
485
+ INSUFFICIENT_STORAGE: 507,
486
+ LOOP_DETECTED: 508,
487
+ NOT_EXTENDED: 510,
488
+ NETWORK_AUTHENTICATION_REQUIRED: 511
489
+ };
490
+
491
+ // src/core/handlers/notFoundHandler.ts
492
+ var QuikNotFoundHandler = (req, res) => {
493
+ res.status(Status.NOT_FOUND).json({
494
+ error: "Not Found",
495
+ message: `Route ${req.method} ${req.originalUrl} not found`
496
+ });
497
+ };
498
+
499
+ // src/core/handlers/httpErrorHandler.ts
500
+ var QuikErrorHandler = (err, req, res, next) => {
501
+ logger.error(err);
502
+ if (res.headersSent) {
503
+ return next(err);
504
+ }
505
+ res.status(Status.INTERNAL_SERVER_ERROR).json({
506
+ error: "Internal Server Error"
507
+ });
508
+ };
509
+
510
+ // src/core/server.ts
511
+ var defaultConfig2 = {
512
+ language: "en",
513
+ bodyParser: {
514
+ type: "json"
515
+ },
516
+ http: {
517
+ port: 8080
518
+ },
519
+ express: {}
520
+ };
521
+ var defaultNotFoundHandler = QuikNotFoundHandler;
522
+ var defaultErrorHandler = QuikErrorHandler;
523
+ var QuikServer = class {
524
+ app;
525
+ httpServer;
526
+ middlewares = [];
527
+ routes = {};
528
+ staticDirs = [];
529
+ crons = [];
530
+ notFoundHandler;
531
+ errorHandler;
532
+ config;
533
+ constructor() {
534
+ this.app = (0, import_express2.default)();
535
+ this.config = structuredClone(defaultConfig2);
536
+ this.httpServer = import_node_http.default.createServer(
537
+ this.app
538
+ );
539
+ this.notFoundHandler = defaultNotFoundHandler;
540
+ this.errorHandler = defaultErrorHandler;
541
+ }
542
+ setConfig(config2) {
543
+ this.config = {
544
+ ...this.config,
545
+ ...config2,
546
+ http: {
547
+ ...this.config.http,
548
+ ...config2.http
549
+ },
550
+ express: {
551
+ ...this.config.express,
552
+ ...config2.express
553
+ }
554
+ };
555
+ if (config2.timeZone && !isValidTimeZone(config2.timeZone)) {
556
+ const messages = translate(this.config.language, "time");
557
+ logger.warning(
558
+ `${messages.invalidTimeZone1} ${config2.timeZone}. ${messages.invalidTimeZone2}`
559
+ );
560
+ }
561
+ return this;
562
+ }
563
+ setNotFoundHandler(handler) {
564
+ if (!handler) {
565
+ this.notFoundHandler = void 0;
566
+ return this;
567
+ }
568
+ this.notFoundHandler = handler;
569
+ return this;
570
+ }
571
+ setErrorHandler(handler) {
572
+ if (!handler) {
573
+ this.errorHandler = void 0;
574
+ return this;
575
+ }
576
+ this.errorHandler = handler;
577
+ return this;
578
+ }
579
+ addMiddleware(...middlewares) {
580
+ this.middlewares.push(
581
+ ...middlewares
582
+ );
583
+ return this;
584
+ }
585
+ addRoute(path3, router) {
586
+ if (!(router instanceof QuikRouter)) {
587
+ throw new ServerInvalidRouteError(path3);
588
+ }
589
+ if (!path3.startsWith("/"))
590
+ path3 = "/" + path3;
591
+ this.routes[path3] = router;
592
+ return this;
593
+ }
594
+ #listen() {
595
+ const { port, host } = this.config.http;
596
+ const messages = translate(this.config.language, "server");
597
+ this.httpServer.listen(
598
+ port,
599
+ host,
600
+ () => {
601
+ logger.info(`${messages.start} ${host ?? "localhost"}:${port}`);
602
+ }
603
+ );
604
+ return this;
605
+ }
606
+ addCron(cron2) {
607
+ if (cron2.constructor.name != "QuikCron") {
608
+ throw new ServerInvalidCronError();
609
+ }
610
+ this.crons.push(cron2);
611
+ return this;
612
+ }
613
+ addStaticDir(...paths) {
614
+ for (const i in paths) {
615
+ const dir = paths[i] ?? "";
616
+ const dirPath = import_node_path2.default.resolve(dir);
617
+ const exists = import_node_fs2.default.existsSync(dirPath);
618
+ if (!exists) {
619
+ const messages = translate(this.config.language, "server");
620
+ logger.warning(`[ STATIC ] "${dir}" ${messages.static_warn}`);
621
+ continue;
622
+ }
623
+ this.staticDirs.push(...paths);
624
+ }
625
+ return this;
626
+ }
627
+ #configureHTTP() {
628
+ const config2 = this.config.http;
629
+ if (config2.timeout)
630
+ this.httpServer.timeout = config2.timeout;
631
+ if (config2.keepAlive)
632
+ this.httpServer.keepAliveTimeout = config2.keepAlive;
633
+ if (config2.maxConnections)
634
+ this.httpServer.maxConnections = config2.maxConnections;
635
+ return this;
636
+ }
637
+ #configureExpress() {
638
+ const config2 = this.config.express;
639
+ if (config2.trustProxy !== void 0) {
640
+ this.app.set(
641
+ "trust proxy",
642
+ config2.trustProxy
643
+ );
644
+ }
645
+ return this;
646
+ }
647
+ #configureMiddleware() {
648
+ const bodyParser = this.config.bodyParser;
649
+ switch (bodyParser.type) {
650
+ case "json":
651
+ this.app.use(
652
+ import_express2.default.json(bodyParser.options)
653
+ );
654
+ break;
655
+ case "urlencoded":
656
+ this.app.use(
657
+ import_express2.default.urlencoded(bodyParser.options)
658
+ );
659
+ break;
660
+ case "raw":
661
+ this.app.use(
662
+ import_express2.default.raw(bodyParser.options)
663
+ );
664
+ break;
665
+ case "text":
666
+ this.app.use(
667
+ import_express2.default.text(bodyParser.options)
668
+ );
669
+ break;
670
+ }
671
+ if (this.middlewares.length > 0)
672
+ this.app.use(...this.middlewares);
673
+ return this;
674
+ }
675
+ #configureRoutes() {
676
+ for (const [path3, router] of Object.entries(this.routes)) {
677
+ this.app.use(
678
+ path3,
679
+ router.router
680
+ );
681
+ }
682
+ const messages = translate(this.config.language, "server");
683
+ logger.info(`[ ROUTER ] ${Object.entries(this.routes).length} ${messages.routers_loaded}.`);
684
+ return this;
685
+ }
686
+ #loadCrons() {
687
+ for (const cron2 of this.crons) {
688
+ cron2.start();
689
+ }
690
+ const messages = translate(this.config.language, "server");
691
+ logger.info(`[ CRON ] ${this.crons.length} ${messages.crons_loaded}.`);
692
+ return this;
693
+ }
694
+ #loadStaticDirs() {
695
+ for (const dir of this.staticDirs) {
696
+ const dirPath = import_node_path2.default.resolve(dir);
697
+ this.app.use(import_express2.default.static(dirPath));
698
+ }
699
+ const messages = translate(this.config.language, "server");
700
+ logger.info(`[ STATIC ] ${this.staticDirs.length} ${messages.static_loaded}.`);
701
+ return this;
702
+ }
703
+ #loadHandlers() {
704
+ if (this.notFoundHandler) {
705
+ this.app.use(
706
+ this.notFoundHandler
707
+ );
708
+ }
709
+ if (this.errorHandler) {
710
+ this.app.use(
711
+ this.errorHandler
712
+ );
713
+ }
714
+ }
715
+ start() {
716
+ this.#configureExpress();
717
+ this.#configureMiddleware();
718
+ this.#loadStaticDirs();
719
+ this.#configureRoutes();
720
+ this.#loadHandlers();
721
+ this.#loadCrons();
722
+ this.#configureHTTP();
723
+ this.#listen();
724
+ return this;
725
+ }
726
+ };
727
+ function Server() {
728
+ return new QuikServer();
729
+ }
229
730
  // Annotate the CommonJS export names for ESM import in node:
230
731
  0 && (module.exports = {
732
+ QuikRouter,
733
+ Router,
734
+ Server,
735
+ ServerInvalidRouteError,
231
736
  logger
232
737
  });
233
738
  //# sourceMappingURL=index.cjs.map