cadenlane-cli-2 1.0.0

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.
Files changed (206) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE +21 -0
  3. package/README.md +333 -0
  4. package/bin.js +2 -0
  5. package/dist/application/config/config.manager.d.ts +62 -0
  6. package/dist/application/config/config.manager.d.ts.map +1 -0
  7. package/dist/application/config/config.manager.js +146 -0
  8. package/dist/application/config/config.manager.js.map +1 -0
  9. package/dist/application/services/application.service.d.ts +35 -0
  10. package/dist/application/services/application.service.d.ts.map +1 -0
  11. package/dist/application/services/application.service.js +174 -0
  12. package/dist/application/services/application.service.js.map +1 -0
  13. package/dist/application/services/download.service.d.ts +27 -0
  14. package/dist/application/services/download.service.d.ts.map +1 -0
  15. package/dist/application/services/download.service.js +197 -0
  16. package/dist/application/services/download.service.js.map +1 -0
  17. package/dist/application/services/file-naming.service.d.ts +34 -0
  18. package/dist/application/services/file-naming.service.d.ts.map +1 -0
  19. package/dist/application/services/file-naming.service.js +142 -0
  20. package/dist/application/services/file-naming.service.js.map +1 -0
  21. package/dist/application/services/queue.service.d.ts +53 -0
  22. package/dist/application/services/queue.service.d.ts.map +1 -0
  23. package/dist/application/services/queue.service.js +82 -0
  24. package/dist/application/services/queue.service.js.map +1 -0
  25. package/dist/cli/commands/start.command.d.ts +39 -0
  26. package/dist/cli/commands/start.command.d.ts.map +1 -0
  27. package/dist/cli/commands/start.command.js +196 -0
  28. package/dist/cli/commands/start.command.js.map +1 -0
  29. package/dist/cli/index.d.ts +3 -0
  30. package/dist/cli/index.d.ts.map +1 -0
  31. package/dist/cli/index.js +86 -0
  32. package/dist/cli/index.js.map +1 -0
  33. package/dist/domain/constants/config.constants.d.ts +54 -0
  34. package/dist/domain/constants/config.constants.d.ts.map +1 -0
  35. package/dist/domain/constants/config.constants.js +142 -0
  36. package/dist/domain/constants/config.constants.js.map +1 -0
  37. package/dist/domain/dtos/index.d.ts +4 -0
  38. package/dist/domain/dtos/index.d.ts.map +1 -0
  39. package/dist/domain/dtos/index.js +10 -0
  40. package/dist/domain/dtos/index.js.map +1 -0
  41. package/dist/domain/dtos/log-entry.dto.d.ts +15 -0
  42. package/dist/domain/dtos/log-entry.dto.d.ts.map +1 -0
  43. package/dist/domain/dtos/log-entry.dto.js +64 -0
  44. package/dist/domain/dtos/log-entry.dto.js.map +1 -0
  45. package/dist/domain/dtos/message.dto.d.ts +27 -0
  46. package/dist/domain/dtos/message.dto.d.ts.map +1 -0
  47. package/dist/domain/dtos/message.dto.js +140 -0
  48. package/dist/domain/dtos/message.dto.js.map +1 -0
  49. package/dist/domain/dtos/queue-message.dto.d.ts +10 -0
  50. package/dist/domain/dtos/queue-message.dto.d.ts.map +1 -0
  51. package/dist/domain/dtos/queue-message.dto.js +39 -0
  52. package/dist/domain/dtos/queue-message.dto.js.map +1 -0
  53. package/dist/domain/entities/cli-instance.entity.d.ts +55 -0
  54. package/dist/domain/entities/cli-instance.entity.d.ts.map +1 -0
  55. package/dist/domain/entities/cli-instance.entity.js +132 -0
  56. package/dist/domain/entities/cli-instance.entity.js.map +1 -0
  57. package/dist/domain/entities/index.d.ts +3 -0
  58. package/dist/domain/entities/index.d.ts.map +1 -0
  59. package/dist/domain/entities/index.js +8 -0
  60. package/dist/domain/entities/index.js.map +1 -0
  61. package/dist/domain/entities/log-entry.entity.d.ts +60 -0
  62. package/dist/domain/entities/log-entry.entity.d.ts.map +1 -0
  63. package/dist/domain/entities/log-entry.entity.js +101 -0
  64. package/dist/domain/entities/log-entry.entity.js.map +1 -0
  65. package/dist/domain/entities/message.entity.d.ts +64 -0
  66. package/dist/domain/entities/message.entity.d.ts.map +1 -0
  67. package/dist/domain/entities/message.entity.js +110 -0
  68. package/dist/domain/entities/message.entity.js.map +1 -0
  69. package/dist/domain/enums/error-category.enum.d.ts +11 -0
  70. package/dist/domain/enums/error-category.enum.d.ts.map +1 -0
  71. package/dist/domain/enums/error-category.enum.js +15 -0
  72. package/dist/domain/enums/error-category.enum.js.map +1 -0
  73. package/dist/domain/enums/index.d.ts +4 -0
  74. package/dist/domain/enums/index.d.ts.map +1 -0
  75. package/dist/domain/enums/index.js +10 -0
  76. package/dist/domain/enums/index.js.map +1 -0
  77. package/dist/domain/enums/log-level.enum.d.ts +11 -0
  78. package/dist/domain/enums/log-level.enum.d.ts.map +1 -0
  79. package/dist/domain/enums/log-level.enum.js +15 -0
  80. package/dist/domain/enums/log-level.enum.js.map +1 -0
  81. package/dist/domain/enums/message-status.enum.d.ts +11 -0
  82. package/dist/domain/enums/message-status.enum.d.ts.map +1 -0
  83. package/dist/domain/enums/message-status.enum.js +15 -0
  84. package/dist/domain/enums/message-status.enum.js.map +1 -0
  85. package/dist/domain/interfaces/adapters/ifilesystem.adapter.d.ts +34 -0
  86. package/dist/domain/interfaces/adapters/ifilesystem.adapter.d.ts.map +1 -0
  87. package/dist/domain/interfaces/adapters/ifilesystem.adapter.js +3 -0
  88. package/dist/domain/interfaces/adapters/ifilesystem.adapter.js.map +1 -0
  89. package/dist/domain/interfaces/adapters/ihttp.adapter.d.ts +22 -0
  90. package/dist/domain/interfaces/adapters/ihttp.adapter.d.ts.map +1 -0
  91. package/dist/domain/interfaces/adapters/ihttp.adapter.js +3 -0
  92. package/dist/domain/interfaces/adapters/ihttp.adapter.js.map +1 -0
  93. package/dist/domain/interfaces/adapters/index.d.ts +4 -0
  94. package/dist/domain/interfaces/adapters/index.d.ts.map +1 -0
  95. package/dist/domain/interfaces/adapters/index.js +3 -0
  96. package/dist/domain/interfaces/adapters/index.js.map +1 -0
  97. package/dist/domain/interfaces/adapters/isupabase.adapter.d.ts +27 -0
  98. package/dist/domain/interfaces/adapters/isupabase.adapter.d.ts.map +1 -0
  99. package/dist/domain/interfaces/adapters/isupabase.adapter.js +3 -0
  100. package/dist/domain/interfaces/adapters/isupabase.adapter.js.map +1 -0
  101. package/dist/domain/interfaces/repositories/ilog.repository.d.ts +32 -0
  102. package/dist/domain/interfaces/repositories/ilog.repository.d.ts.map +1 -0
  103. package/dist/domain/interfaces/repositories/ilog.repository.js +3 -0
  104. package/dist/domain/interfaces/repositories/ilog.repository.js.map +1 -0
  105. package/dist/domain/interfaces/repositories/imessage.repository.d.ts +39 -0
  106. package/dist/domain/interfaces/repositories/imessage.repository.d.ts.map +1 -0
  107. package/dist/domain/interfaces/repositories/imessage.repository.js +3 -0
  108. package/dist/domain/interfaces/repositories/imessage.repository.js.map +1 -0
  109. package/dist/domain/interfaces/repositories/index.d.ts +4 -0
  110. package/dist/domain/interfaces/repositories/index.d.ts.map +1 -0
  111. package/dist/domain/interfaces/repositories/index.js +3 -0
  112. package/dist/domain/interfaces/repositories/index.js.map +1 -0
  113. package/dist/domain/interfaces/repositories/iqueue.repository.d.ts +75 -0
  114. package/dist/domain/interfaces/repositories/iqueue.repository.d.ts.map +1 -0
  115. package/dist/domain/interfaces/repositories/iqueue.repository.js +3 -0
  116. package/dist/domain/interfaces/repositories/iqueue.repository.js.map +1 -0
  117. package/dist/domain/interfaces/services/idownload.service.d.ts +28 -0
  118. package/dist/domain/interfaces/services/idownload.service.d.ts.map +1 -0
  119. package/dist/domain/interfaces/services/idownload.service.js +3 -0
  120. package/dist/domain/interfaces/services/idownload.service.js.map +1 -0
  121. package/dist/domain/interfaces/services/iqueue.service.d.ts +35 -0
  122. package/dist/domain/interfaces/services/iqueue.service.d.ts.map +1 -0
  123. package/dist/domain/interfaces/services/iqueue.service.js +3 -0
  124. package/dist/domain/interfaces/services/iqueue.service.js.map +1 -0
  125. package/dist/domain/services/path-resolver.service.d.ts +94 -0
  126. package/dist/domain/services/path-resolver.service.d.ts.map +1 -0
  127. package/dist/domain/services/path-resolver.service.js +332 -0
  128. package/dist/domain/services/path-resolver.service.js.map +1 -0
  129. package/dist/domain/validators/index.d.ts +4 -0
  130. package/dist/domain/validators/index.d.ts.map +1 -0
  131. package/dist/domain/validators/index.js +10 -0
  132. package/dist/domain/validators/index.js.map +1 -0
  133. package/dist/domain/validators/message.validator.d.ts +20 -0
  134. package/dist/domain/validators/message.validator.d.ts.map +1 -0
  135. package/dist/domain/validators/message.validator.js +31 -0
  136. package/dist/domain/validators/message.validator.js.map +1 -0
  137. package/dist/domain/validators/path.validator.d.ts +44 -0
  138. package/dist/domain/validators/path.validator.d.ts.map +1 -0
  139. package/dist/domain/validators/path.validator.js +156 -0
  140. package/dist/domain/validators/path.validator.js.map +1 -0
  141. package/dist/domain/validators/url.validator.d.ts +19 -0
  142. package/dist/domain/validators/url.validator.d.ts.map +1 -0
  143. package/dist/domain/validators/url.validator.js +46 -0
  144. package/dist/domain/validators/url.validator.js.map +1 -0
  145. package/dist/index.d.ts +11 -0
  146. package/dist/index.d.ts.map +1 -0
  147. package/dist/index.js +27 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/infrastructure/adapters/filesystem.adapter.d.ts +35 -0
  150. package/dist/infrastructure/adapters/filesystem.adapter.d.ts.map +1 -0
  151. package/dist/infrastructure/adapters/filesystem.adapter.js +103 -0
  152. package/dist/infrastructure/adapters/filesystem.adapter.js.map +1 -0
  153. package/dist/infrastructure/adapters/http.adapter.d.ts +15 -0
  154. package/dist/infrastructure/adapters/http.adapter.d.ts.map +1 -0
  155. package/dist/infrastructure/adapters/http.adapter.js +80 -0
  156. package/dist/infrastructure/adapters/http.adapter.js.map +1 -0
  157. package/dist/infrastructure/adapters/index.d.ts +4 -0
  158. package/dist/infrastructure/adapters/index.d.ts.map +1 -0
  159. package/dist/infrastructure/adapters/index.js +10 -0
  160. package/dist/infrastructure/adapters/index.js.map +1 -0
  161. package/dist/infrastructure/adapters/pgmq.adapter.d.ts +29 -0
  162. package/dist/infrastructure/adapters/pgmq.adapter.d.ts.map +1 -0
  163. package/dist/infrastructure/adapters/pgmq.adapter.js +84 -0
  164. package/dist/infrastructure/adapters/pgmq.adapter.js.map +1 -0
  165. package/dist/infrastructure/adapters/supabase.adapter.d.ts +79 -0
  166. package/dist/infrastructure/adapters/supabase.adapter.d.ts.map +1 -0
  167. package/dist/infrastructure/adapters/supabase.adapter.js +97 -0
  168. package/dist/infrastructure/adapters/supabase.adapter.js.map +1 -0
  169. package/dist/infrastructure/database/supabase.client.d.ts +20 -0
  170. package/dist/infrastructure/database/supabase.client.d.ts.map +1 -0
  171. package/dist/infrastructure/database/supabase.client.js +36 -0
  172. package/dist/infrastructure/database/supabase.client.js.map +1 -0
  173. package/dist/infrastructure/di/container.d.ts +18 -0
  174. package/dist/infrastructure/di/container.d.ts.map +1 -0
  175. package/dist/infrastructure/di/container.js +103 -0
  176. package/dist/infrastructure/di/container.js.map +1 -0
  177. package/dist/infrastructure/repositories/cli-instance.repository.d.ts +64 -0
  178. package/dist/infrastructure/repositories/cli-instance.repository.d.ts.map +1 -0
  179. package/dist/infrastructure/repositories/cli-instance.repository.js +154 -0
  180. package/dist/infrastructure/repositories/cli-instance.repository.js.map +1 -0
  181. package/dist/infrastructure/repositories/config.repository.d.ts +52 -0
  182. package/dist/infrastructure/repositories/config.repository.d.ts.map +1 -0
  183. package/dist/infrastructure/repositories/config.repository.js +130 -0
  184. package/dist/infrastructure/repositories/config.repository.js.map +1 -0
  185. package/dist/infrastructure/repositories/index.d.ts +4 -0
  186. package/dist/infrastructure/repositories/index.d.ts.map +1 -0
  187. package/dist/infrastructure/repositories/index.js +10 -0
  188. package/dist/infrastructure/repositories/index.js.map +1 -0
  189. package/dist/infrastructure/repositories/log.repository.d.ts +44 -0
  190. package/dist/infrastructure/repositories/log.repository.d.ts.map +1 -0
  191. package/dist/infrastructure/repositories/log.repository.js +108 -0
  192. package/dist/infrastructure/repositories/log.repository.js.map +1 -0
  193. package/dist/infrastructure/repositories/message.repository.d.ts +51 -0
  194. package/dist/infrastructure/repositories/message.repository.d.ts.map +1 -0
  195. package/dist/infrastructure/repositories/message.repository.js +161 -0
  196. package/dist/infrastructure/repositories/message.repository.js.map +1 -0
  197. package/dist/infrastructure/repositories/queue.repository.d.ts +69 -0
  198. package/dist/infrastructure/repositories/queue.repository.d.ts.map +1 -0
  199. package/dist/infrastructure/repositories/queue.repository.js +130 -0
  200. package/dist/infrastructure/repositories/queue.repository.js.map +1 -0
  201. package/dist/infrastructure/utils/connection-health.util.d.ts +23 -0
  202. package/dist/infrastructure/utils/connection-health.util.d.ts.map +1 -0
  203. package/dist/infrastructure/utils/connection-health.util.js +64 -0
  204. package/dist/infrastructure/utils/connection-health.util.js.map +1 -0
  205. package/package.json +105 -0
  206. package/pm2.config.js +104 -0
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.QueueRepository = void 0;
16
+ const tsyringe_1 = require("tsyringe");
17
+ const pgmq_adapter_1 = require("../adapters/pgmq.adapter");
18
+ /**
19
+ * Queue Repository
20
+ * Handles PGMQ queue operations using direct PostgreSQL connection
21
+ */
22
+ let QueueRepository = class QueueRepository {
23
+ adapter;
24
+ constructor(adapter) {
25
+ this.adapter = adapter;
26
+ }
27
+ /**
28
+ * Reads a message from the queue (non-blocking)
29
+ * @param queueName - Name of the queue
30
+ * @param visibilityTimeoutSeconds - Visibility timeout in seconds
31
+ * @returns PGMQ message or null if queue is empty
32
+ */
33
+ async readMessage(queueName, visibilityTimeoutSeconds) {
34
+ try {
35
+ const messages = await this.adapter.readMessage(queueName, visibilityTimeoutSeconds, 1);
36
+ return messages.length > 0 ? messages[0] : null;
37
+ }
38
+ catch (error) {
39
+ throw new Error('Failed to read message from queue: ' + (error instanceof Error ? error.message : String(error)));
40
+ }
41
+ }
42
+ /**
43
+ * Reads a message from the queue with blocking poll (event-driven)
44
+ * Note: Not implemented with direct PG adapter - use readMessage instead
45
+ * @param queueName - Name of the queue
46
+ * @param visibilityTimeoutSeconds - Visibility timeout in seconds
47
+ * @param pollTimeoutSeconds - How long to wait for a message (default: 5s)
48
+ * @param pollIntervalMs - Internal polling interval (default: 250ms)
49
+ * @returns PGMQ message or null if timeout reached
50
+ */
51
+ async readMessageWithPoll(queueName, visibilityTimeoutSeconds, _pollTimeoutSeconds = 5, _pollIntervalMs = 250) {
52
+ // Use simple read instead of blocking poll
53
+ return this.readMessage(queueName, visibilityTimeoutSeconds);
54
+ }
55
+ /**
56
+ * Deletes a message from the queue
57
+ * @param queueName - Name of the queue
58
+ * @param messageId - PGMQ message ID
59
+ * @returns true if deleted, false otherwise
60
+ */
61
+ async deleteMessage(queueName, messageId) {
62
+ try {
63
+ return await this.adapter.deleteMessage(queueName, messageId);
64
+ }
65
+ catch (error) {
66
+ throw new Error('Failed to delete message from queue: ' + (error instanceof Error ? error.message : String(error)));
67
+ }
68
+ }
69
+ /**
70
+ * Sends a message to the queue
71
+ * @param queueName - Name of the queue
72
+ * @param message - Message to send
73
+ * @returns PGMQ message ID
74
+ */
75
+ async sendMessage(queueName, message) {
76
+ try {
77
+ return await this.adapter.sendMessage(queueName, message);
78
+ }
79
+ catch (error) {
80
+ throw new Error('Failed to send message to queue: ' + (error instanceof Error ? error.message : String(error)));
81
+ }
82
+ }
83
+ /**
84
+ * Gets queue metrics
85
+ * @param queueName - Name of the queue
86
+ * @returns Queue metrics
87
+ */
88
+ async getMetrics(_queueName) {
89
+ // Not implemented with direct PG adapter
90
+ throw new Error('getMetrics not implemented with direct PostgreSQL adapter');
91
+ }
92
+ /**
93
+ * Creates a new queue (idempotent - safe to call if queue exists)
94
+ * @param queueName - Name of the queue to create
95
+ * @returns true if created or already exists
96
+ */
97
+ async createQueue(queueName) {
98
+ try {
99
+ await this.adapter.createQueue(queueName);
100
+ return true;
101
+ }
102
+ catch (error) {
103
+ const errorMessage = error instanceof Error ? error.message : String(error);
104
+ // Queue already exists - this is OK (idempotent operation)
105
+ if (errorMessage.includes('already a member of extension') ||
106
+ errorMessage.includes('already exists')) {
107
+ return true;
108
+ }
109
+ throw new Error('Failed to create queue: ' + errorMessage);
110
+ }
111
+ }
112
+ /**
113
+ * Sends a message to a specific CLI instance queue
114
+ * @param baseQueueName - Base queue name (e.g., 'image_downloads')
115
+ * @param targetInstanceId - Target CLI instance ID
116
+ * @param message - Message to send
117
+ * @returns PGMQ message ID
118
+ */
119
+ async sendMessageToInstance(baseQueueName, targetInstanceId, message) {
120
+ const instanceQueueName = `${baseQueueName}_${targetInstanceId}`;
121
+ return await this.sendMessage(instanceQueueName, message);
122
+ }
123
+ };
124
+ exports.QueueRepository = QueueRepository;
125
+ exports.QueueRepository = QueueRepository = __decorate([
126
+ (0, tsyringe_1.injectable)(),
127
+ __param(0, (0, tsyringe_1.inject)(pgmq_adapter_1.PgmqAdapter)),
128
+ __metadata("design:paramtypes", [pgmq_adapter_1.PgmqAdapter])
129
+ ], QueueRepository);
130
+ //# sourceMappingURL=queue.repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.repository.js","sourceRoot":"","sources":["../../../src/infrastructure/repositories/queue.repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { SupabaseClient } from '@supabase/supabase-js';
2
+ /**
3
+ * Connection Health Utility
4
+ * Validates database connectivity with timeout
5
+ */
6
+ export declare class ConnectionHealthUtil {
7
+ /**
8
+ * Checks if Supabase connection is healthy
9
+ * @param client - Supabase client to test
10
+ * @param timeoutMs - Timeout in milliseconds (default: 5000)
11
+ * @returns true if connection is healthy, false otherwise
12
+ */
13
+ static isHealthy(client: SupabaseClient, timeoutMs?: number): Promise<boolean>;
14
+ /**
15
+ * Waits for connection to become healthy
16
+ * @param client - Supabase client to test
17
+ * @param maxRetries - Maximum number of retries (default: 3)
18
+ * @param retryDelayMs - Delay between retries in milliseconds (default: 1000)
19
+ * @returns true if connection became healthy, false otherwise
20
+ */
21
+ static waitForHealthy(client: SupabaseClient, maxRetries?: number, retryDelayMs?: number): Promise<boolean>;
22
+ }
23
+ //# sourceMappingURL=connection-health.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-health.util.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/utils/connection-health.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;GAGG;AACH,qBAAa,oBAAoB;IAC/B;;;;;OAKG;WACU,SAAS,CACpB,MAAM,EAAE,cAAc,EACtB,SAAS,GAAE,MAAa,GACvB,OAAO,CAAC,OAAO,CAAC;IA+BnB;;;;;;OAMG;WACU,cAAc,CACzB,MAAM,EAAE,cAAc,EACtB,UAAU,GAAE,MAAU,EACtB,YAAY,GAAE,MAAa,GAC1B,OAAO,CAAC,OAAO,CAAC;CAepB"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectionHealthUtil = void 0;
4
+ /**
5
+ * Connection Health Utility
6
+ * Validates database connectivity with timeout
7
+ */
8
+ class ConnectionHealthUtil {
9
+ /**
10
+ * Checks if Supabase connection is healthy
11
+ * @param client - Supabase client to test
12
+ * @param timeoutMs - Timeout in milliseconds (default: 5000)
13
+ * @returns true if connection is healthy, false otherwise
14
+ */
15
+ static async isHealthy(client, timeoutMs = 5000) {
16
+ try {
17
+ // Create timeout promise
18
+ const timeoutPromise = new Promise((resolve) => {
19
+ setTimeout(() => {
20
+ resolve({ data: null, error: new Error('Connection timeout') });
21
+ }, timeoutMs);
22
+ });
23
+ // Create query promise
24
+ const queryPromise = client
25
+ .from('app_config')
26
+ .select('id')
27
+ .limit(1);
28
+ // Race between query and timeout
29
+ const result = await Promise.race([queryPromise, timeoutPromise]);
30
+ if (result.error) {
31
+ console.warn(`[ConnectionHealth] Database query failed: ${result.error.message}`);
32
+ return false;
33
+ }
34
+ return true;
35
+ }
36
+ catch (error) {
37
+ const message = error instanceof Error ? error.message : 'Unknown error';
38
+ console.warn(`[ConnectionHealth] Connection check failed: ${message}`);
39
+ return false;
40
+ }
41
+ }
42
+ /**
43
+ * Waits for connection to become healthy
44
+ * @param client - Supabase client to test
45
+ * @param maxRetries - Maximum number of retries (default: 3)
46
+ * @param retryDelayMs - Delay between retries in milliseconds (default: 1000)
47
+ * @returns true if connection became healthy, false otherwise
48
+ */
49
+ static async waitForHealthy(client, maxRetries = 3, retryDelayMs = 1000) {
50
+ for (let i = 0; i < maxRetries; i++) {
51
+ const healthy = await this.isHealthy(client);
52
+ if (healthy) {
53
+ return true;
54
+ }
55
+ if (i < maxRetries - 1) {
56
+ console.log(`[ConnectionHealth] Retry ${i + 1}/${maxRetries} in ${retryDelayMs}ms...`);
57
+ await new Promise(resolve => setTimeout(resolve, retryDelayMs));
58
+ }
59
+ }
60
+ return false;
61
+ }
62
+ }
63
+ exports.ConnectionHealthUtil = ConnectionHealthUtil;
64
+ //# sourceMappingURL=connection-health.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-health.util.js","sourceRoot":"","sources":["../../../src/infrastructure/utils/connection-health.util.ts"],"names":[],"mappings":";;;AAEA;;;GAGG;AACH,MAAa,oBAAoB;IAC/B;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,SAAS,CACpB,MAAsB,EACtB,YAAoB,IAAI;QAExB,IAAI,CAAC;YACH,yBAAyB;YACzB,MAAM,cAAc,GAAG,IAAI,OAAO,CAA+B,CAAC,OAAO,EAAE,EAAE;gBAC3E,UAAU,CAAC,GAAG,EAAE;oBACd,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;gBAClE,CAAC,EAAE,SAAS,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;YAEH,uBAAuB;YACvB,MAAM,YAAY,GAAG,MAAM;iBACxB,IAAI,CAAC,YAAY,CAAC;iBAClB,MAAM,CAAC,IAAI,CAAC;iBACZ,KAAK,CAAC,CAAC,CAAC,CAAC;YAEZ,iCAAiC;YACjC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;YAElE,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,OAAO,CAAC,IAAI,CAAC,6CAA6C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBAClF,OAAO,KAAK,CAAC;YACf,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACzE,OAAO,CAAC,IAAI,CAAC,+CAA+C,OAAO,EAAE,CAAC,CAAC;YACvE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,cAAc,CACzB,MAAsB,EACtB,aAAqB,CAAC,EACtB,eAAuB,IAAI;QAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,GAAG,CAAC,IAAI,UAAU,OAAO,YAAY,OAAO,CAAC,CAAC;gBACvF,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAnED,oDAmEC"}
package/package.json ADDED
@@ -0,0 +1,105 @@
1
+ {
2
+ "name": "cadenlane-cli-2",
3
+ "version": "1.0.0",
4
+ "description": "Production-ready, cross-platform TypeScript CLI for processing image downloads from Supabase PGMQ queue with multi-instance support",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "cadenlane-cli-2": "./bin.js"
9
+ },
10
+ "files": [
11
+ "dist/**/*",
12
+ "bin.js",
13
+ "pm2.config.js",
14
+ "README.md",
15
+ "CHANGELOG.md",
16
+ "LICENSE"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/Shiphero-Yolo/cadenlane-cli-2.git"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/Shiphero-Yolo/cadenlane-cli-2/issues"
24
+ },
25
+ "homepage": "https://github.com/Shiphero-Yolo/cadenlane-cli-2#readme",
26
+ "scripts": {
27
+ "dev": "ts-node -r tsconfig-paths/register src/index.ts start",
28
+ "build": "npm run clean && tsc && tsc-alias",
29
+ "clean": "rimraf dist",
30
+ "prepublishOnly": "npm run test && npm run build",
31
+ "start": "node dist/index.js start",
32
+ "start:build": "npm run build && node dist/index.js start",
33
+ "test": "jest",
34
+ "test:unit": "jest --testPathPattern=tests/unit",
35
+ "test:unit:coverage": "jest --testPathPattern=tests/unit --coverage",
36
+ "test:integration": "jest --testPathPattern=tests/integration",
37
+ "test:e2e": "jest --config jest.e2e.config.ts --runInBand",
38
+ "test:watch": "jest --watch",
39
+ "test:coverage": "jest --coverage",
40
+ "coverage:check": "jest --coverage --coverageThreshold='{\"global\":{\"statements\":90,\"branches\":85,\"functions\":90,\"lines\":90}}'",
41
+ "lint": "eslint src tests --ext .ts",
42
+ "lint:fix": "eslint src tests --ext .ts --fix",
43
+ "format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"",
44
+ "type-check": "tsc --noEmit",
45
+ "pm2:start": "npm run build && pm2 start ecosystem.config.js",
46
+ "pm2:stop": "pm2 stop ecosystem.config.js",
47
+ "pm2:restart": "pm2 restart ecosystem.config.js",
48
+ "pm2:reload": "pm2 reload ecosystem.config.js",
49
+ "pm2:delete": "pm2 delete ecosystem.config.js",
50
+ "pm2:logs": "pm2 logs cli-base-worker",
51
+ "pm2:monit": "pm2 monit",
52
+ "pm2:status": "pm2 status"
53
+ },
54
+ "keywords": [
55
+ "cli",
56
+ "image-download",
57
+ "supabase",
58
+ "pgmq",
59
+ "queue",
60
+ "typescript",
61
+ "cross-platform",
62
+ "multi-instance",
63
+ "event-driven",
64
+ "automation",
65
+ "worker",
66
+ "distributed"
67
+ ],
68
+ "author": "Caden Lane",
69
+ "license": "MIT",
70
+ "dependencies": {
71
+ "@automapper/classes": "^8.8.1",
72
+ "@automapper/core": "^8.8.1",
73
+ "@supabase/supabase-js": "^2.55.0",
74
+ "@types/pg": "^8.15.6",
75
+ "axios": "^1.12.2",
76
+ "class-transformer": "^0.5.1",
77
+ "class-validator": "^0.14.0",
78
+ "commander": "^11.0.0",
79
+ "dotenv": "^17.2.1",
80
+ "pg": "^8.16.3",
81
+ "reflect-metadata": "^0.1.14",
82
+ "tsyringe": "^4.8.0"
83
+ },
84
+ "devDependencies": {
85
+ "@jest/globals": "^29.7.0",
86
+ "@types/jest": "^29.5.0",
87
+ "@types/node": "^20.0.0",
88
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
89
+ "@typescript-eslint/parser": "^8.54.0",
90
+ "eslint": "^9.39.2",
91
+ "jest": "^29.7.0",
92
+ "jest-mock-extended": "^3.0.5",
93
+ "pm2": "^6.0.13",
94
+ "prettier": "^3.0.0",
95
+ "rimraf": "^6.0.1",
96
+ "ts-jest": "^29.1.0",
97
+ "ts-node": "^10.9.0",
98
+ "tsc-alias": "^1.8.16",
99
+ "tsconfig-paths": "^4.2.0",
100
+ "typescript": "^5.0.0"
101
+ },
102
+ "engines": {
103
+ "node": ">=18.0.0"
104
+ }
105
+ }
package/pm2.config.js ADDED
@@ -0,0 +1,104 @@
1
+ /**
2
+ * PM2 Ecosystem Configuration for cadenlane CLI
3
+ *
4
+ * This configuration is designed for global npm installations.
5
+ *
6
+ * Usage:
7
+ * pm2 start pm2.config.js
8
+ * pm2 save
9
+ * pm2 startup
10
+ *
11
+ * For custom configuration, copy this file and modify as needed:
12
+ * cp $(npm root -g)/cadenlane-cli-2/pm2.config.js ~/cadenlane-cli-2-pm2.config.js
13
+ */
14
+
15
+ const os = require('os');
16
+ const path = require('path');
17
+
18
+ // Get home directory for cross-platform compatibility
19
+ const homeDir = os.homedir();
20
+ const logsDir = path.join(homeDir, '.cadenlane-cli-2', 'logs');
21
+
22
+ module.exports = {
23
+ apps: [{
24
+ name: 'cadenlane-worker',
25
+ // Use the compiled JS file directly for better Windows compatibility
26
+ script: path.join(__dirname, 'dist', 'cli', 'index.js'),
27
+ args: 'start',
28
+
29
+ // Process configuration
30
+ instances: 1,
31
+ exec_mode: 'fork',
32
+ autorestart: true,
33
+ watch: false,
34
+ max_memory_restart: '500M',
35
+
36
+ // Environment
37
+ env: {
38
+ NODE_ENV: 'production',
39
+ },
40
+
41
+ // Logging configuration
42
+ error_file: path.join(logsDir, 'pm2-error.log'),
43
+ out_file: path.join(logsDir, 'pm2-out.log'),
44
+ log_file: path.join(logsDir, 'pm2-combined.log'),
45
+ time: true,
46
+ merge_logs: true,
47
+ log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
48
+
49
+ // Restart configuration
50
+ min_uptime: '10s',
51
+ max_restarts: 10,
52
+
53
+ // Advanced features
54
+ kill_timeout: 5000,
55
+ wait_ready: false,
56
+ listen_timeout: 3000,
57
+
58
+ // Custom actions for PM2.io dashboard
59
+ actions: [
60
+ {
61
+ action_name: 'stop-worker',
62
+ action_type: 'internal',
63
+ description: 'Stop the worker process',
64
+ command: 'pm2',
65
+ args: ['stop', 'cadenlane-worker']
66
+ },
67
+ {
68
+ action_name: 'restart-worker',
69
+ action_type: 'internal',
70
+ description: 'Restart the worker process',
71
+ command: 'pm2',
72
+ args: ['restart', 'cadenlane-worker']
73
+ },
74
+ {
75
+ action_name: 'view-logs',
76
+ action_type: 'internal',
77
+ description: 'View last 50 lines of logs',
78
+ command: 'pm2',
79
+ args: ['logs', 'cadenlane-worker', '--lines', '50']
80
+ },
81
+ {
82
+ action_name: 'flush-logs',
83
+ action_type: 'internal',
84
+ description: 'Clear all PM2 logs',
85
+ command: 'pm2',
86
+ args: ['flush', 'cadenlane-worker']
87
+ },
88
+ {
89
+ action_name: 'reload-env',
90
+ action_type: 'internal',
91
+ description: 'Reload environment variables',
92
+ command: 'pm2',
93
+ args: ['restart', 'cadenlane-worker', '--update-env']
94
+ },
95
+ {
96
+ action_name: 'update-package',
97
+ action_type: 'internal',
98
+ description: 'Update to latest npm package version',
99
+ command: 'npm',
100
+ args: ['install', '-g', 'cadenlane-cli-2@latest']
101
+ }
102
+ ]
103
+ }],
104
+ };