@desaubv/quik 0.0.31 → 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,12 +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,
33
34
  Router: () => Router,
35
+ Server: () => Server,
36
+ ServerInvalidRouteError: () => ServerInvalidRouteError,
34
37
  logger: () => logger
35
38
  });
36
- 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
+ };
37
52
 
38
53
  // src/core/logger.ts
39
54
  var import_node_fs = __toESM(require("fs"), 1);
@@ -61,37 +76,122 @@ var colors = Object.fromEntries(
61
76
  );
62
77
 
63
78
  // src/core/time.ts
64
- 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
+ );
65
94
  return format.replace(/(YYYY|MM|DD|hh|mm|ss)/g, (match) => {
66
95
  switch (match) {
67
96
  case "YYYY":
68
- return date.getFullYear().toString();
97
+ return values.year || "";
69
98
  case "MM":
70
- return (date.getMonth() + 1).toString().padStart(2, "0");
99
+ return values.month || "";
71
100
  case "DD":
72
- return date.getDate().toString().padStart(2, "0");
101
+ return values.day || "";
73
102
  case "hh":
74
- return date.getHours().toString().padStart(2, "0");
103
+ return values.hour || "";
75
104
  case "mm":
76
- return date.getMinutes().toString().padStart(2, "0");
105
+ return values.minute || "";
77
106
  case "ss":
78
- return date.getSeconds().toString().padStart(2, "0");
107
+ return values.second || "";
79
108
  default:
80
109
  return match;
81
110
  }
82
111
  });
83
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
+ }
84
182
 
85
183
  // src/core/logger.ts
86
184
  var defaultConfig = {
185
+ language: "en",
87
186
  save: {
88
187
  logFilePath: null,
89
- errorFilePath: null,
90
- //"logs/error.log",
91
- warningFilePath: null
188
+ infoFilePath: null,
189
+ errorFilePath: "logs/error.log",
190
+ warningFilePath: "logs/warning.log"
92
191
  },
93
192
  color: {
94
193
  logColor: "blue",
194
+ infoColor: "green",
95
195
  errorColor: "red",
96
196
  warningColor: "yellow",
97
197
  debugColor: null
@@ -136,7 +236,17 @@ function write(level, color2, file, ...content) {
136
236
  function parseContent(level, ...body) {
137
237
  let header = "";
138
238
  if (config.format.timestampFormat) {
139
- 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
+ );
140
250
  header += `${timestamp} `;
141
251
  }
142
252
  switch (config.format.titleCase) {
@@ -168,6 +278,8 @@ function saveToFile(filePath, content) {
168
278
  }
169
279
  function mergeConfig(current, update) {
170
280
  return {
281
+ ...current,
282
+ ...update,
171
283
  save: {
172
284
  ...current.save,
173
285
  ...update.save
@@ -192,37 +304,53 @@ var logger = {
192
304
  return Object.freeze(structuredClone(config));
193
305
  },
194
306
  log(...content) {
307
+ const messages = translate(config.language, "logger");
195
308
  write(
196
- "log",
309
+ messages.levels.log,
197
310
  config.color.logColor,
198
311
  config.save.logFilePath,
199
312
  ...content
200
313
  );
201
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
+ },
202
324
  error(...content) {
325
+ const messages = translate(config.language, "logger");
203
326
  write(
204
- "error",
327
+ messages.levels.error,
205
328
  config.color.errorColor,
206
329
  config.save.errorFilePath,
207
330
  ...content
208
331
  );
209
332
  },
210
333
  warning(...content) {
334
+ const messages = translate(config.language, "logger");
211
335
  write(
212
- "warning",
336
+ messages.levels.warning,
213
337
  config.color.warningColor,
214
338
  config.save.warningFilePath,
215
339
  ...content
216
340
  );
217
341
  },
218
342
  debug(...content) {
343
+ const messages = translate(config.language, "logger");
219
344
  write(
220
- "debug",
345
+ messages.levels.debug,
221
346
  config.color.debugColor,
222
347
  null,
223
348
  ...content
224
349
  );
225
350
  },
351
+ clear() {
352
+ console.clear();
353
+ },
226
354
  custom(level, color2, file, ...content) {
227
355
  write(level, color2, file, ...content);
228
356
  }
@@ -230,10 +358,10 @@ var logger = {
230
358
 
231
359
  // src/core/router.ts
232
360
  var import_express = require("express");
233
- var Router = class {
361
+ var QuikRouter = class {
234
362
  router;
235
363
  pendingMiddleware = [];
236
- pnedingPath = "";
364
+ currentPath = "";
237
365
  constructor() {
238
366
  this.router = (0, import_express.Router)();
239
367
  }
@@ -241,13 +369,13 @@ var Router = class {
241
369
  this.pendingMiddleware.push(...handlers);
242
370
  return this;
243
371
  }
244
- path(path2) {
245
- this.pnedingPath = path2;
372
+ path(path3) {
373
+ this.currentPath = path3;
246
374
  return this;
247
375
  }
248
376
  register(method, handler) {
249
377
  this.router[method](
250
- this.pnedingPath,
378
+ this.currentPath,
251
379
  ...this.pendingMiddleware,
252
380
  async (req, res, next) => {
253
381
  try {
@@ -258,7 +386,7 @@ var Router = class {
258
386
  }
259
387
  );
260
388
  this.pendingMiddleware = [];
261
- this.pnedingPath = "";
389
+ this.currentPath = "";
262
390
  return this;
263
391
  }
264
392
  get(handler) {
@@ -277,9 +405,334 @@ var Router = class {
277
405
  return this.register("delete", handler);
278
406
  }
279
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
+ }
280
730
  // Annotate the CommonJS export names for ESM import in node:
281
731
  0 && (module.exports = {
732
+ QuikRouter,
282
733
  Router,
734
+ Server,
735
+ ServerInvalidRouteError,
283
736
  logger
284
737
  });
285
738
  //# sourceMappingURL=index.cjs.map