@freshguard/freshguard-core 0.11.2

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 (180) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +644 -0
  3. package/dist/cli/index.d.ts +3 -0
  4. package/dist/cli/index.d.ts.map +1 -0
  5. package/dist/cli/index.js +350 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/connectors/base-connector.d.ts +62 -0
  8. package/dist/connectors/base-connector.d.ts.map +1 -0
  9. package/dist/connectors/base-connector.js +549 -0
  10. package/dist/connectors/base-connector.js.map +1 -0
  11. package/dist/connectors/bigquery.d.ts +38 -0
  12. package/dist/connectors/bigquery.d.ts.map +1 -0
  13. package/dist/connectors/bigquery.js +406 -0
  14. package/dist/connectors/bigquery.js.map +1 -0
  15. package/dist/connectors/duckdb.d.ts +36 -0
  16. package/dist/connectors/duckdb.d.ts.map +1 -0
  17. package/dist/connectors/duckdb.js +364 -0
  18. package/dist/connectors/duckdb.js.map +1 -0
  19. package/dist/connectors/index.d.ts +7 -0
  20. package/dist/connectors/index.d.ts.map +1 -0
  21. package/dist/connectors/index.js +7 -0
  22. package/dist/connectors/index.js.map +1 -0
  23. package/dist/connectors/mysql.d.ts +32 -0
  24. package/dist/connectors/mysql.d.ts.map +1 -0
  25. package/dist/connectors/mysql.js +348 -0
  26. package/dist/connectors/mysql.js.map +1 -0
  27. package/dist/connectors/postgres.d.ts +31 -0
  28. package/dist/connectors/postgres.d.ts.map +1 -0
  29. package/dist/connectors/postgres.js +326 -0
  30. package/dist/connectors/postgres.js.map +1 -0
  31. package/dist/connectors/redshift.d.ts +32 -0
  32. package/dist/connectors/redshift.d.ts.map +1 -0
  33. package/dist/connectors/redshift.js +366 -0
  34. package/dist/connectors/redshift.js.map +1 -0
  35. package/dist/connectors/snowflake.d.ts +43 -0
  36. package/dist/connectors/snowflake.d.ts.map +1 -0
  37. package/dist/connectors/snowflake.js +442 -0
  38. package/dist/connectors/snowflake.js.map +1 -0
  39. package/dist/db/index.d.ts +9 -0
  40. package/dist/db/index.d.ts.map +1 -0
  41. package/dist/db/index.js +10 -0
  42. package/dist/db/index.js.map +1 -0
  43. package/dist/db/migrate.d.ts +12 -0
  44. package/dist/db/migrate.d.ts.map +1 -0
  45. package/dist/db/migrate.js +114 -0
  46. package/dist/db/migrate.js.map +1 -0
  47. package/dist/db/schema.d.ts +2053 -0
  48. package/dist/db/schema.d.ts.map +1 -0
  49. package/dist/db/schema.js +164 -0
  50. package/dist/db/schema.js.map +1 -0
  51. package/dist/errors/debug-factory.d.ts +23 -0
  52. package/dist/errors/debug-factory.d.ts.map +1 -0
  53. package/dist/errors/debug-factory.js +149 -0
  54. package/dist/errors/debug-factory.js.map +1 -0
  55. package/dist/errors/index.d.ts +119 -0
  56. package/dist/errors/index.d.ts.map +1 -0
  57. package/dist/errors/index.js +341 -0
  58. package/dist/errors/index.js.map +1 -0
  59. package/dist/index.d.ts +9 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +6 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/metadata/duckdb-storage.d.ts +31 -0
  64. package/dist/metadata/duckdb-storage.d.ts.map +1 -0
  65. package/dist/metadata/duckdb-storage.js +230 -0
  66. package/dist/metadata/duckdb-storage.js.map +1 -0
  67. package/dist/metadata/factory.d.ts +4 -0
  68. package/dist/metadata/factory.d.ts.map +1 -0
  69. package/dist/metadata/factory.js +23 -0
  70. package/dist/metadata/factory.js.map +1 -0
  71. package/dist/metadata/index.d.ts +6 -0
  72. package/dist/metadata/index.d.ts.map +1 -0
  73. package/dist/metadata/index.js +4 -0
  74. package/dist/metadata/index.js.map +1 -0
  75. package/dist/metadata/interface.d.ts +26 -0
  76. package/dist/metadata/interface.d.ts.map +1 -0
  77. package/dist/metadata/interface.js +2 -0
  78. package/dist/metadata/interface.js.map +1 -0
  79. package/dist/metadata/postgresql-storage.d.ts +32 -0
  80. package/dist/metadata/postgresql-storage.d.ts.map +1 -0
  81. package/dist/metadata/postgresql-storage.js +242 -0
  82. package/dist/metadata/postgresql-storage.js.map +1 -0
  83. package/dist/metadata/schema-config.d.ts +30 -0
  84. package/dist/metadata/schema-config.d.ts.map +1 -0
  85. package/dist/metadata/schema-config.js +94 -0
  86. package/dist/metadata/schema-config.js.map +1 -0
  87. package/dist/metadata/types.d.ts +35 -0
  88. package/dist/metadata/types.d.ts.map +1 -0
  89. package/dist/metadata/types.js +2 -0
  90. package/dist/metadata/types.js.map +1 -0
  91. package/dist/monitor/baseline-calculator.d.ts +30 -0
  92. package/dist/monitor/baseline-calculator.d.ts.map +1 -0
  93. package/dist/monitor/baseline-calculator.js +192 -0
  94. package/dist/monitor/baseline-calculator.js.map +1 -0
  95. package/dist/monitor/baseline-config.d.ts +37 -0
  96. package/dist/monitor/baseline-config.d.ts.map +1 -0
  97. package/dist/monitor/baseline-config.js +156 -0
  98. package/dist/monitor/baseline-config.js.map +1 -0
  99. package/dist/monitor/freshness.d.ts +5 -0
  100. package/dist/monitor/freshness.d.ts.map +1 -0
  101. package/dist/monitor/freshness.js +239 -0
  102. package/dist/monitor/freshness.js.map +1 -0
  103. package/dist/monitor/index.d.ts +5 -0
  104. package/dist/monitor/index.d.ts.map +1 -0
  105. package/dist/monitor/index.js +5 -0
  106. package/dist/monitor/index.js.map +1 -0
  107. package/dist/monitor/schema-baseline.d.ts +22 -0
  108. package/dist/monitor/schema-baseline.d.ts.map +1 -0
  109. package/dist/monitor/schema-baseline.js +211 -0
  110. package/dist/monitor/schema-baseline.js.map +1 -0
  111. package/dist/monitor/schema-changes.d.ts +5 -0
  112. package/dist/monitor/schema-changes.d.ts.map +1 -0
  113. package/dist/monitor/schema-changes.js +289 -0
  114. package/dist/monitor/schema-changes.js.map +1 -0
  115. package/dist/monitor/volume.d.ts +5 -0
  116. package/dist/monitor/volume.d.ts.map +1 -0
  117. package/dist/monitor/volume.js +262 -0
  118. package/dist/monitor/volume.js.map +1 -0
  119. package/dist/observability/logger.d.ts +63 -0
  120. package/dist/observability/logger.d.ts.map +1 -0
  121. package/dist/observability/logger.js +282 -0
  122. package/dist/observability/logger.js.map +1 -0
  123. package/dist/observability/metrics.d.ts +106 -0
  124. package/dist/observability/metrics.d.ts.map +1 -0
  125. package/dist/observability/metrics.js +441 -0
  126. package/dist/observability/metrics.js.map +1 -0
  127. package/dist/query-analyzer.js +526 -0
  128. package/dist/resilience/circuit-breaker.d.ts +94 -0
  129. package/dist/resilience/circuit-breaker.d.ts.map +1 -0
  130. package/dist/resilience/circuit-breaker.js +379 -0
  131. package/dist/resilience/circuit-breaker.js.map +1 -0
  132. package/dist/resilience/index.d.ts +7 -0
  133. package/dist/resilience/index.d.ts.map +1 -0
  134. package/dist/resilience/index.js +7 -0
  135. package/dist/resilience/index.js.map +1 -0
  136. package/dist/resilience/retry-policy.d.ts +87 -0
  137. package/dist/resilience/retry-policy.d.ts.map +1 -0
  138. package/dist/resilience/retry-policy.js +423 -0
  139. package/dist/resilience/retry-policy.js.map +1 -0
  140. package/dist/resilience/timeout-manager.d.ts +97 -0
  141. package/dist/resilience/timeout-manager.d.ts.map +1 -0
  142. package/dist/resilience/timeout-manager.js +339 -0
  143. package/dist/resilience/timeout-manager.js.map +1 -0
  144. package/dist/security/query-analyzer.d.ts +82 -0
  145. package/dist/security/query-analyzer.d.ts.map +1 -0
  146. package/dist/security/query-analyzer.js +381 -0
  147. package/dist/security/query-analyzer.js.map +1 -0
  148. package/dist/security/schema-cache.d.ts +95 -0
  149. package/dist/security/schema-cache.d.ts.map +1 -0
  150. package/dist/security/schema-cache.js +344 -0
  151. package/dist/security/schema-cache.js.map +1 -0
  152. package/dist/types/connector.d.ts +68 -0
  153. package/dist/types/connector.d.ts.map +1 -0
  154. package/dist/types/connector.js +26 -0
  155. package/dist/types/connector.js.map +1 -0
  156. package/dist/types.d.ts +244 -0
  157. package/dist/types.d.ts.map +1 -0
  158. package/dist/types.js +2 -0
  159. package/dist/types.js.map +1 -0
  160. package/dist/validation/index.d.ts +7 -0
  161. package/dist/validation/index.d.ts.map +1 -0
  162. package/dist/validation/index.js +5 -0
  163. package/dist/validation/index.js.map +1 -0
  164. package/dist/validation/runtime-validator.d.ts +70 -0
  165. package/dist/validation/runtime-validator.d.ts.map +1 -0
  166. package/dist/validation/runtime-validator.js +206 -0
  167. package/dist/validation/runtime-validator.js.map +1 -0
  168. package/dist/validation/sanitizers.d.ts +56 -0
  169. package/dist/validation/sanitizers.d.ts.map +1 -0
  170. package/dist/validation/sanitizers.js +264 -0
  171. package/dist/validation/sanitizers.js.map +1 -0
  172. package/dist/validation/schemas.d.ts +224 -0
  173. package/dist/validation/schemas.d.ts.map +1 -0
  174. package/dist/validation/schemas.js +263 -0
  175. package/dist/validation/schemas.js.map +1 -0
  176. package/dist/validators/index.d.ts +18 -0
  177. package/dist/validators/index.d.ts.map +1 -0
  178. package/dist/validators/index.js +209 -0
  179. package/dist/validators/index.js.map +1 -0
  180. package/package.json +91 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 FreshGuard
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,644 @@
1
+ # FreshGuard Core
2
+
3
+ **Open source data pipeline freshness monitoring engine for self-hosting.**
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![pnpm version](https://img.shields.io/npm/v/@freshguard/freshguard-core.svg)](https://www.npmjs.com/package/@freshguard/freshguard-core)
7
+
8
+ ## What is FreshGuard Core?
9
+
10
+ Monitor when your data pipelines go stale. Get alerts when:
11
+ - **Data hasn't updated in X minutes** (freshness checks)
12
+ - **Row counts deviate unexpectedly** (volume anomaly detection)
13
+ - **Database schemas change unexpectedly** (schema change monitoring)
14
+
15
+ Supports PostgreSQL, DuckDB, BigQuery, and Snowflake. Self-hosted. Free forever.
16
+
17
+ ## 🔒 Security Features
18
+
19
+ FreshGuard Core includes basic security protections for self-hosted deployments:
20
+
21
+ **🛡️ Query Security**
22
+ - ✅ **SQL Injection Protection** - Input validation and pattern analysis
23
+ - ✅ **Query Validation** - Basic checks for dangerous operations
24
+ - ✅ **Input Sanitization** - Identifier validation and parameter checking
25
+
26
+ **🔄 Resilience Features**
27
+ - ✅ **Circuit Breaker Protection** - Automatic failure detection and recovery
28
+ - ✅ **Retry Logic** - Exponential backoff with jitter
29
+ - ✅ **Timeout Protection** - Query and connection timeouts
30
+ - ✅ **Connection Management** - Basic connection pooling
31
+
32
+ **📊 Observability**
33
+ - ✅ **Structured Logging** - JSON logging with Pino
34
+ - ✅ **Error Handling** - Sanitized error messages
35
+ - ✅ **Performance Tracking** - Basic query performance metrics
36
+
37
+ **🔐 Security Basics**
38
+ - ✅ **SSL/TLS Support** - Secure database connections
39
+ - ✅ **Environment Variables** - Secure credential management
40
+ - ✅ **Error Sanitization** - Safe error messages
41
+
42
+ **📋 [Complete Security Guide →](docs/SECURITY_FOR_SELF_HOSTERS.md)** | **🚀 [Integration Guide →](docs/INTEGRATION_GUIDE.md)**
43
+
44
+ ## Quick Start
45
+
46
+ ### 1. Install
47
+
48
+ ```bash
49
+ pnpm install @freshguard/freshguard-core
50
+ ```
51
+
52
+ ### 2. Check Freshness
53
+
54
+ ```typescript
55
+ import { checkFreshness, PostgresConnector } from '@freshguard/freshguard-core';
56
+ import type { MonitoringRule } from '@freshguard/freshguard-core';
57
+
58
+ // Connect to your database
59
+ const connector = new PostgresConnector({
60
+ host: process.env.DB_HOST || 'localhost',
61
+ port: Number(process.env.DB_PORT) || 5432,
62
+ database: process.env.DB_NAME || 'mydb',
63
+ username: process.env.DB_USER!,
64
+ password: process.env.DB_PASSWORD!,
65
+ ssl: true, // Enable SSL for secure connections
66
+ });
67
+
68
+ const rule: MonitoringRule = {
69
+ id: 'orders-freshness',
70
+ sourceId: 'prod_db',
71
+ name: 'Orders Freshness',
72
+ tableName: 'orders',
73
+ ruleType: 'freshness',
74
+ toleranceMinutes: 60,
75
+ timestampColumn: 'updated_at',
76
+ checkIntervalMinutes: 5,
77
+ isActive: true,
78
+ createdAt: new Date(),
79
+ updatedAt: new Date(),
80
+ };
81
+
82
+ const result = await checkFreshness(connector, rule);
83
+
84
+ if (result.status === 'alert') {
85
+ console.log(`⚠️ Data is ${result.lagMinutes}m stale!`);
86
+ } else {
87
+ console.log(`✅ Data is fresh (lag: ${result.lagMinutes}m)`);
88
+ }
89
+ ```
90
+
91
+ ### 3. Check Volume Anomalies
92
+
93
+ ```typescript
94
+ import { checkVolumeAnomaly, PostgresConnector } from '@freshguard/freshguard-core';
95
+
96
+ const connector = new PostgresConnector({
97
+ host: process.env.DB_HOST!,
98
+ database: process.env.DB_NAME!,
99
+ username: process.env.DB_USER!,
100
+ password: process.env.DB_PASSWORD!,
101
+ ssl: true,
102
+ });
103
+
104
+ const result = await checkVolumeAnomaly(connector, rule);
105
+
106
+ if (result.status === 'alert') {
107
+ console.log(`⚠️ Volume anomaly detected: ${result.deviation}% deviation from baseline`);
108
+ }
109
+ ```
110
+
111
+ ### 4. Monitor Schema Changes
112
+
113
+ ```typescript
114
+ import { checkSchemaChanges, PostgresConnector } from '@freshguard/freshguard-core';
115
+
116
+ const schemaRule: MonitoringRule = {
117
+ id: 'users-schema',
118
+ sourceId: 'prod_db',
119
+ name: 'Users Table Schema Monitor',
120
+ tableName: 'users',
121
+ ruleType: 'schema_change',
122
+ checkIntervalMinutes: 60,
123
+ isActive: true,
124
+ trackColumnChanges: true,
125
+ trackTableChanges: true,
126
+ schemaChangeConfig: {
127
+ adaptationMode: 'manual', // 'auto' | 'manual' | 'alert_only'
128
+ monitoringMode: 'full', // 'full' | 'partial'
129
+ trackedColumns: {
130
+ alertLevel: 'medium', // 'low' | 'medium' | 'high'
131
+ trackTypes: true, // Monitor data type changes
132
+ trackNullability: false // Don't track nullability changes
133
+ },
134
+ baselineRefreshDays: 30 // Auto-refresh baseline monthly
135
+ },
136
+ createdAt: new Date(),
137
+ updatedAt: new Date(),
138
+ };
139
+
140
+ const result = await checkSchemaChanges(connector, schemaRule, metadataStorage);
141
+
142
+ if (result.status === 'alert') {
143
+ console.log(`⚠️ Schema changes detected: ${result.schemaChanges?.summary}`);
144
+
145
+ // Check specific changes
146
+ if (result.schemaChanges?.addedColumns?.length > 0) {
147
+ console.log('New columns:', result.schemaChanges.addedColumns.map(c => c.columnName));
148
+ }
149
+
150
+ if (result.schemaChanges?.removedColumns?.length > 0) {
151
+ console.log('Removed columns:', result.schemaChanges.removedColumns.map(c => c.columnName));
152
+ }
153
+
154
+ if (result.schemaChanges?.modifiedColumns?.length > 0) {
155
+ console.log('Modified columns:', result.schemaChanges.modifiedColumns.map(c =>
156
+ `${c.columnName} (${c.changeType}): ${c.oldValue} → ${c.newValue}`
157
+ ));
158
+ }
159
+ } else {
160
+ console.log(`✅ Schema is stable (${result.schemaChanges?.changeCount || 0} changes)`);
161
+ }
162
+ ```
163
+
164
+ **Schema Change Adaptation Modes:**
165
+ - **`auto`** - Automatically adapt to safe changes (column additions, safe type changes)
166
+ - **`manual`** - Require manual approval for all changes (default)
167
+ - **`alert_only`** - Always alert, never update baseline automatically
168
+
169
+ **Monitoring Modes:**
170
+ - **`full`** - Monitor all columns in the table (default)
171
+ - **`partial`** - Monitor only specified columns in `trackedColumns.columns` array
172
+
173
+ ## 📊 Metadata Storage
174
+
175
+ FreshGuard tracks execution history for volume anomaly detection and monitoring analytics. Choose between **DuckDB** (embedded, zero-setup) or **PostgreSQL** (production-ready) storage.
176
+
177
+ ### Quick Setup (Zero Configuration)
178
+
179
+ ```typescript
180
+ import { createMetadataStorage, checkVolumeAnomaly, PostgresConnector } from '@freshguard/freshguard-core';
181
+
182
+ // Create database connector
183
+ const connector = new PostgresConnector({
184
+ host: process.env.DB_HOST!,
185
+ database: process.env.DB_NAME!,
186
+ username: process.env.DB_USER!,
187
+ password: process.env.DB_PASSWORD!,
188
+ });
189
+
190
+ // Automatic setup - creates ./freshguard-metadata.db
191
+ const metadataStorage = await createMetadataStorage();
192
+
193
+ // Use with monitoring functions
194
+ const result = await checkVolumeAnomaly(connector, rule, metadataStorage);
195
+
196
+ // Clean up
197
+ await metadataStorage.close();
198
+ ```
199
+
200
+ ### Storage Options
201
+
202
+ **DuckDB (Recommended for Self-Hosting)**
203
+ - ✅ Zero database server setup
204
+ - ✅ Single file storage (`./freshguard-metadata.db`)
205
+ - ✅ Perfect for Docker containers
206
+
207
+ ```typescript
208
+ // Custom path
209
+ const storage = await createMetadataStorage({
210
+ type: 'duckdb',
211
+ path: './my-freshguard-data.db'
212
+ });
213
+ ```
214
+
215
+ **PostgreSQL (Recommended for Production)**
216
+ - ✅ Full ACID compliance
217
+ - ✅ Concurrent access support
218
+ - ✅ Backup/restore capabilities
219
+
220
+ ```typescript
221
+ // Production setup
222
+ const storage = await createMetadataStorage({
223
+ type: 'postgresql',
224
+ url: 'postgresql://user:pass@host:5432/freshguard_metadata'
225
+ });
226
+ ```
227
+
228
+ **📋 [Complete Metadata Storage Guide →](docs/METADATA_STORAGE.md)**
229
+
230
+ ### 🚨 Error Handling
231
+
232
+ FreshGuard Core exports comprehensive error classes for proper error handling:
233
+
234
+ ```typescript
235
+ import {
236
+ checkFreshness,
237
+ PostgresConnector,
238
+ SecurityError,
239
+ ConnectionError,
240
+ TimeoutError,
241
+ QueryError,
242
+ ConfigurationError,
243
+ MonitoringError
244
+ } from '@freshguard/freshguard-core';
245
+
246
+ try {
247
+ const result = await checkFreshness(connector, rule);
248
+ console.log(`✅ Check completed: ${result.status}`);
249
+ } catch (error) {
250
+ // Handle specific error types
251
+ if (error instanceof SecurityError) {
252
+ console.error('🔒 Security violation:', error.message);
253
+ // Log security incident, block request source
254
+ } else if (error instanceof ConnectionError) {
255
+ console.error('🔌 Database connection failed:', error.message);
256
+ // Retry with backoff, check network connectivity
257
+ } else if (error instanceof TimeoutError) {
258
+ console.error('⏱️ Query timeout:', error.message);
259
+ // Check query complexity, database performance
260
+ } else if (error instanceof QueryError) {
261
+ console.error('📊 Query execution failed:', error.message);
262
+ // Check table exists, column names, permissions
263
+ } else if (error instanceof ConfigurationError) {
264
+ console.error('⚙️ Configuration error:', error.message);
265
+ // Check environment variables, config file
266
+ } else if (error instanceof MonitoringError) {
267
+ console.error('📈 Monitoring check failed:', error.message);
268
+ // Check rule configuration, data availability
269
+ } else {
270
+ console.error('❌ Unknown error:', error.message);
271
+ }
272
+ }
273
+ ```
274
+
275
+ **Error Properties:**
276
+ - `error.code` - Machine-readable error code (e.g., "SECURITY_VIOLATION")
277
+ - `error.timestamp` - When the error occurred
278
+ - `error.sanitized` - Whether error message is safe for user display
279
+
280
+ ## Features
281
+
282
+ ### 📊 Monitoring
283
+ ✅ **Freshness Monitoring** - Detect stale data based on last update time
284
+ ✅ **Volume Anomaly Detection** - Identify unexpected row count changes
285
+ ✅ **Schema Change Monitoring** - Track database schema evolution with configurable adaptation modes
286
+
287
+ ### 🗄️ Database Support
288
+ ✅ **PostgreSQL** - Production-ready with SSL/TLS support
289
+ ✅ **DuckDB** - Analytics and local development
290
+ ✅ **BigQuery** - Google Cloud data warehouses
291
+ ✅ **Snowflake** - Enterprise data platforms
292
+
293
+ ### 🔒 Security
294
+ ✅ **Security Basics** - Input validation and secure connections
295
+ ✅ **Error Sanitization** - Safe error handling and logging
296
+ ✅ **Open Source** - Transparent and auditable code
297
+
298
+ ### 🛠️ Developer Experience
299
+ ✅ **Type-Safe** - Written in TypeScript with full type definitions
300
+ ✅ **CLI Tool** - Secure command-line interface for self-hosters
301
+ ✅ **Self-Hosted** - Run on your own infrastructure
302
+ ✅ **MIT Licensed** - Free to use, modify, and distribute
303
+
304
+ ## 🖥️ CLI Usage
305
+
306
+ FreshGuard Core includes a CLI tool for self-hosters:
307
+
308
+ ```bash
309
+ # Set up environment variables
310
+ export FRESHGUARD_DATABASE_URL="postgresql://user:password@localhost:5432/db?sslmode=require"
311
+
312
+ # Initialize monitoring configuration
313
+ pnpm exec freshguard init
314
+
315
+ # Test connection
316
+ pnpm exec freshguard test
317
+
318
+ # Run monitoring scheduler
319
+ pnpm exec freshguard run
320
+ ```
321
+
322
+ **Features:**
323
+ - 🔐 **Environment variables** - Secure credential management
324
+ - 📝 **Configuration validation** - Proper setup verification
325
+ - 🔒 **SSL support** - Secure database connections
326
+ - 📊 **Monitoring commands** - Run checks and view results
327
+
328
+ **📋 [Security Guide →](docs/SECURITY_FOR_SELF_HOSTERS.md)**
329
+
330
+ ## 🚀 Self-Hosting
331
+
332
+ ### Production Deployment
333
+
334
+ **📋 [Security Guide →](docs/SECURITY_FOR_SELF_HOSTERS.md)**
335
+
336
+ Important considerations for production deployments:
337
+ - **🔒 Security checklist and best practices**
338
+ - **🗄️ Database security configuration** (PostgreSQL, BigQuery, Snowflake)
339
+ - **🌐 Network configuration**
340
+ - **🔑 Credential management**
341
+ - **📊 Monitoring and logging**
342
+
343
+ ### Deployment Guides
344
+
345
+ See the [Self-Hosting Guide](docs/SELF_HOSTING.md) for:
346
+ - Docker deployment with security hardening
347
+ - Kubernetes setup with secrets management
348
+ - Environment configuration examples
349
+ - Custom alerting integration
350
+
351
+ ## What's Not Included
352
+
353
+ This is the **open source core**. It does not include:
354
+ - Managed hosting (you manage uptime)
355
+ - Multi-user dashboard and config UI (use config files instead)
356
+
357
+ Want these features? Check out **[FreshGuard Cloud](https://freshguard.dev)** - our managed SaaS.
358
+
359
+ ## Architecture
360
+
361
+ FreshGuard uses an **Open Core** model:
362
+
363
+ - **`@freshguard/freshguard-core`** (this package) - MIT licensed, open source monitoring engine
364
+ - **`freshguard`** - Proprietary multi-tenant SaaS (optional)
365
+
366
+ You can self-host the core or use our managed cloud service.
367
+
368
+ ## Contributing
369
+
370
+ We welcome contributions! See [CONTRIBUTING.md](docs/CONTRIBUTING.md).
371
+
372
+ ## Examples
373
+
374
+ ### 📊 Database Connections
375
+
376
+ ```typescript
377
+ import { PostgresConnector, BigQueryConnector } from '@freshguard/freshguard-core';
378
+
379
+ // PostgreSQL connection
380
+ const pgConfig = {
381
+ host: 'localhost',
382
+ port: 5432,
383
+ database: 'myapp',
384
+ username: process.env.DB_USER!,
385
+ password: process.env.DB_PASSWORD!,
386
+ ssl: true, // Enable SSL for secure connections
387
+ };
388
+ const postgres = new PostgresConnector(pgConfig);
389
+
390
+ // BigQuery connection
391
+ const bqConfig = {
392
+ host: 'bigquery.googleapis.com',
393
+ database: 'my-project',
394
+ password: process.env.BIGQUERY_SERVICE_ACCOUNT_JSON!,
395
+ ssl: true,
396
+ };
397
+ const bigquery = new BigQueryConnector(bqConfig);
398
+ ```
399
+
400
+ ### 🔔 Custom Alerting
401
+
402
+ ```typescript
403
+ import { checkFreshness } from '@freshguard/freshguard-core';
404
+ import { PostgresConnector } from '@freshguard/freshguard-core';
405
+ import { sendSlackAlert } from './alerts.js';
406
+
407
+ // Database connection
408
+ const connector = new PostgresConnector({
409
+ host: process.env.DB_HOST!,
410
+ database: process.env.DB_NAME!,
411
+ username: process.env.DB_USER!,
412
+ password: process.env.DB_PASSWORD!,
413
+ ssl: true,
414
+ });
415
+
416
+ const result = await checkFreshness(connector, rule);
417
+
418
+ if (result.status === 'alert') {
419
+ await sendSlackAlert({
420
+ channel: '#data-alerts',
421
+ message: `⚠️ ${rule.name} is stale (${result.lagMinutes}m lag)`,
422
+ });
423
+ }
424
+ ```
425
+
426
+ ### 📅 Scheduled Monitoring
427
+
428
+ ```typescript
429
+ import { checkFreshness, checkVolumeAnomaly, checkSchemaChanges } from '@freshguard/freshguard-core';
430
+ import { PostgresConnector } from '@freshguard/freshguard-core';
431
+ import cron from 'node-cron';
432
+
433
+ const connector = new PostgresConnector({
434
+ host: process.env.DB_HOST!,
435
+ database: process.env.DB_NAME!,
436
+ username: process.env.DB_USER!,
437
+ password: process.env.DB_PASSWORD!,
438
+ ssl: true,
439
+ });
440
+
441
+ // Run every 5 minutes with comprehensive error handling
442
+ cron.schedule('*/5 * * * *', async () => {
443
+ try {
444
+ const result = await checkFreshness(connector, rule);
445
+ console.log(`✅ Check result: ${result.status}`);
446
+ } catch (error) {
447
+ // Import error classes for specific handling
448
+ const { SecurityError, ConnectionError, TimeoutError } = require('@freshguard/freshguard-core');
449
+
450
+ if (error instanceof ConnectionError) {
451
+ console.error(`🔌 Database connection failed: ${error.message}`);
452
+ // Implement reconnection logic
453
+ } else if (error instanceof TimeoutError) {
454
+ console.error(`⏱️ Query timeout: ${error.message}`);
455
+ // Alert ops team about performance issues
456
+ } else if (error instanceof SecurityError) {
457
+ console.error(`🔒 Security violation: ${error.message}`);
458
+ // Log security incident for investigation
459
+ } else {
460
+ console.error(`❌ Monitoring failed: ${error.message}`);
461
+ }
462
+ }
463
+ });
464
+
465
+ // Monitor schema changes hourly
466
+ cron.schedule('0 * * * *', async () => {
467
+ try {
468
+ const schemaRule = {
469
+ id: 'user-schema-monitor',
470
+ sourceId: 'prod_db',
471
+ name: 'User Table Schema Monitor',
472
+ tableName: 'users',
473
+ ruleType: 'schema_change',
474
+ checkIntervalMinutes: 60,
475
+ isActive: true,
476
+ schemaChangeConfig: {
477
+ adaptationMode: 'manual', // Require manual approval
478
+ monitoringMode: 'full', // Monitor all columns
479
+ trackedColumns: {
480
+ alertLevel: 'high', // High-priority alerts
481
+ trackTypes: true,
482
+ trackNullability: false
483
+ }
484
+ },
485
+ createdAt: new Date(),
486
+ updatedAt: new Date(),
487
+ };
488
+
489
+ const result = await checkSchemaChanges(connector, schemaRule, metadataStorage);
490
+
491
+ if (result.status === 'alert') {
492
+ console.log(`🚨 Schema changes detected in users table: ${result.schemaChanges?.summary}`);
493
+ // Send critical alert to operations team
494
+ } else {
495
+ console.log(`✅ Schema check passed: ${result.schemaChanges?.changeCount || 0} changes`);
496
+ }
497
+ } catch (error) {
498
+ console.error(`❌ Schema monitoring failed: ${error.message}`);
499
+ }
500
+ });
501
+ ```
502
+
503
+
504
+ ## 📚 API Documentation
505
+
506
+ ### Database Connectors
507
+
508
+ ```typescript
509
+ // Import connectors, monitoring functions, and error classes
510
+ import {
511
+ PostgresConnector,
512
+ DuckDBConnector,
513
+ BigQueryConnector,
514
+ SnowflakeConnector,
515
+ checkFreshness,
516
+ checkVolumeAnomaly,
517
+ checkSchemaChanges,
518
+ SecurityError,
519
+ ConnectionError,
520
+ TimeoutError,
521
+ QueryError,
522
+ ConfigurationError,
523
+ MonitoringError
524
+ } from '@freshguard/freshguard-core';
525
+ ```
526
+
527
+ ### Error Classes
528
+
529
+ FreshGuard Core provides comprehensive error handling with specific error types:
530
+
531
+ - **`SecurityError`** - SQL injection attempts, invalid identifiers, blocked queries
532
+ - **`ConnectionError`** - Database connection failures, authentication issues
533
+ - **`TimeoutError`** - Query timeouts, connection timeouts
534
+ - **`QueryError`** - Syntax errors, table/column not found, execution failures
535
+ - **`ConfigurationError`** - Missing required fields, invalid configuration values
536
+ - **`MonitoringError`** - Freshness check failures, volume anomaly detection errors
537
+
538
+ All errors include:
539
+ - `error.code` - Machine-readable error code
540
+ - `error.timestamp` - Error occurrence timestamp
541
+ - `error.sanitized` - Whether the message is safe for user display
542
+
543
+ ### `checkFreshness(connector, rule)`
544
+
545
+ Check data freshness for a given monitoring rule.
546
+
547
+ **Parameters:**
548
+ - `connector` - Database connector (PostgresConnector, BigQueryConnector, etc.)
549
+ - `rule` - Monitoring rule configuration
550
+
551
+ **Returns:** `Promise<CheckResult>` with status and lag information
552
+
553
+ ### `checkVolumeAnomaly(connector, rule)`
554
+
555
+ Check for volume anomalies in row counts.
556
+
557
+ **Parameters:**
558
+ - `connector` - Database connector
559
+ - `rule` - Monitoring rule configuration
560
+
561
+ **Returns:** `Promise<CheckResult>` with anomaly detection results
562
+
563
+ ### `checkSchemaChanges(connector, rule)`
564
+
565
+ Monitor database schema changes with configurable adaptation modes.
566
+
567
+ **Parameters:**
568
+ - `connector` - Secure database connector
569
+ - `rule` - Monitoring rule with `ruleType: 'schema_change'` and optional `schemaChangeConfig`
570
+ - `metadataStorage` (optional) - Metadata storage for baseline persistence
571
+
572
+ **Returns:** `Promise<CheckResult>` with `schemaChanges` field containing:
573
+ - `hasChanges` - Boolean indicating if changes were detected
574
+ - `addedColumns` - Array of newly added columns
575
+ - `removedColumns` - Array of removed columns (breaking changes)
576
+ - `modifiedColumns` - Array of type/constraint changes
577
+ - `summary` - Human-readable change summary
578
+ - `changeCount` - Total number of changes
579
+ - `severity` - Change impact level ('low', 'medium', 'high')
580
+
581
+ ### Database Connectors
582
+
583
+ **PostgresConnector** - PostgreSQL databases with SSL support
584
+ ```typescript
585
+ const connector = new PostgresConnector({
586
+ host: 'localhost',
587
+ port: 5432,
588
+ database: 'myapp',
589
+ username: process.env.DB_USER!,
590
+ password: process.env.DB_PASSWORD!,
591
+ ssl: true, // Enable SSL for secure connections
592
+ });
593
+ ```
594
+
595
+ **BigQueryConnector** - Google Cloud BigQuery data warehouses
596
+ **SnowflakeConnector** - Snowflake data platform integration
597
+ **DuckDBConnector** - DuckDB for analytics and development
598
+
599
+ ### 🔧 Environment Setup
600
+
601
+ Copy `.env.example` to `.env` for secure configuration:
602
+
603
+ ```bash
604
+ cp .env.example .env
605
+ # Edit .env with your secure credentials
606
+ ```
607
+
608
+ The `.env.example` file includes comprehensive security guidelines and examples for all supported databases.
609
+
610
+ ## License
611
+
612
+ MIT - See [LICENSE](./LICENSE)
613
+
614
+ ## 📞 Support
615
+
616
+ ### 📋 Documentation
617
+
618
+ **🚀 Getting Started**
619
+ - **🔧 [Integration Guide](docs/INTEGRATION_GUIDE.md)** - Complete integration examples for developers
620
+ - **🏠 [Self-Hosting Guide](docs/SELF_HOSTING.md)** - Production deployment with security features
621
+ - **🤝 [Contributing Guide](docs/CONTRIBUTING.md)** - Development setup and guidelines
622
+
623
+ **🔒 Security & Production**
624
+ - **🛡️ [Security Guide](docs/SECURITY_FOR_SELF_HOSTERS.md)**
625
+
626
+ **🏗️ Advanced Topics**
627
+ - **⚙️ Configuration Examples** - Environment-specific setups (dev/staging/prod)
628
+ - **📈 Monitoring & Observability** - Structured logging, metrics, and alerting
629
+ - **🔄 Multi-Database Setup** - PostgreSQL, BigQuery, Snowflake, DuckDB integration
630
+ - **🚨 Circuit Breakers & Resilience** - Automatic failure recovery and protection
631
+
632
+ ### 💬 Community
633
+ - **🐛 [Issues](https://github.com/freshguard/freshguard/issues)** - Bug reports and feature requests
634
+ - **💭 [Discussions](https://github.com/freshguard/freshguard/discussions)** - Questions and community support
635
+
636
+ ## Need Managed Hosting?
637
+
638
+ Self-hosting requires ops. Want a managed experience?
639
+
640
+ **[Try FreshGuard Cloud (COMING SOON)](https://freshguard.dev)**
641
+
642
+ ---
643
+
644
+ Built with ❤️ by the FreshGuard community
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}