@snapback/cli 1.6.0 → 3.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 (57) hide show
  1. package/README.md +120 -21
  2. package/dist/SkippedTestDetector-AXTMWWHC.js +5 -0
  3. package/dist/SkippedTestDetector-QLSQV7K7.js +5 -0
  4. package/dist/analysis-6WTBZJH3.js +6 -0
  5. package/dist/analysis-C472LUGW.js +2475 -0
  6. package/dist/auth-TDIHGKKL.js +1446 -0
  7. package/dist/auto-provision-organization-CXHL46P3.js +161 -0
  8. package/dist/{chunk-FVIYXFCL.js → chunk-4YTE4JEW.js} +2 -3
  9. package/dist/chunk-5EOPYJ4Y.js +12 -0
  10. package/dist/{chunk-ARVV3F4K.js → chunk-5SQA44V7.js} +1085 -18
  11. package/dist/{chunk-RB7H4UQJ.js → chunk-7ADPL4Q3.js} +10 -3
  12. package/dist/chunk-CBGOC6RV.js +293 -0
  13. package/dist/chunk-CPZWXRP2.js +4432 -0
  14. package/dist/{chunk-7JX6Y4TL.js → chunk-DPWFZNMY.js} +21 -34
  15. package/dist/{chunk-R7CUQ7CU.js → chunk-E6V6QKS7.js} +317 -33
  16. package/dist/chunk-FMWCFAY7.js +111 -0
  17. package/dist/chunk-GQ73B37K.js +314 -0
  18. package/dist/chunk-LIBBDBW5.js +6136 -0
  19. package/dist/chunk-O7HMAZ7L.js +3497 -0
  20. package/dist/chunk-PL4HF4M2.js +593 -0
  21. package/dist/chunk-Q4VC7GND.js +2300 -0
  22. package/dist/chunk-WS36HDEU.js +3735 -0
  23. package/dist/chunk-ZBQDE6WJ.js +108 -0
  24. package/dist/client-62E3L6DW.js +8 -0
  25. package/dist/dist-5LR7APG5.js +5 -0
  26. package/dist/dist-NFU5UJEW.js +9 -0
  27. package/dist/dist-OO5LJHL6.js +12 -0
  28. package/dist/index.js +61644 -37198
  29. package/dist/local-service-adapter-AB3UYRUK.js +6 -0
  30. package/dist/pioneer-oauth-hook-V2JKEXM7.js +12 -0
  31. package/dist/{secure-credentials-IWQB6KU4.js → secure-credentials-UEPG7GWW.js} +2 -3
  32. package/dist/snapback-dir-MG7DTRMF.js +6 -0
  33. package/package.json +12 -11
  34. package/scripts/postinstall.mjs +2 -3
  35. package/dist/SkippedTestDetector-5WJZKZQ3.js +0 -5
  36. package/dist/SkippedTestDetector-5WJZKZQ3.js.map +0 -1
  37. package/dist/analysis-YI4UNUCM.js +0 -6
  38. package/dist/analysis-YI4UNUCM.js.map +0 -1
  39. package/dist/chunk-7JX6Y4TL.js.map +0 -1
  40. package/dist/chunk-ARVV3F4K.js.map +0 -1
  41. package/dist/chunk-EU2IZPOK.js +0 -13002
  42. package/dist/chunk-EU2IZPOK.js.map +0 -1
  43. package/dist/chunk-FVIYXFCL.js.map +0 -1
  44. package/dist/chunk-R7CUQ7CU.js.map +0 -1
  45. package/dist/chunk-RB7H4UQJ.js.map +0 -1
  46. package/dist/chunk-SOABQWAU.js +0 -385
  47. package/dist/chunk-SOABQWAU.js.map +0 -1
  48. package/dist/dist-O6EBXLN6.js +0 -5
  49. package/dist/dist-O6EBXLN6.js.map +0 -1
  50. package/dist/dist-PJVBBZTF.js +0 -5
  51. package/dist/dist-PJVBBZTF.js.map +0 -1
  52. package/dist/index.js.map +0 -1
  53. package/dist/learning-pruner-QC4CTJDX.js +0 -5
  54. package/dist/learning-pruner-QC4CTJDX.js.map +0 -1
  55. package/dist/secure-credentials-IWQB6KU4.js.map +0 -1
  56. package/dist/snapback-dir-V6MWXIW4.js +0 -5
  57. package/dist/snapback-dir-V6MWXIW4.js.map +0 -1
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env node --no-warnings=ExperimentalWarning
2
+ import { logger } from './chunk-PL4HF4M2.js';
3
+ import { __name } from './chunk-7ADPL4Q3.js';
4
+
5
+ process.env.SNAPBACK_CLI='true';
6
+
7
+ // ../../packages/auth/dist/lib/audit.js
8
+ var POSTHOG_API_KEY = process.env.POSTHOG_API_KEY || "";
9
+ var POSTHOG_HOST = process.env.POSTHOG_HOST || "https://us.posthog.com";
10
+ var POSTHOG_ENABLED = !!POSTHOG_API_KEY;
11
+ async function emitPostHogEvent(eventType, metadata) {
12
+ if (!POSTHOG_ENABLED) {
13
+ return;
14
+ }
15
+ try {
16
+ const event = {
17
+ api_key: POSTHOG_API_KEY,
18
+ event: eventType,
19
+ distinct_id: metadata.userId || metadata.ip || "anonymous",
20
+ properties: {
21
+ ...metadata,
22
+ $ip: metadata.ip,
23
+ $set: {
24
+ email: metadata.userId ? `user_${metadata.userId}` : void 0
25
+ }
26
+ },
27
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
28
+ };
29
+ const response = await fetch(`${POSTHOG_HOST}/capture/`, {
30
+ method: "POST",
31
+ headers: {
32
+ "Content-Type": "application/json"
33
+ },
34
+ body: JSON.stringify(event)
35
+ });
36
+ if (!response.ok) {
37
+ logger.error("Failed to emit PostHog event", {
38
+ eventType,
39
+ status: response.status,
40
+ statusText: response.statusText
41
+ });
42
+ }
43
+ } catch (error) {
44
+ logger.error("Error emitting PostHog event", {
45
+ error,
46
+ eventType
47
+ });
48
+ }
49
+ }
50
+ __name(emitPostHogEvent, "emitPostHogEvent");
51
+ async function writeAuditLog(eventType, metadata) {
52
+ try {
53
+ const { db, snapbackSchema } = await import('./dist-OO5LJHL6.js');
54
+ if (!db) {
55
+ logger.warn("Database not available for audit logging", {
56
+ eventType
57
+ });
58
+ return;
59
+ }
60
+ const { telemetryEvents } = snapbackSchema;
61
+ await db.insert(telemetryEvents).values({
62
+ eventType,
63
+ eventCategory: "audit",
64
+ userId: metadata.userId,
65
+ properties: {
66
+ ip: metadata.ip,
67
+ userAgent: metadata.userAgent,
68
+ method: metadata.method,
69
+ path: metadata.path,
70
+ statusCode: metadata.statusCode,
71
+ errorMessage: metadata.errorMessage,
72
+ ...metadata
73
+ }
74
+ });
75
+ logger.debug("Audit log written", {
76
+ eventType,
77
+ userId: metadata.userId,
78
+ orgId: metadata.orgId
79
+ });
80
+ } catch (error) {
81
+ logger.error("Failed to write audit log", {
82
+ error,
83
+ eventType,
84
+ metadata
85
+ });
86
+ }
87
+ }
88
+ __name(writeAuditLog, "writeAuditLog");
89
+ async function trackEvent(eventType, metadata) {
90
+ logger.info("Audit event", {
91
+ eventType,
92
+ userId: metadata.userId,
93
+ orgId: metadata.orgId,
94
+ path: metadata.path
95
+ });
96
+ emitPostHogEvent(eventType, metadata).catch((error) => {
97
+ logger.error("PostHog emit failed", {
98
+ error,
99
+ eventType
100
+ });
101
+ });
102
+ writeAuditLog(eventType, metadata).catch((error) => {
103
+ logger.error("Audit log write failed", {
104
+ error,
105
+ eventType
106
+ });
107
+ });
108
+ }
109
+ __name(trackEvent, "trackEvent");
110
+
111
+ export { trackEvent };
@@ -0,0 +1,314 @@
1
+ #!/usr/bin/env node --no-warnings=ExperimentalWarning
2
+ import { createLogger, LogLevel } from './chunk-WS36HDEU.js';
3
+ import { __name } from './chunk-7ADPL4Q3.js';
4
+ import { createClient } from 'redis';
5
+
6
+ process.env.SNAPBACK_CLI='true';
7
+ createLogger({
8
+ name: "redis-factory",
9
+ level: LogLevel.INFO
10
+ });
11
+ function isSocketTimeoutError(cause) {
12
+ if (!cause) return false;
13
+ return cause?.name === "SocketTimeoutError" || cause?.message?.includes("socket timeout");
14
+ }
15
+ __name(isSocketTimeoutError, "isSocketTimeoutError");
16
+
17
+ // ../../packages/platform/dist/cache/redis-metrics.js
18
+ var LATENCY_THRESHOLDS = {
19
+ /** Under 100ms is healthy */
20
+ healthy: 100,
21
+ /** Under 500ms is degraded */
22
+ degraded: 500
23
+ };
24
+ var RedisMetricsCollector = class {
25
+ static {
26
+ __name(this, "RedisMetricsCollector");
27
+ }
28
+ reconnectAttempts = 0;
29
+ lastSuccessAt = null;
30
+ lastErrorAt = null;
31
+ lastError = null;
32
+ keyPrefix;
33
+ constructor(keyPrefix = "") {
34
+ this.keyPrefix = keyPrefix;
35
+ }
36
+ /**
37
+ * Record a successful operation
38
+ */
39
+ recordSuccess() {
40
+ this.lastSuccessAt = Date.now();
41
+ }
42
+ /**
43
+ * Record an error
44
+ */
45
+ recordError(error) {
46
+ this.lastErrorAt = Date.now();
47
+ this.lastError = error.message;
48
+ }
49
+ /**
50
+ * Record a reconnection attempt
51
+ */
52
+ recordReconnect() {
53
+ this.reconnectAttempts++;
54
+ }
55
+ /**
56
+ * Reset reconnection counter (after successful connection)
57
+ */
58
+ resetReconnectCount() {
59
+ this.reconnectAttempts = 0;
60
+ }
61
+ /**
62
+ * Measure Redis latency using PING command
63
+ */
64
+ async measureLatency(client) {
65
+ if (!client || !client.isReady) {
66
+ return null;
67
+ }
68
+ try {
69
+ const start = Date.now();
70
+ await client.ping();
71
+ const latency = Date.now() - start;
72
+ this.recordSuccess();
73
+ return latency;
74
+ } catch (error) {
75
+ this.recordError(error);
76
+ return null;
77
+ }
78
+ }
79
+ /**
80
+ * Collect comprehensive metrics
81
+ */
82
+ async collect(client) {
83
+ const isConnected = client?.isReady ?? false;
84
+ const isOpen = client?.isOpen ?? false;
85
+ const latency = await this.measureLatency(client);
86
+ let status;
87
+ let message;
88
+ if (!isConnected) {
89
+ status = "unhealthy";
90
+ message = "Redis client not connected";
91
+ } else if (latency === null) {
92
+ status = "unhealthy";
93
+ message = "Redis PING failed";
94
+ } else if (latency < LATENCY_THRESHOLDS.healthy) {
95
+ status = "healthy";
96
+ message = `Redis latency: ${latency}ms`;
97
+ } else if (latency < LATENCY_THRESHOLDS.degraded) {
98
+ status = "degraded";
99
+ message = `Redis latency elevated: ${latency}ms`;
100
+ } else {
101
+ status = "unhealthy";
102
+ message = `Redis latency too high: ${latency}ms`;
103
+ }
104
+ return {
105
+ isConnected,
106
+ isOpen,
107
+ latency,
108
+ status,
109
+ message,
110
+ lastSuccessAt: this.lastSuccessAt,
111
+ lastErrorAt: this.lastErrorAt,
112
+ lastError: this.lastError,
113
+ reconnectAttempts: this.reconnectAttempts,
114
+ keyPrefix: this.keyPrefix
115
+ };
116
+ }
117
+ /**
118
+ * Get current reconnection attempt count
119
+ */
120
+ getReconnectAttempts() {
121
+ return this.reconnectAttempts;
122
+ }
123
+ };
124
+ var metricsCollectors = /* @__PURE__ */ new Map();
125
+ function getMetricsCollector(keyPrefix = "") {
126
+ let collector = metricsCollectors.get(keyPrefix);
127
+ if (!collector) {
128
+ collector = new RedisMetricsCollector(keyPrefix);
129
+ metricsCollectors.set(keyPrefix, collector);
130
+ }
131
+ return collector;
132
+ }
133
+ __name(getMetricsCollector, "getMetricsCollector");
134
+
135
+ // ../../packages/platform/dist/cache/redis-client.js
136
+ var logger2 = createLogger({
137
+ name: "redis-client",
138
+ level: LogLevel.INFO
139
+ });
140
+ var KEY_PREFIX = "cache:";
141
+ var redisClient = null;
142
+ var redisAvailable = false;
143
+ var initializationPromise = null;
144
+ var metricsCollector = getMetricsCollector(KEY_PREFIX);
145
+ async function initializeRedis() {
146
+ if (initializationPromise) {
147
+ return initializationPromise;
148
+ }
149
+ initializationPromise = (async () => {
150
+ const redisUrl = process.env.REDIS_URL;
151
+ if (!redisUrl) {
152
+ logger2.warn("REDIS_URL not configured - using in-memory fallback for caching");
153
+ return;
154
+ }
155
+ try {
156
+ redisClient = createClient({
157
+ url: redisUrl,
158
+ socket: {
159
+ // Connection timeout - how long to wait for initial connection
160
+ connectTimeout: 1e4,
161
+ // TCP keepalive - prevents silent connection drops
162
+ keepAlive: 5e3,
163
+ // Reconnection strategy with exponential backoff + jitter
164
+ reconnectStrategy: /* @__PURE__ */ __name((retries, cause) => {
165
+ if (isSocketTimeoutError(cause)) {
166
+ logger2.warn("Redis socket timeout - not reconnecting", {
167
+ cause: cause?.message
168
+ });
169
+ return false;
170
+ }
171
+ if (retries > 20) {
172
+ logger2.error("Redis max retries exceeded", {
173
+ retries,
174
+ cause: cause?.message
175
+ });
176
+ return new Error("Redis connection failed");
177
+ }
178
+ const baseDelay = Math.min(2 ** retries * 100, 3e4);
179
+ const jitter = Math.floor(Math.random() * 200);
180
+ return baseDelay + jitter;
181
+ }, "reconnectStrategy")
182
+ },
183
+ // Application-level ping to keep connection alive
184
+ pingInterval: 6e4
185
+ });
186
+ redisClient.on("error", (err) => {
187
+ if (err.message.includes("ECONNRESET") || err.message.includes("ECONNREFUSED")) {
188
+ logger2.debug("Redis connection error (will reconnect)", {
189
+ error: err.message
190
+ });
191
+ } else {
192
+ logger2.warn("Redis client error", {
193
+ error: err.message
194
+ });
195
+ }
196
+ redisAvailable = false;
197
+ metricsCollector.recordError(err);
198
+ });
199
+ redisClient.on("connect", () => {
200
+ redisAvailable = true;
201
+ metricsCollector.resetReconnectCount();
202
+ if (process.env.NODE_ENV !== "production") {
203
+ logger2.info("Redis connected for platform caching");
204
+ }
205
+ });
206
+ redisClient.on("ready", () => {
207
+ redisAvailable = true;
208
+ logger2.debug("Redis client ready for platform caching");
209
+ });
210
+ redisClient.on("reconnecting", () => {
211
+ metricsCollector.recordReconnect();
212
+ logger2.debug("Redis reconnecting for platform caching");
213
+ });
214
+ await redisClient.connect();
215
+ redisAvailable = true;
216
+ if (process.env.NODE_ENV !== "production") {
217
+ logger2.info("\u2705 Redis client initialized for platform caching with production config");
218
+ }
219
+ } catch (error) {
220
+ logger2.error("Redis initialization failed", {
221
+ error: error instanceof Error ? error.message : String(error)
222
+ });
223
+ redisAvailable = false;
224
+ }
225
+ })();
226
+ return initializationPromise;
227
+ }
228
+ __name(initializeRedis, "initializeRedis");
229
+ async function getCache(key) {
230
+ await initializeRedis();
231
+ if (!redisAvailable || !redisClient) {
232
+ return null;
233
+ }
234
+ try {
235
+ const value = await redisClient.get(key);
236
+ if (!value) {
237
+ return null;
238
+ }
239
+ return JSON.parse(value);
240
+ } catch (error) {
241
+ logger2.error("Redis GET failed", {
242
+ key,
243
+ error
244
+ });
245
+ return null;
246
+ }
247
+ }
248
+ __name(getCache, "getCache");
249
+ async function setCache(key, value, ttlSeconds) {
250
+ await initializeRedis();
251
+ if (!redisAvailable || !redisClient) {
252
+ return false;
253
+ }
254
+ try {
255
+ const serialized = JSON.stringify(value);
256
+ if (ttlSeconds) {
257
+ await redisClient.set(key, serialized, {
258
+ EX: ttlSeconds
259
+ });
260
+ } else {
261
+ await redisClient.set(key, serialized);
262
+ }
263
+ return true;
264
+ } catch (error) {
265
+ logger2.error("Redis SET failed", {
266
+ key,
267
+ error
268
+ });
269
+ return false;
270
+ }
271
+ }
272
+ __name(setCache, "setCache");
273
+ async function deleteCache(key) {
274
+ await initializeRedis();
275
+ if (!redisAvailable || !redisClient) {
276
+ return false;
277
+ }
278
+ try {
279
+ await redisClient.del(key);
280
+ return true;
281
+ } catch (error) {
282
+ logger2.error("Redis DEL failed", {
283
+ key,
284
+ error
285
+ });
286
+ return false;
287
+ }
288
+ }
289
+ __name(deleteCache, "deleteCache");
290
+ async function closeRedis() {
291
+ if (redisClient) {
292
+ try {
293
+ await redisClient.quit();
294
+ logger2.info("Redis connection closed");
295
+ } catch (error) {
296
+ logger2.error("Error closing Redis connection", {
297
+ error
298
+ });
299
+ }
300
+ redisClient = null;
301
+ redisAvailable = false;
302
+ }
303
+ }
304
+ __name(closeRedis, "closeRedis");
305
+ function isRedisAvailable() {
306
+ return redisAvailable;
307
+ }
308
+ __name(isRedisAvailable, "isRedisAvailable");
309
+ function getRedisClient() {
310
+ return redisClient;
311
+ }
312
+ __name(getRedisClient, "getRedisClient");
313
+
314
+ export { closeRedis, deleteCache, getCache, getRedisClient, initializeRedis, isRedisAvailable, setCache };