@devbro/pashmak 0.1.25 → 0.1.26

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.
@@ -583,8 +583,10 @@ var init_queue = __esm({
583
583
  db_connection: "default",
584
584
  listen_interval: 60,
585
585
  // seconds
586
- message_limit: 10
586
+ message_limit: 10,
587
587
  // messages per each fetch
588
+ max_retry_count: 5
589
+ // maximum retry count for failed messages
588
590
  };
589
591
  channels = /* @__PURE__ */ new Map();
590
592
  messageQueues = [];
@@ -593,24 +595,31 @@ var init_queue = __esm({
593
595
  await import_neko_context2.context_provider.run(async () => {
594
596
  const conn = db(this.config.db_connection);
595
597
  try {
596
- await conn.connect();
597
598
  let q = conn.getQuery();
598
- let messages = await q.table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
599
+ let messages = await conn.getQuery().table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).whereOp("retried_count", "<", this.config.max_retry_count).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
599
600
  for (let msg of messages) {
600
601
  try {
601
- let callback = this.channels.get(msg.channel);
602
- await callback(msg.message);
603
- await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
604
- status: "processed",
602
+ await conn.getQuery().table(this.config.queue_table).whereOp("id", "=", msg.id).update({
603
+ status: "processing",
605
604
  updated_at: /* @__PURE__ */ new Date(),
606
605
  last_tried_at: /* @__PURE__ */ new Date(),
607
606
  retried_count: (msg.retried_count || 0) + 1
608
607
  });
608
+ let callback = this.channels.get(msg.channel);
609
+ await callback(msg.message);
610
+ await conn.getQuery().table(this.config.queue_table).whereOp("id", "=", msg.id).update({
611
+ status: "processed",
612
+ updated_at: /* @__PURE__ */ new Date()
613
+ });
609
614
  } catch (error) {
615
+ logger().error("Error processing message:", {
616
+ error,
617
+ message_id: msg.id,
618
+ channel: msg.channel
619
+ });
610
620
  await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
611
621
  status: "failed",
612
- last_tried_at: /* @__PURE__ */ new Date(),
613
- retried_count: (msg.retried_count || 0) + 1,
622
+ updated_at: /* @__PURE__ */ new Date(),
614
623
  process_message: error.message || "Error processing message"
615
624
  });
616
625
  }
@@ -631,27 +640,21 @@ var init_queue = __esm({
631
640
  }
632
641
  async dispatch(channel, message) {
633
642
  const conn = db(this.config.db_connection);
634
- try {
635
- await conn.connect();
636
- let schema = conn.getSchema();
637
- if (await schema.tableExists(this.config.queue_table) === false) {
638
- return;
639
- }
640
- let q = conn.getQuery();
641
- await q.table(this.config.queue_table).insert({
642
- channel,
643
- message,
644
- processed: false,
645
- created_at: /* @__PURE__ */ new Date(),
646
- updated_at: /* @__PURE__ */ new Date(),
647
- last_tried_at: null,
648
- process_message: "",
649
- retried_count: 0,
650
- status: "pending"
651
- });
652
- } finally {
653
- await conn.disconnect();
643
+ let schema = conn.getSchema();
644
+ if (await schema.tableExists(this.config.queue_table) === false) {
645
+ return;
654
646
  }
647
+ let q = conn.getQuery();
648
+ await q.table(this.config.queue_table).insert({
649
+ channel,
650
+ message,
651
+ created_at: /* @__PURE__ */ new Date(),
652
+ updated_at: /* @__PURE__ */ new Date(),
653
+ last_tried_at: null,
654
+ process_message: "",
655
+ retried_count: 0,
656
+ status: "pending"
657
+ });
655
658
  }
656
659
  async registerListener(channel, callback) {
657
660
  this.channels.set(channel, callback);
@@ -491,8 +491,10 @@ var DatabaseTransport = class {
491
491
  db_connection: "default",
492
492
  listen_interval: 60,
493
493
  // seconds
494
- message_limit: 10
494
+ message_limit: 10,
495
495
  // messages per each fetch
496
+ max_retry_count: 5
497
+ // maximum retry count for failed messages
496
498
  };
497
499
  channels = /* @__PURE__ */ new Map();
498
500
  messageQueues = [];
@@ -501,24 +503,31 @@ var DatabaseTransport = class {
501
503
  await import_neko_context2.context_provider.run(async () => {
502
504
  const conn = db(this.config.db_connection);
503
505
  try {
504
- await conn.connect();
505
506
  let q = conn.getQuery();
506
- let messages = await q.table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
507
+ let messages = await conn.getQuery().table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).whereOp("retried_count", "<", this.config.max_retry_count).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
507
508
  for (let msg of messages) {
508
509
  try {
509
- let callback = this.channels.get(msg.channel);
510
- await callback(msg.message);
511
- await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
512
- status: "processed",
510
+ await conn.getQuery().table(this.config.queue_table).whereOp("id", "=", msg.id).update({
511
+ status: "processing",
513
512
  updated_at: /* @__PURE__ */ new Date(),
514
513
  last_tried_at: /* @__PURE__ */ new Date(),
515
514
  retried_count: (msg.retried_count || 0) + 1
516
515
  });
516
+ let callback = this.channels.get(msg.channel);
517
+ await callback(msg.message);
518
+ await conn.getQuery().table(this.config.queue_table).whereOp("id", "=", msg.id).update({
519
+ status: "processed",
520
+ updated_at: /* @__PURE__ */ new Date()
521
+ });
517
522
  } catch (error) {
523
+ logger().error("Error processing message:", {
524
+ error,
525
+ message_id: msg.id,
526
+ channel: msg.channel
527
+ });
518
528
  await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
519
529
  status: "failed",
520
- last_tried_at: /* @__PURE__ */ new Date(),
521
- retried_count: (msg.retried_count || 0) + 1,
530
+ updated_at: /* @__PURE__ */ new Date(),
522
531
  process_message: error.message || "Error processing message"
523
532
  });
524
533
  }
@@ -539,27 +548,21 @@ var DatabaseTransport = class {
539
548
  }
540
549
  async dispatch(channel, message) {
541
550
  const conn = db(this.config.db_connection);
542
- try {
543
- await conn.connect();
544
- let schema = conn.getSchema();
545
- if (await schema.tableExists(this.config.queue_table) === false) {
546
- return;
547
- }
548
- let q = conn.getQuery();
549
- await q.table(this.config.queue_table).insert({
550
- channel,
551
- message,
552
- processed: false,
553
- created_at: /* @__PURE__ */ new Date(),
554
- updated_at: /* @__PURE__ */ new Date(),
555
- last_tried_at: null,
556
- process_message: "",
557
- retried_count: 0,
558
- status: "pending"
559
- });
560
- } finally {
561
- await conn.disconnect();
551
+ let schema = conn.getSchema();
552
+ if (await schema.tableExists(this.config.queue_table) === false) {
553
+ return;
562
554
  }
555
+ let q = conn.getQuery();
556
+ await q.table(this.config.queue_table).insert({
557
+ channel,
558
+ message,
559
+ created_at: /* @__PURE__ */ new Date(),
560
+ updated_at: /* @__PURE__ */ new Date(),
561
+ last_tried_at: null,
562
+ process_message: "",
563
+ retried_count: 0,
564
+ status: "pending"
565
+ });
563
566
  }
564
567
  async registerListener(channel, callback) {
565
568
  this.channels.set(channel, callback);
@@ -658,8 +658,10 @@ var DatabaseTransport = class {
658
658
  db_connection: "default",
659
659
  listen_interval: 60,
660
660
  // seconds
661
- message_limit: 10
661
+ message_limit: 10,
662
662
  // messages per each fetch
663
+ max_retry_count: 5
664
+ // maximum retry count for failed messages
663
665
  };
664
666
  channels = /* @__PURE__ */ new Map();
665
667
  messageQueues = [];
@@ -668,24 +670,31 @@ var DatabaseTransport = class {
668
670
  await import_neko_context3.context_provider.run(async () => {
669
671
  const conn = db(this.config.db_connection);
670
672
  try {
671
- await conn.connect();
672
673
  let q = conn.getQuery();
673
- let messages = await q.table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
674
+ let messages = await conn.getQuery().table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).whereOp("retried_count", "<", this.config.max_retry_count).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
674
675
  for (let msg of messages) {
675
676
  try {
676
- let callback = this.channels.get(msg.channel);
677
- await callback(msg.message);
678
- await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
679
- status: "processed",
677
+ await conn.getQuery().table(this.config.queue_table).whereOp("id", "=", msg.id).update({
678
+ status: "processing",
680
679
  updated_at: /* @__PURE__ */ new Date(),
681
680
  last_tried_at: /* @__PURE__ */ new Date(),
682
681
  retried_count: (msg.retried_count || 0) + 1
683
682
  });
683
+ let callback = this.channels.get(msg.channel);
684
+ await callback(msg.message);
685
+ await conn.getQuery().table(this.config.queue_table).whereOp("id", "=", msg.id).update({
686
+ status: "processed",
687
+ updated_at: /* @__PURE__ */ new Date()
688
+ });
684
689
  } catch (error) {
690
+ logger().error("Error processing message:", {
691
+ error,
692
+ message_id: msg.id,
693
+ channel: msg.channel
694
+ });
685
695
  await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
686
696
  status: "failed",
687
- last_tried_at: /* @__PURE__ */ new Date(),
688
- retried_count: (msg.retried_count || 0) + 1,
697
+ updated_at: /* @__PURE__ */ new Date(),
689
698
  process_message: error.message || "Error processing message"
690
699
  });
691
700
  }
@@ -706,27 +715,21 @@ var DatabaseTransport = class {
706
715
  }
707
716
  async dispatch(channel, message) {
708
717
  const conn = db(this.config.db_connection);
709
- try {
710
- await conn.connect();
711
- let schema = conn.getSchema();
712
- if (await schema.tableExists(this.config.queue_table) === false) {
713
- return;
714
- }
715
- let q = conn.getQuery();
716
- await q.table(this.config.queue_table).insert({
717
- channel,
718
- message,
719
- processed: false,
720
- created_at: /* @__PURE__ */ new Date(),
721
- updated_at: /* @__PURE__ */ new Date(),
722
- last_tried_at: null,
723
- process_message: "",
724
- retried_count: 0,
725
- status: "pending"
726
- });
727
- } finally {
728
- await conn.disconnect();
718
+ let schema = conn.getSchema();
719
+ if (await schema.tableExists(this.config.queue_table) === false) {
720
+ return;
729
721
  }
722
+ let q = conn.getQuery();
723
+ await q.table(this.config.queue_table).insert({
724
+ channel,
725
+ message,
726
+ created_at: /* @__PURE__ */ new Date(),
727
+ updated_at: /* @__PURE__ */ new Date(),
728
+ last_tried_at: null,
729
+ process_message: "",
730
+ retried_count: 0,
731
+ status: "pending"
732
+ });
730
733
  }
731
734
  async registerListener(channel, callback) {
732
735
  this.channels.set(channel, callback);
package/dist/queue.d.mts CHANGED
@@ -7,6 +7,7 @@ type DatabaseTransportConfig = {
7
7
  db_connection: string;
8
8
  listen_interval: number;
9
9
  message_limit: number;
10
+ max_retry_count: number;
10
11
  };
11
12
  declare class DatabaseTransport implements QueueTransportInterface {
12
13
  private config;
package/dist/queue.mjs CHANGED
@@ -13,8 +13,10 @@ class DatabaseTransport {
13
13
  db_connection: "default",
14
14
  listen_interval: 60,
15
15
  // seconds
16
- message_limit: 10
16
+ message_limit: 10,
17
17
  // messages per each fetch
18
+ max_retry_count: 5
19
+ // maximum retry count for failed messages
18
20
  };
19
21
  channels = /* @__PURE__ */ new Map();
20
22
  messageQueues = [];
@@ -23,24 +25,31 @@ class DatabaseTransport {
23
25
  await context_provider.run(async () => {
24
26
  const conn = db(this.config.db_connection);
25
27
  try {
26
- await conn.connect();
27
28
  let q = conn.getQuery();
28
- let messages = await q.table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
29
+ let messages = await conn.getQuery().table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).whereOp("retried_count", "<", this.config.max_retry_count).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
29
30
  for (let msg of messages) {
30
31
  try {
31
- let callback = this.channels.get(msg.channel);
32
- await callback(msg.message);
33
- await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
34
- status: "processed",
32
+ await conn.getQuery().table(this.config.queue_table).whereOp("id", "=", msg.id).update({
33
+ status: "processing",
35
34
  updated_at: /* @__PURE__ */ new Date(),
36
35
  last_tried_at: /* @__PURE__ */ new Date(),
37
36
  retried_count: (msg.retried_count || 0) + 1
38
37
  });
38
+ let callback = this.channels.get(msg.channel);
39
+ await callback(msg.message);
40
+ await conn.getQuery().table(this.config.queue_table).whereOp("id", "=", msg.id).update({
41
+ status: "processed",
42
+ updated_at: /* @__PURE__ */ new Date()
43
+ });
39
44
  } catch (error) {
45
+ logger().error("Error processing message:", {
46
+ error,
47
+ message_id: msg.id,
48
+ channel: msg.channel
49
+ });
40
50
  await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
41
51
  status: "failed",
42
- last_tried_at: /* @__PURE__ */ new Date(),
43
- retried_count: (msg.retried_count || 0) + 1,
52
+ updated_at: /* @__PURE__ */ new Date(),
44
53
  process_message: error.message || "Error processing message"
45
54
  });
46
55
  }
@@ -61,27 +70,21 @@ class DatabaseTransport {
61
70
  }
62
71
  async dispatch(channel, message) {
63
72
  const conn = db(this.config.db_connection);
64
- try {
65
- await conn.connect();
66
- let schema = conn.getSchema();
67
- if (await schema.tableExists(this.config.queue_table) === false) {
68
- return;
69
- }
70
- let q = conn.getQuery();
71
- await q.table(this.config.queue_table).insert({
72
- channel,
73
- message,
74
- processed: false,
75
- created_at: /* @__PURE__ */ new Date(),
76
- updated_at: /* @__PURE__ */ new Date(),
77
- last_tried_at: null,
78
- process_message: "",
79
- retried_count: 0,
80
- status: "pending"
81
- });
82
- } finally {
83
- await conn.disconnect();
73
+ let schema = conn.getSchema();
74
+ if (await schema.tableExists(this.config.queue_table) === false) {
75
+ return;
84
76
  }
77
+ let q = conn.getQuery();
78
+ await q.table(this.config.queue_table).insert({
79
+ channel,
80
+ message,
81
+ created_at: /* @__PURE__ */ new Date(),
82
+ updated_at: /* @__PURE__ */ new Date(),
83
+ last_tried_at: null,
84
+ process_message: "",
85
+ retried_count: 0,
86
+ status: "pending"
87
+ });
85
88
  }
86
89
  async registerListener(channel, callback) {
87
90
  this.channels.set(channel, callback);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/queue.mts"],"sourcesContent":["export * from \"@devbro/neko-queue\";\nimport { QueueTransportInterface } from \"@devbro/neko-queue\";\nimport { Query } from \"@devbro/neko-sql\";\nimport { db, logger } from \"./facades.mjs\";\nimport { createRepeater } from \"@devbro/neko-helper\";\nimport { context_provider } from \"@devbro/neko-context\";\n\ntype DatabaseTransportConfig = {\n queue_table: string;\n db_connection: string;\n listen_interval: number;\n message_limit: number;\n};\n\nexport class DatabaseTransport implements QueueTransportInterface {\n private config: DatabaseTransportConfig = {\n queue_table: \"queue_messages\",\n db_connection: \"default\",\n listen_interval: 60, // seconds\n message_limit: 10, // messages per each fetch\n };\n channels = new Map<string, (message: string) => Promise<void>>();\n messageQueues: { channel: string; message: string }[] = [];\n repeater: ReturnType<typeof createRepeater>;\n\n processMessage = async () => {\n await context_provider.run(async () => {\n const conn = db(this.config.db_connection);\n try {\n await conn.connect();\n let q: Query = conn.getQuery();\n let messages = await q\n .table(this.config.queue_table)\n .whereOp(\"channel\", \"in\", Array.from(this.channels.keys()))\n .whereOp(\"status\", \"in\", [\"pending\", \"failed\"])\n .limit(this.config.message_limit)\n .orderBy(\"last_tried_at\", \"asc\")\n .get();\n for (let msg of messages) {\n try {\n let callback = this.channels.get(msg.channel)!;\n await callback(msg.message);\n // mark message as processed\n await q\n .table(this.config.queue_table)\n .whereOp(\"id\", \"=\", msg.id)\n .update({\n status: \"processed\",\n updated_at: new Date(),\n last_tried_at: new Date(),\n retried_count: (msg.retried_count || 0) + 1,\n });\n } catch (error) {\n await q\n .table(this.config.queue_table)\n .whereOp(\"id\", \"=\", msg.id)\n .update({\n status: \"failed\",\n last_tried_at: new Date(),\n retried_count: (msg.retried_count || 0) + 1,\n process_message:\n (error as Error).message || \"Error processing message\",\n });\n }\n }\n } catch (error) {\n logger().error(\"Error in DatabaseTransport listen interval:\", {\n error,\n });\n }\n });\n };\n\n constructor(config: Partial<DatabaseTransportConfig> = {}) {\n this.config = { ...this.config, ...config };\n this.repeater = createRepeater(\n this.processMessage,\n this.config.listen_interval * 1000,\n );\n }\n\n async dispatch(channel: string, message: string): Promise<void> {\n const conn = db(this.config.db_connection);\n try {\n await conn.connect();\n let schema = conn.getSchema();\n if ((await schema.tableExists(this.config.queue_table)) === false) {\n return;\n }\n let q: Query = conn.getQuery();\n await q.table(this.config.queue_table).insert({\n channel: channel,\n message: message,\n processed: false,\n created_at: new Date(),\n updated_at: new Date(),\n last_tried_at: null,\n process_message: \"\",\n retried_count: 0,\n status: \"pending\",\n });\n } finally {\n await conn.disconnect();\n }\n }\n\n async registerListener(\n channel: string,\n callback: (message: string) => Promise<void>,\n ): Promise<void> {\n this.channels.set(channel, callback);\n }\n\n async startListening(): Promise<void> {\n this.repeater.start();\n }\n\n async stopListening(): Promise<void> {\n this.repeater.stop();\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/queue.mts"],"sourcesContent":["export * from \"@devbro/neko-queue\";\nimport { QueueTransportInterface } from \"@devbro/neko-queue\";\nimport { Query } from \"@devbro/neko-sql\";\nimport { db, logger } from \"./facades.mjs\";\nimport { createRepeater } from \"@devbro/neko-helper\";\nimport { context_provider } from \"@devbro/neko-context\";\n\ntype DatabaseTransportConfig = {\n queue_table: string;\n db_connection: string;\n listen_interval: number;\n message_limit: number;\n max_retry_count: number;\n};\n\nexport class DatabaseTransport implements QueueTransportInterface {\n private config: DatabaseTransportConfig = {\n queue_table: \"queue_messages\",\n db_connection: \"default\",\n listen_interval: 60, // seconds\n message_limit: 10, // messages per each fetch\n max_retry_count: 5, // maximum retry count for failed messages\n };\n channels = new Map<string, (message: string) => Promise<void>>();\n messageQueues: { channel: string; message: string }[] = [];\n repeater: ReturnType<typeof createRepeater>;\n\n processMessage = async () => {\n await context_provider.run(async () => {\n const conn = db(this.config.db_connection);\n try {\n let q: Query = conn.getQuery();\n let messages = await conn\n .getQuery()\n .table(this.config.queue_table)\n .whereOp(\"channel\", \"in\", Array.from(this.channels.keys()))\n .whereOp(\"status\", \"in\", [\"pending\", \"failed\"])\n .whereOp(\"retried_count\", \"<\", this.config.max_retry_count)\n .limit(this.config.message_limit)\n .orderBy(\"last_tried_at\", \"asc\")\n .get();\n for (let msg of messages) {\n try {\n await conn\n .getQuery()\n .table(this.config.queue_table)\n .whereOp(\"id\", \"=\", msg.id)\n .update({\n status: \"processing\",\n updated_at: new Date(),\n last_tried_at: new Date(),\n retried_count: (msg.retried_count || 0) + 1,\n });\n let callback = this.channels.get(msg.channel)!;\n await callback(msg.message);\n // mark message as processed\n await conn\n .getQuery()\n .table(this.config.queue_table)\n .whereOp(\"id\", \"=\", msg.id)\n .update({\n status: \"processed\",\n updated_at: new Date(),\n });\n } catch (error) {\n logger().error(\"Error processing message:\", {\n error,\n message_id: msg.id,\n channel: msg.channel,\n });\n\n await q\n .table(this.config.queue_table)\n .whereOp(\"id\", \"=\", msg.id)\n .update({\n status: \"failed\",\n updated_at: new Date(),\n process_message:\n (error as Error).message || \"Error processing message\",\n });\n }\n }\n } catch (error) {\n logger().error(\"Error in DatabaseTransport listen interval:\", {\n error,\n });\n }\n });\n };\n\n constructor(config: Partial<DatabaseTransportConfig> = {}) {\n this.config = { ...this.config, ...config };\n this.repeater = createRepeater(\n this.processMessage,\n this.config.listen_interval * 1000,\n );\n }\n\n async dispatch(channel: string, message: string): Promise<void> {\n const conn = db(this.config.db_connection);\n let schema = conn.getSchema();\n if ((await schema.tableExists(this.config.queue_table)) === false) {\n return;\n }\n let q: Query = conn.getQuery();\n await q.table(this.config.queue_table).insert({\n channel: channel,\n message: message,\n created_at: new Date(),\n updated_at: new Date(),\n last_tried_at: null,\n process_message: \"\",\n retried_count: 0,\n status: \"pending\",\n });\n }\n\n async registerListener(\n channel: string,\n callback: (message: string) => Promise<void>,\n ): Promise<void> {\n this.channels.set(channel, callback);\n }\n\n async startListening(): Promise<void> {\n this.repeater.start();\n }\n\n async stopListening(): Promise<void> {\n this.repeater.stop();\n }\n}\n"],"mappings":";;AAAA,cAAc;AAGd,SAAS,IAAI,cAAc;AAC3B,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AAU1B,MAAM,kBAAqD;AAAA,EAflE,OAekE;AAAA;AAAA;AAAA,EACxD,SAAkC;AAAA,IACxC,aAAa;AAAA,IACb,eAAe;AAAA,IACf,iBAAiB;AAAA;AAAA,IACjB,eAAe;AAAA;AAAA,IACf,iBAAiB;AAAA;AAAA,EACnB;AAAA,EACA,WAAW,oBAAI,IAAgD;AAAA,EAC/D,gBAAwD,CAAC;AAAA,EACzD;AAAA,EAEA,iBAAiB,mCAAY;AAC3B,UAAM,iBAAiB,IAAI,YAAY;AACrC,YAAM,OAAO,GAAG,KAAK,OAAO,aAAa;AACzC,UAAI;AACF,YAAI,IAAW,KAAK,SAAS;AAC7B,YAAI,WAAW,MAAM,KAClB,SAAS,EACT,MAAM,KAAK,OAAO,WAAW,EAC7B,QAAQ,WAAW,MAAM,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC,CAAC,EACzD,QAAQ,UAAU,MAAM,CAAC,WAAW,QAAQ,CAAC,EAC7C,QAAQ,iBAAiB,KAAK,KAAK,OAAO,eAAe,EACzD,MAAM,KAAK,OAAO,aAAa,EAC/B,QAAQ,iBAAiB,KAAK,EAC9B,IAAI;AACP,iBAAS,OAAO,UAAU;AACxB,cAAI;AACF,kBAAM,KACH,SAAS,EACT,MAAM,KAAK,OAAO,WAAW,EAC7B,QAAQ,MAAM,KAAK,IAAI,EAAE,EACzB,OAAO;AAAA,cACN,QAAQ;AAAA,cACR,YAAY,oBAAI,KAAK;AAAA,cACrB,eAAe,oBAAI,KAAK;AAAA,cACxB,gBAAgB,IAAI,iBAAiB,KAAK;AAAA,YAC5C,CAAC;AACH,gBAAI,WAAW,KAAK,SAAS,IAAI,IAAI,OAAO;AAC5C,kBAAM,SAAS,IAAI,OAAO;AAE1B,kBAAM,KACH,SAAS,EACT,MAAM,KAAK,OAAO,WAAW,EAC7B,QAAQ,MAAM,KAAK,IAAI,EAAE,EACzB,OAAO;AAAA,cACN,QAAQ;AAAA,cACR,YAAY,oBAAI,KAAK;AAAA,YACvB,CAAC;AAAA,UACL,SAAS,OAAO;AACd,mBAAO,EAAE,MAAM,6BAA6B;AAAA,cAC1C;AAAA,cACA,YAAY,IAAI;AAAA,cAChB,SAAS,IAAI;AAAA,YACf,CAAC;AAED,kBAAM,EACH,MAAM,KAAK,OAAO,WAAW,EAC7B,QAAQ,MAAM,KAAK,IAAI,EAAE,EACzB,OAAO;AAAA,cACN,QAAQ;AAAA,cACR,YAAY,oBAAI,KAAK;AAAA,cACrB,iBACG,MAAgB,WAAW;AAAA,YAChC,CAAC;AAAA,UACL;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,eAAO,EAAE,MAAM,+CAA+C;AAAA,UAC5D;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH,GA7DiB;AAAA,EA+DjB,YAAY,SAA2C,CAAC,GAAG;AACzD,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,OAAO;AAC1C,SAAK,WAAW;AAAA,MACd,KAAK;AAAA,MACL,KAAK,OAAO,kBAAkB;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,SAAiB,SAAgC;AAC9D,UAAM,OAAO,GAAG,KAAK,OAAO,aAAa;AACzC,QAAI,SAAS,KAAK,UAAU;AAC5B,QAAK,MAAM,OAAO,YAAY,KAAK,OAAO,WAAW,MAAO,OAAO;AACjE;AAAA,IACF;AACA,QAAI,IAAW,KAAK,SAAS;AAC7B,UAAM,EAAE,MAAM,KAAK,OAAO,WAAW,EAAE,OAAO;AAAA,MAC5C;AAAA,MACA;AAAA,MACA,YAAY,oBAAI,KAAK;AAAA,MACrB,YAAY,oBAAI,KAAK;AAAA,MACrB,eAAe;AAAA,MACf,iBAAiB;AAAA,MACjB,eAAe;AAAA,MACf,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,iBACJ,SACA,UACe;AACf,SAAK,SAAS,IAAI,SAAS,QAAQ;AAAA,EACrC;AAAA,EAEA,MAAM,iBAAgC;AACpC,SAAK,SAAS,MAAM;AAAA,EACtB;AAAA,EAEA,MAAM,gBAA+B;AACnC,SAAK,SAAS,KAAK;AAAA,EACrB;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devbro/pashmak",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "description": "testing application for the entire repo",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",