@ceschiatti/redistail 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Core data types and error definitions for the redistail CLI utility.
3
+ *
4
+ * This module defines immutable data structures using Effect Data types
5
+ * and error types using Data.TaggedError for type-safe error handling.
6
+ */
7
+
8
+ import { Data } from 'effect';
9
+
10
+ // ============================================================================
11
+ // CLI Configuration Types
12
+ // ============================================================================
13
+
14
+ /**
15
+ * CLI configuration parsed from command line arguments
16
+ */
17
+ export interface CLIConfig {
18
+ readonly connectionType: 'pubsub' | 'stream';
19
+ readonly topicName: string;
20
+ readonly help?: boolean;
21
+ readonly version?: boolean;
22
+ }
23
+
24
+ /**
25
+ * Complete redistail configuration including Redis connection and display settings
26
+ */
27
+ export interface RedistailConfig {
28
+ readonly redis: {
29
+ readonly host: string;
30
+ readonly port: number;
31
+ readonly url?: string;
32
+ readonly timeout: number;
33
+ readonly retryAttempts: number;
34
+ readonly retryDelay: number;
35
+ };
36
+ readonly display: {
37
+ readonly colors: boolean;
38
+ readonly timestamps: boolean;
39
+ readonly prettyJson: boolean;
40
+ };
41
+ readonly monitoring: {
42
+ readonly blockTimeout: number;
43
+ readonly maxReconnectAttempts: number;
44
+ };
45
+ }
46
+
47
+ // Data constructors for immutable data structures
48
+ export const CLIConfig = Data.struct<CLIConfig>;
49
+ export const RedistailConfig = Data.struct<RedistailConfig>;
50
+
51
+ // ============================================================================
52
+ // Message Types
53
+ // ============================================================================
54
+
55
+ /**
56
+ * Pub/Sub message data structure
57
+ */
58
+ export interface PubSubMessage {
59
+ readonly timestamp: Date;
60
+ readonly channel: string;
61
+ readonly content: string;
62
+ }
63
+
64
+ /**
65
+ * Redis Stream message data structure
66
+ */
67
+ export interface StreamMessage {
68
+ readonly timestamp: Date;
69
+ readonly streamKey: string;
70
+ readonly entryId: string;
71
+ readonly fields: Record<string, string>;
72
+ }
73
+
74
+ // Data constructors for message types
75
+ export const PubSubMessage = Data.struct<PubSubMessage>;
76
+ export const StreamMessage = Data.struct<StreamMessage>;
77
+
78
+ // ============================================================================
79
+ // Error Types using Data.TaggedError
80
+ // ============================================================================
81
+
82
+ /**
83
+ * CLI-specific errors for argument parsing and validation
84
+ */
85
+ export class CLIError extends Data.TaggedError('CLIError')<{
86
+ readonly reason: 'InvalidArguments' | 'MissingArguments' | 'UnknownCommand';
87
+ readonly message: string;
88
+ readonly context?: string;
89
+ }> {}
90
+
91
+ /**
92
+ * Configuration errors for environment variables and Redis connection
93
+ */
94
+ export class ConfigError extends Data.TaggedError('ConfigError')<{
95
+ readonly reason:
96
+ | 'InvalidEnvironment'
97
+ | 'ConnectionFailed'
98
+ | 'ValidationFailed';
99
+ readonly message: string;
100
+ readonly cause?: unknown;
101
+ readonly context?: string;
102
+ }> {}
103
+
104
+ /**
105
+ * Runtime monitoring errors for subscription and connection issues
106
+ */
107
+ export class MonitoringError extends Data.TaggedError('MonitoringError')<{
108
+ readonly reason: 'ConnectionLost' | 'SubscriptionFailed' | 'StreamReadFailed';
109
+ readonly message: string;
110
+ readonly retryable: boolean;
111
+ readonly cause?: unknown;
112
+ }> {}
113
+
114
+ /**
115
+ * Union type for all redistail-specific errors
116
+ */
117
+ export type RedistailError = CLIError | ConfigError | MonitoringError;
118
+
119
+ // ============================================================================
120
+ // Stream Monitor Options
121
+ // ============================================================================
122
+
123
+ /**
124
+ * Options for Redis Stream monitoring
125
+ */
126
+ export interface StreamMonitorOptions {
127
+ readonly startId?: string;
128
+ readonly blockTimeout?: number;
129
+ readonly count?: number;
130
+ }
131
+
132
+ export const StreamMonitorOptions = Data.struct<StreamMonitorOptions>;
133
+
134
+ // ============================================================================
135
+ // Type Guards and Utilities
136
+ // ============================================================================
137
+
138
+ /**
139
+ * Type guard to check if a connection type is valid
140
+ */
141
+ export const isValidConnectionType = (
142
+ type: string,
143
+ ): type is 'pubsub' | 'stream' => type === 'pubsub' || type === 'stream';
144
+
145
+ /**
146
+ * Type guard to check if a topic name is valid (non-empty after trimming)
147
+ */
148
+ export const isValidTopicName = (name: string): boolean =>
149
+ typeof name === 'string' && name.trim().length > 0;
150
+
151
+ /**
152
+ * Helper to create CLIError for invalid arguments
153
+ */
154
+ export const createInvalidArgumentError = (
155
+ message: string,
156
+ context?: string,
157
+ ): CLIError =>
158
+ new CLIError({
159
+ reason: 'InvalidArguments',
160
+ message,
161
+ context,
162
+ });
163
+
164
+ /**
165
+ * Helper to create CLIError for missing arguments
166
+ */
167
+ export const createMissingArgumentError = (
168
+ message: string,
169
+ context?: string,
170
+ ): CLIError =>
171
+ new CLIError({
172
+ reason: 'MissingArguments',
173
+ message,
174
+ context,
175
+ });
176
+
177
+ /**
178
+ * Helper to create ConfigError for environment issues
179
+ */
180
+ export const createEnvironmentError = (
181
+ message: string,
182
+ cause?: unknown,
183
+ context?: string,
184
+ ): ConfigError =>
185
+ new ConfigError({
186
+ reason: 'InvalidEnvironment',
187
+ message,
188
+ cause,
189
+ context,
190
+ });
191
+
192
+ /**
193
+ * Helper to create ConfigError for connection failures
194
+ */
195
+ export const createConnectionError = (
196
+ message: string,
197
+ cause?: unknown,
198
+ context?: string,
199
+ ): ConfigError =>
200
+ new ConfigError({
201
+ reason: 'ConnectionFailed',
202
+ message,
203
+ cause,
204
+ context,
205
+ });
206
+
207
+ /**
208
+ * Helper to create MonitoringError for connection loss
209
+ */
210
+ export const createConnectionLostError = (
211
+ message: string,
212
+ cause?: unknown,
213
+ ): MonitoringError =>
214
+ new MonitoringError({
215
+ reason: 'ConnectionLost',
216
+ message,
217
+ retryable: true,
218
+ cause,
219
+ });
220
+
221
+ /**
222
+ * Helper to create MonitoringError for subscription failures
223
+ */
224
+ export const createSubscriptionFailedError = (
225
+ message: string,
226
+ retryable = true,
227
+ cause?: unknown,
228
+ ): MonitoringError =>
229
+ new MonitoringError({
230
+ reason: 'SubscriptionFailed',
231
+ message,
232
+ retryable,
233
+ cause,
234
+ });
235
+
236
+ /**
237
+ * Helper to create MonitoringError for stream read failures
238
+ */
239
+ export const createStreamReadFailedError = (
240
+ message: string,
241
+ retryable = true,
242
+ cause?: unknown,
243
+ ): MonitoringError =>
244
+ new MonitoringError({
245
+ reason: 'StreamReadFailed',
246
+ message,
247
+ retryable,
248
+ cause,
249
+ });
250
+
251
+ // ============================================================================
252
+ // Default Configuration Values
253
+ // ============================================================================
254
+
255
+ /**
256
+ * Default Redis configuration values for CLI
257
+ */
258
+ export const DEFAULT_CLI_REDIS_CONFIG = {
259
+ host: '127.0.0.1',
260
+ port: 6379,
261
+ timeout: 5000,
262
+ retryAttempts: 3,
263
+ retryDelay: 1000,
264
+ } as const;
265
+
266
+ /**
267
+ * Default display configuration values
268
+ */
269
+ export const DEFAULT_DISPLAY_CONFIG = {
270
+ colors: true,
271
+ timestamps: true,
272
+ prettyJson: true,
273
+ } as const;
274
+
275
+ /**
276
+ * Default monitoring configuration values
277
+ */
278
+ export const DEFAULT_MONITORING_CONFIG = {
279
+ blockTimeout: 5000,
280
+ maxReconnectAttempts: 5,
281
+ } as const;
282
+
283
+ /**
284
+ * Helper to create a default RedistailConfig with overrides
285
+ */
286
+ export const createDefaultRedistailConfig = (
287
+ overrides?: Partial<RedistailConfig>,
288
+ ): RedistailConfig =>
289
+ RedistailConfig({
290
+ redis: {
291
+ ...DEFAULT_CLI_REDIS_CONFIG,
292
+ ...overrides?.redis,
293
+ },
294
+ display: {
295
+ ...DEFAULT_DISPLAY_CONFIG,
296
+ ...overrides?.display,
297
+ },
298
+ monitoring: {
299
+ ...DEFAULT_MONITORING_CONFIG,
300
+ ...overrides?.monitoring,
301
+ },
302
+ });
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Build version information
3
+ *
4
+ * This file is a template that gets replaced during the build process
5
+ * DO NOT EDIT MANUALLY
6
+ */
7
+
8
+ // These values are replaced at build time by build-cli.js
9
+ export const BUILD_COMMIT: string = 'd18b194';
10
+ export const BUILD_VERSION: string = '0.0.4';
11
+
12
+ /**
13
+ * Get formatted version information for display
14
+ */
15
+ export const getVersionInfo = () => ({
16
+ version: BUILD_VERSION,
17
+ commit: BUILD_COMMIT,
18
+ isDev: BUILD_VERSION === '__BUILD_VERSION__',
19
+ });
20
+
21
+ /**
22
+ * Format version information as a string
23
+ */
24
+ export const formatVersion = () => {
25
+ const info = getVersionInfo();
26
+ return `${info.version}${info.isDev ? ' (dev)' : ` (${info.commit})`}`;
27
+ };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Build version information
3
+ *
4
+ * This file is a template that gets replaced during the build process
5
+ * DO NOT EDIT MANUALLY
6
+ */
7
+
8
+ // These values are replaced at build time by build-cli.js
9
+ export const BUILD_COMMIT: string = '__BUILD_COMMIT__';
10
+ export const BUILD_VERSION: string = '__BUILD_VERSION__';
11
+
12
+ /**
13
+ * Get formatted version information for display
14
+ */
15
+ export const getVersionInfo = () => ({
16
+ version: BUILD_VERSION,
17
+ commit: BUILD_COMMIT,
18
+ isDev: BUILD_VERSION === '__BUILD_VERSION__',
19
+ });
20
+
21
+ /**
22
+ * Format version information as a string
23
+ */
24
+ export const formatVersion = () => {
25
+ const info = getVersionInfo();
26
+ return `${info.version}${info.isDev ? ' (dev)' : ` (${info.commit})`}`;
27
+ };