gateops-core 0.1.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.
@@ -0,0 +1,570 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ var sqliteCore = require('drizzle-orm/sqlite-core');
5
+ var Database = require('better-sqlite3');
6
+ var betterSqlite3 = require('drizzle-orm/better-sqlite3');
7
+ var drizzleOrm = require('drizzle-orm');
8
+ var fs2 = require('fs');
9
+ var path2 = require('path');
10
+ var commander = require('commander');
11
+ var inquirer = require('inquirer');
12
+ var chalk = require('chalk');
13
+ var axios = require('axios');
14
+
15
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
16
+
17
+ function _interopNamespace(e) {
18
+ if (e && e.__esModule) return e;
19
+ var n = Object.create(null);
20
+ if (e) {
21
+ Object.keys(e).forEach(function (k) {
22
+ if (k !== 'default') {
23
+ var d = Object.getOwnPropertyDescriptor(e, k);
24
+ Object.defineProperty(n, k, d.get ? d : {
25
+ enumerable: true,
26
+ get: function () { return e[k]; }
27
+ });
28
+ }
29
+ });
30
+ }
31
+ n.default = e;
32
+ return Object.freeze(n);
33
+ }
34
+
35
+ var Database__default = /*#__PURE__*/_interopDefault(Database);
36
+ var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
37
+ var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
38
+ var inquirer__default = /*#__PURE__*/_interopDefault(inquirer);
39
+ var chalk__default = /*#__PURE__*/_interopDefault(chalk);
40
+ var axios__default = /*#__PURE__*/_interopDefault(axios);
41
+
42
+ var __defProp = Object.defineProperty;
43
+ var __getOwnPropNames = Object.getOwnPropertyNames;
44
+ var __esm = (fn, res) => function __init() {
45
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
46
+ };
47
+ var __commonJS = (cb, mod) => function __require() {
48
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
49
+ };
50
+ var __export = (target, all) => {
51
+ for (var name in all)
52
+ __defProp(target, name, { get: all[name], enumerable: true });
53
+ };
54
+
55
+ // src/config.ts
56
+ function getPanelUrl(endpoint) {
57
+ return `${PANEL_BASE_URL}${PANEL_ENDPOINTS[endpoint]}`;
58
+ }
59
+ var PANEL_BASE_URL, PANEL_ENDPOINTS, SDK_DEFAULTS;
60
+ var init_config = __esm({
61
+ "src/config.ts"() {
62
+ PANEL_BASE_URL = process.env.GATEOPS_PANEL_URL || "https://gateops.sleeksoulsmedia.com";
63
+ PANEL_ENDPOINTS = {
64
+ // Verify API key during initialization
65
+ VERIFY: "/api/sdk/verify",
66
+ // Send batched logs to Panel
67
+ LOGS: "/api/sdk/logs",
68
+ // Fetch remote configuration (optional)
69
+ CONFIG: "/api/sdk/config",
70
+ // Send discovered endpoints/routes
71
+ ENDPOINTS: "/api/sdk/endpoints",
72
+ // Heartbeat/health check
73
+ HEARTBEAT: "/api/sdk/heartbeat"
74
+ };
75
+ SDK_DEFAULTS = {
76
+ // Buffer settings
77
+ BUFFER_MAX_SIZE: 50,
78
+ // Flush when buffer reaches this size
79
+ BUFFER_FLUSH_INTERVAL: 1e4,
80
+ // Flush every 10 seconds (ms)
81
+ // Payload limits
82
+ MAX_BODY_SIZE: 10240,
83
+ // 10KB max for req/res bodies
84
+ // Log retention
85
+ LOG_TTL_DAYS: 15,
86
+ // Auto-cleanup logs older than 15 days
87
+ // Retry settings
88
+ MAX_RETRY_ATTEMPTS: 3,
89
+ RETRY_DELAY_BASE: 1e3,
90
+ // Base delay for exponential backoff (ms)
91
+ // Database
92
+ DEFAULT_DB_PATH: ".gateops/data.sqlite",
93
+ BUFFER_FILE_PATH: ".gateops/buffer.json",
94
+ // Route prefix for exposed endpoints
95
+ ROUTE_PREFIX: "/.well-known/gateops"
96
+ };
97
+ }
98
+ });
99
+
100
+ // src/db/schema.ts
101
+ var schema_exports = {};
102
+ __export(schema_exports, {
103
+ config: () => config,
104
+ endpoints: () => endpoints,
105
+ trafficLogs: () => trafficLogs
106
+ });
107
+ var trafficLogs, endpoints, config;
108
+ var init_schema = __esm({
109
+ "src/db/schema.ts"() {
110
+ trafficLogs = sqliteCore.sqliteTable("gateops_traffic_logs", {
111
+ id: sqliteCore.integer("id").primaryKey({ autoIncrement: true }),
112
+ // Unique identifier for request tracing
113
+ trace_id: sqliteCore.text("trace_id").notNull(),
114
+ // Request info
115
+ endpoint: sqliteCore.text("endpoint").notNull(),
116
+ method: sqliteCore.text("method").notNull(),
117
+ status: sqliteCore.integer("status").notNull(),
118
+ duration_ms: sqliteCore.integer("duration_ms").notNull(),
119
+ // Headers (JSON strings)
120
+ req_headers: sqliteCore.text("req_headers"),
121
+ res_headers: sqliteCore.text("res_headers"),
122
+ // Bodies (JSON strings, sanitized, max 10KB each)
123
+ req_body: sqliteCore.text("req_body"),
124
+ res_body: sqliteCore.text("res_body"),
125
+ // Additional context
126
+ query_params: sqliteCore.text("query_params"),
127
+ ip_address: sqliteCore.text("ip_address"),
128
+ user_agent: sqliteCore.text("user_agent"),
129
+ // Timestamp (stored as Unix timestamp)
130
+ created_at: sqliteCore.integer("created_at", { mode: "timestamp" }).notNull()
131
+ });
132
+ endpoints = sqliteCore.sqliteTable("gateops_endpoints", {
133
+ id: sqliteCore.integer("id").primaryKey({ autoIncrement: true }),
134
+ // Route identification (unique constraint on path + method)
135
+ path: sqliteCore.text("path").notNull(),
136
+ method: sqliteCore.text("method").notNull(),
137
+ // Inferred request/response schema (JSON string)
138
+ // Deep inference captures nested structures
139
+ detected_schema: sqliteCore.text("detected_schema"),
140
+ // List of middleware names (JSON array)
141
+ middleware_names: sqliteCore.text("middleware_names"),
142
+ // Last time this endpoint was hit
143
+ last_seen: sqliteCore.integer("last_seen", { mode: "timestamp" }).notNull()
144
+ });
145
+ config = sqliteCore.sqliteTable("gateops_config", {
146
+ // Unique key name
147
+ key: sqliteCore.text("key").primaryKey(),
148
+ // Value as JSON string
149
+ value: sqliteCore.text("value").notNull(),
150
+ // When this config was last updated
151
+ updated_at: sqliteCore.integer("updated_at", { mode: "timestamp" })
152
+ });
153
+ }
154
+ });
155
+
156
+ // src/db/index.ts
157
+ var db_exports = {};
158
+ __export(db_exports, {
159
+ cleanupOldLogs: () => cleanupOldLogs,
160
+ closeDatabase: () => closeDatabase,
161
+ config: () => config,
162
+ endpoints: () => endpoints,
163
+ getDatabase: () => getDatabase,
164
+ initializeSchema: () => initializeSchema,
165
+ trafficLogs: () => trafficLogs
166
+ });
167
+ function getDatabase(dbPath) {
168
+ if (db) {
169
+ return db;
170
+ }
171
+ const resolvedPath = dbPath || process.env.GATEOPS_DB_PATH || SDK_DEFAULTS.DEFAULT_DB_PATH;
172
+ const absolutePath = path2__namespace.isAbsolute(resolvedPath) ? resolvedPath : path2__namespace.join(process.cwd(), resolvedPath);
173
+ const dir = path2__namespace.dirname(absolutePath);
174
+ if (!fs2__namespace.existsSync(dir)) {
175
+ fs2__namespace.mkdirSync(dir, { recursive: true });
176
+ }
177
+ sqliteDb = new Database__default.default(absolutePath);
178
+ sqliteDb.pragma("journal_mode = WAL");
179
+ db = betterSqlite3.drizzle(sqliteDb, { schema: schema_exports });
180
+ return db;
181
+ }
182
+ function initializeSchema(database) {
183
+ const targetDb = database || getDatabase();
184
+ targetDb.run(drizzleOrm.sql`
185
+ CREATE TABLE IF NOT EXISTS gateops_traffic_logs (
186
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
187
+ trace_id TEXT NOT NULL,
188
+ endpoint TEXT NOT NULL,
189
+ method TEXT NOT NULL,
190
+ status INTEGER NOT NULL,
191
+ duration_ms INTEGER NOT NULL,
192
+ req_headers TEXT,
193
+ res_headers TEXT,
194
+ req_body TEXT,
195
+ res_body TEXT,
196
+ query_params TEXT,
197
+ ip_address TEXT,
198
+ user_agent TEXT,
199
+ created_at INTEGER NOT NULL
200
+ )
201
+ `);
202
+ targetDb.run(drizzleOrm.sql`
203
+ CREATE INDEX IF NOT EXISTS idx_traffic_logs_created_at
204
+ ON gateops_traffic_logs(created_at)
205
+ `);
206
+ targetDb.run(drizzleOrm.sql`
207
+ CREATE INDEX IF NOT EXISTS idx_traffic_logs_endpoint
208
+ ON gateops_traffic_logs(endpoint, method)
209
+ `);
210
+ targetDb.run(drizzleOrm.sql`
211
+ CREATE INDEX IF NOT EXISTS idx_traffic_logs_status
212
+ ON gateops_traffic_logs(status)
213
+ `);
214
+ targetDb.run(drizzleOrm.sql`
215
+ CREATE TABLE IF NOT EXISTS gateops_endpoints (
216
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
217
+ path TEXT NOT NULL,
218
+ method TEXT NOT NULL,
219
+ detected_schema TEXT,
220
+ middleware_names TEXT,
221
+ last_seen INTEGER NOT NULL,
222
+ UNIQUE(path, method)
223
+ )
224
+ `);
225
+ targetDb.run(drizzleOrm.sql`
226
+ CREATE TABLE IF NOT EXISTS gateops_config (
227
+ key TEXT PRIMARY KEY,
228
+ value TEXT NOT NULL,
229
+ updated_at INTEGER
230
+ )
231
+ `);
232
+ }
233
+ function closeDatabase() {
234
+ if (sqliteDb) {
235
+ sqliteDb.close();
236
+ sqliteDb = null;
237
+ db = null;
238
+ }
239
+ }
240
+ function cleanupOldLogs(ttlDays = SDK_DEFAULTS.LOG_TTL_DAYS) {
241
+ const database = getDatabase();
242
+ const cutoffDate = /* @__PURE__ */ new Date();
243
+ cutoffDate.setDate(cutoffDate.getDate() - ttlDays);
244
+ const result = database.run(drizzleOrm.sql`
245
+ DELETE FROM gateops_traffic_logs
246
+ WHERE created_at < ${Math.floor(cutoffDate.getTime() / 1e3)}
247
+ `);
248
+ return result.changes;
249
+ }
250
+ var db, sqliteDb;
251
+ var init_db = __esm({
252
+ "src/db/index.ts"() {
253
+ init_schema();
254
+ init_config();
255
+ init_schema();
256
+ db = null;
257
+ sqliteDb = null;
258
+ }
259
+ });
260
+
261
+ // package.json
262
+ var require_package = __commonJS({
263
+ "package.json"(exports$1, module) {
264
+ module.exports = {
265
+ name: "gateops-core",
266
+ version: "0.1.0",
267
+ description: "Lightweight API observability SDK for Express.js - Zero-config, privacy-first traffic monitoring",
268
+ main: "dist/index.js",
269
+ module: "dist/index.mjs",
270
+ types: "dist/index.d.ts",
271
+ bin: {
272
+ "gateops-init": "dist/bin/gateops-init.js"
273
+ },
274
+ files: [
275
+ "dist"
276
+ ],
277
+ scripts: {
278
+ build: "tsup",
279
+ dev: "tsup --watch",
280
+ test: "vitest",
281
+ "test:run": "vitest run",
282
+ lint: "eslint src --ext .ts",
283
+ format: "prettier --write src",
284
+ prepublishOnly: "npm run build"
285
+ },
286
+ keywords: [
287
+ "api",
288
+ "observability",
289
+ "monitoring",
290
+ "express",
291
+ "middleware",
292
+ "logging",
293
+ "debugging",
294
+ "documentation",
295
+ "swagger",
296
+ "openapi"
297
+ ],
298
+ author: "GateOps",
299
+ license: "MIT",
300
+ repository: {
301
+ type: "git",
302
+ url: "https://github.com/gateops/gateops-core"
303
+ },
304
+ engines: {
305
+ node: ">=18.0.0"
306
+ },
307
+ peerDependencies: {
308
+ express: "^4.18.0 || ^5.0.0"
309
+ },
310
+ dependencies: {
311
+ axios: "^1.6.0",
312
+ "better-sqlite3": "^11.0.0",
313
+ chalk: "^4.1.2",
314
+ commander: "^12.0.0",
315
+ "drizzle-orm": "^0.29.0",
316
+ inquirer: "^8.2.6",
317
+ uuid: "^9.0.0",
318
+ zod: "^3.22.0"
319
+ },
320
+ devDependencies: {
321
+ "@types/better-sqlite3": "^7.6.8",
322
+ "@types/express": "^4.17.21",
323
+ "@types/inquirer": "^8.2.10",
324
+ "@types/node": "^20.10.0",
325
+ "@types/uuid": "^9.0.7",
326
+ "drizzle-kit": "^0.20.0",
327
+ eslint: "^8.56.0",
328
+ express: "^4.18.2",
329
+ prettier: "^3.2.0",
330
+ tsup: "^8.0.0",
331
+ typescript: "^5.3.0",
332
+ vitest: "^1.2.0"
333
+ }
334
+ };
335
+ }
336
+ });
337
+
338
+ // src/sync.ts
339
+ init_config();
340
+ async function verifyCredentials(username, apiKey) {
341
+ try {
342
+ const response = await axios__default.default.post(
343
+ getPanelUrl("VERIFY"),
344
+ { username },
345
+ {
346
+ headers: {
347
+ "Content-Type": "application/json",
348
+ "x-gateops-username": username,
349
+ "x-gateops-api-key": apiKey
350
+ },
351
+ timeout: 1e4
352
+ }
353
+ );
354
+ return response.data;
355
+ } catch (error) {
356
+ if (axios__default.default.isAxiosError(error)) {
357
+ if (error.response?.status === 401) {
358
+ return {
359
+ success: false,
360
+ message: "Invalid credentials"
361
+ };
362
+ }
363
+ return {
364
+ success: false,
365
+ message: error.message
366
+ };
367
+ }
368
+ return {
369
+ success: false,
370
+ message: "Connection failed"
371
+ };
372
+ }
373
+ }
374
+
375
+ // src/bin/gateops-init.ts
376
+ init_db();
377
+ init_config();
378
+ var program = new commander.Command();
379
+ program.name("gateops-init").description("Initialize GateOps SDK in your Express project").version(require_package().version);
380
+ program.command("init", { isDefault: true }).description("Setup GateOps SDK").option("--username <username>", "GateOps username").option("--api-key <key>", "GateOps API key").option("--skip-verify", "Skip credential verification").option("--force", "Overwrite existing configuration").action(async (options) => {
381
+ console.log(chalk__default.default.cyan.bold("\n\u{1F680} GateOps SDK Setup\n"));
382
+ const gateopsDir = path2__namespace.join(process.cwd(), ".gateops");
383
+ const envPath = path2__namespace.join(process.cwd(), ".env");
384
+ if (fs2__namespace.existsSync(gateopsDir) && !options.force) {
385
+ const { proceed } = await inquirer__default.default.prompt([{
386
+ type: "confirm",
387
+ name: "proceed",
388
+ message: "GateOps appears to be already initialized. Reinitialize?",
389
+ default: false
390
+ }]);
391
+ if (!proceed) {
392
+ console.log(chalk__default.default.yellow("Setup cancelled."));
393
+ return;
394
+ }
395
+ }
396
+ let username = options.username;
397
+ let apiKey = options.apiKey;
398
+ if (fs2__namespace.existsSync(envPath) && (!username || !apiKey)) {
399
+ const envContent = fs2__namespace.readFileSync(envPath, "utf-8");
400
+ const usernameMatch = envContent.match(/GATEOPS_USERNAME=(.+)/);
401
+ const apiKeyMatch = envContent.match(/GATEOPS_API_KEY=(.+)/);
402
+ if (usernameMatch && apiKeyMatch) {
403
+ const { useExisting } = await inquirer__default.default.prompt([{
404
+ type: "confirm",
405
+ name: "useExisting",
406
+ message: "Found existing GateOps credentials in .env. Use them?",
407
+ default: true
408
+ }]);
409
+ if (useExisting) {
410
+ username = usernameMatch[1].trim();
411
+ apiKey = apiKeyMatch[1].trim();
412
+ }
413
+ }
414
+ }
415
+ if (!username || !apiKey) {
416
+ console.log(chalk__default.default.gray("Get your credentials from: https://gateops.sleeksoulsmedia.com\n"));
417
+ const answers = await inquirer__default.default.prompt([
418
+ {
419
+ type: "input",
420
+ name: "username",
421
+ message: "Enter your GateOps Username:",
422
+ validate: (input) => input.length > 0 || "Username is required"
423
+ },
424
+ {
425
+ type: "password",
426
+ name: "apiKey",
427
+ message: "Enter your API Key:",
428
+ mask: "*",
429
+ validate: (input) => input.length > 0 || "API Key is required"
430
+ }
431
+ ]);
432
+ username = answers.username;
433
+ apiKey = answers.apiKey;
434
+ }
435
+ if (!options.skipVerify) {
436
+ console.log(chalk__default.default.gray("\nVerifying credentials with GateOps Panel..."));
437
+ const verification = await verifyCredentials(username, apiKey);
438
+ if (!verification.success) {
439
+ console.log(chalk__default.default.red(`
440
+ \u2717 Verification failed: ${verification.message}`));
441
+ console.log(chalk__default.default.yellow("Use --skip-verify to skip verification (not recommended)\n"));
442
+ process.exit(1);
443
+ }
444
+ console.log(chalk__default.default.green("\u2713 Credentials verified"));
445
+ if (verification.projectName) {
446
+ console.log(chalk__default.default.gray(` Project: ${verification.projectName}`));
447
+ }
448
+ } else {
449
+ console.log(chalk__default.default.yellow("\u26A0 Skipping credential verification"));
450
+ }
451
+ console.log(chalk__default.default.gray("\nSetting up GateOps..."));
452
+ if (!fs2__namespace.existsSync(gateopsDir)) {
453
+ fs2__namespace.mkdirSync(gateopsDir, { recursive: true });
454
+ console.log(chalk__default.default.green("\u2713 Created .gateops/ directory"));
455
+ }
456
+ try {
457
+ const dbPath = path2__namespace.join(gateopsDir, "data.sqlite");
458
+ process.env.GATEOPS_DB_PATH = dbPath;
459
+ getDatabase(dbPath);
460
+ initializeSchema();
461
+ console.log(chalk__default.default.green("\u2713 Initialized database"));
462
+ } catch (error) {
463
+ console.log(chalk__default.default.red("\u2717 Failed to initialize database:", error));
464
+ process.exit(1);
465
+ }
466
+ const { updateEnv } = await inquirer__default.default.prompt([{
467
+ type: "confirm",
468
+ name: "updateEnv",
469
+ message: "Add GateOps credentials to .env file?",
470
+ default: true
471
+ }]);
472
+ if (updateEnv) {
473
+ const envLines = [
474
+ "",
475
+ "# GateOps Configuration",
476
+ `GATEOPS_USERNAME=${username}`,
477
+ `GATEOPS_API_KEY=${apiKey}`,
478
+ "GATEOPS_ENABLED=true",
479
+ ""
480
+ ].join("\n");
481
+ if (fs2__namespace.existsSync(envPath)) {
482
+ let envContent = fs2__namespace.readFileSync(envPath, "utf-8");
483
+ if (envContent.includes("GATEOPS_USERNAME")) {
484
+ envContent = envContent.replace(/GATEOPS_USERNAME=.+/, `GATEOPS_USERNAME=${username}`);
485
+ envContent = envContent.replace(/GATEOPS_API_KEY=.+/, `GATEOPS_API_KEY=${apiKey}`);
486
+ fs2__namespace.writeFileSync(envPath, envContent);
487
+ } else {
488
+ fs2__namespace.appendFileSync(envPath, envLines);
489
+ }
490
+ } else {
491
+ fs2__namespace.writeFileSync(envPath, envLines.trim() + "\n");
492
+ }
493
+ console.log(chalk__default.default.green("\u2713 Updated .env file"));
494
+ }
495
+ const gitignorePath = path2__namespace.join(process.cwd(), ".gitignore");
496
+ if (fs2__namespace.existsSync(gitignorePath)) {
497
+ const gitignoreContent = fs2__namespace.readFileSync(gitignorePath, "utf-8");
498
+ if (!gitignoreContent.includes(".gateops")) {
499
+ fs2__namespace.appendFileSync(gitignorePath, "\n# GateOps\n.gateops/\n");
500
+ console.log(chalk__default.default.green("\u2713 Added .gateops to .gitignore"));
501
+ }
502
+ }
503
+ console.log(chalk__default.default.cyan.bold("\n\u2728 GateOps SDK initialized successfully!\n"));
504
+ console.log(chalk__default.default.white("Next steps:\n"));
505
+ console.log(chalk__default.default.gray("1. Add the middleware to your Express app:\n"));
506
+ console.log(chalk__default.default.white(` const gateops = require('gateops-core');`));
507
+ console.log(chalk__default.default.white(` app.use(gateops.init());
508
+ `));
509
+ console.log(chalk__default.default.gray("2. Start your server and make some requests\n"));
510
+ console.log(chalk__default.default.gray("3. View your logs at:"));
511
+ console.log(chalk__default.default.blue(" https://gateops.sleeksoulsmedia.com\n"));
512
+ });
513
+ program.command("status").description("Check GateOps SDK status").action(async () => {
514
+ const gateopsDir = path2__namespace.join(process.cwd(), ".gateops");
515
+ const dbPath = path2__namespace.join(gateopsDir, "data.sqlite");
516
+ console.log(chalk__default.default.cyan.bold("\n\u{1F4CA} GateOps Status\n"));
517
+ if (!fs2__namespace.existsSync(gateopsDir)) {
518
+ console.log(chalk__default.default.yellow("\u26A0 GateOps is not initialized. Run `npx gateops-init` first.\n"));
519
+ return;
520
+ }
521
+ console.log(chalk__default.default.green("\u2713 GateOps is initialized"));
522
+ if (fs2__namespace.existsSync(dbPath)) {
523
+ const stats = fs2__namespace.statSync(dbPath);
524
+ console.log(chalk__default.default.green(`\u2713 Database: ${(stats.size / 1024).toFixed(2)} KB`));
525
+ }
526
+ const username = process.env.GATEOPS_USERNAME;
527
+ const apiKey = process.env.GATEOPS_API_KEY;
528
+ const enabled = process.env.GATEOPS_ENABLED !== "false";
529
+ if (username && apiKey) {
530
+ console.log(chalk__default.default.green(`\u2713 Credentials configured (${username})`));
531
+ } else {
532
+ console.log(chalk__default.default.yellow("\u26A0 Credentials not found in environment"));
533
+ }
534
+ console.log(
535
+ enabled ? chalk__default.default.green("\u2713 SDK is enabled") : chalk__default.default.red("\u2717 SDK is disabled (GATEOPS_ENABLED=false)")
536
+ );
537
+ if (username && apiKey) {
538
+ console.log(chalk__default.default.gray("\nChecking Panel connectivity..."));
539
+ const result = await verifyCredentials(username, apiKey);
540
+ console.log(
541
+ result.success ? chalk__default.default.green("\u2713 Connected to Panel") : chalk__default.default.red(`\u2717 Panel connection failed: ${result.message}`)
542
+ );
543
+ }
544
+ console.log("");
545
+ });
546
+ program.command("cleanup").description("Clean up old logs").option("--days <days>", "Delete logs older than N days", String(SDK_DEFAULTS.LOG_TTL_DAYS)).action(async (options) => {
547
+ console.log(chalk__default.default.cyan.bold("\n\u{1F9F9} GateOps Cleanup\n"));
548
+ const days = parseInt(options.days);
549
+ const { confirm } = await inquirer__default.default.prompt([{
550
+ type: "confirm",
551
+ name: "confirm",
552
+ message: `Delete logs older than ${days} days?`,
553
+ default: true
554
+ }]);
555
+ if (!confirm) {
556
+ console.log(chalk__default.default.yellow("Cleanup cancelled.\n"));
557
+ return;
558
+ }
559
+ try {
560
+ const { cleanupOldLogs: cleanupOldLogs2 } = await Promise.resolve().then(() => (init_db(), db_exports));
561
+ const deleted = cleanupOldLogs2(days);
562
+ console.log(chalk__default.default.green(`\u2713 Deleted ${deleted} old log entries
563
+ `));
564
+ } catch (error) {
565
+ console.log(chalk__default.default.red("\u2717 Cleanup failed:", error));
566
+ }
567
+ });
568
+ program.parse();
569
+ //# sourceMappingURL=gateops-init.js.map
570
+ //# sourceMappingURL=gateops-init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/config.ts","../../src/db/schema.ts","../../src/db/index.ts","../../package.json","../../src/sync.ts","../../src/bin/gateops-init.ts"],"names":["sqliteTable","integer","text","path","fs","Database","drizzle","sql","exports","axios","Command","chalk","path2","fs2","inquirer","cleanupOldLogs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqGO,SAAS,YAAY,QAAA,EAAgD;AACxE,EAAA,OAAO,CAAA,EAAG,cAAc,CAAA,EAAG,eAAA,CAAgB,QAAQ,CAAC,CAAA,CAAA;AACxD;AAvGA,IAQa,gBAQA,eAAA,EAoBA,YAAA;AApCb,IAAA,WAAA,GAAA,KAAA,CAAA;AAAA,EAAA,eAAA,GAAA;AAQO,IAAM,cAAA,GAAiB,OAAA,CAAQ,GAAA,CAAI,iBAAA,IAAqB,qCAAA;AAQxD,IAAM,eAAA,GAAkB;AAAA;AAAA,MAE3B,MAAA,EAAQ,iBAAA;AAAA;AAAA,MAGR,IAAA,EAAM,eAAA;AAAA;AAAA,MAGN,MAAA,EAAQ,iBAAA;AAAA;AAAA,MAGR,SAAA,EAAW,oBAAA;AAAA;AAAA,MAGX,SAAA,EAAW;AAAA,KACf;AAKO,IAAM,YAAA,GAAe;AAAA;AAAA,MAExB,eAAA,EAAiB,EAAA;AAAA;AAAA,MACjB,qBAAA,EAAuB,GAAA;AAAA;AAAA;AAAA,MAGvB,aAAA,EAAe,KAAA;AAAA;AAAA;AAAA,MAGf,YAAA,EAAc,EAAA;AAAA;AAAA;AAAA,MAGd,kBAAA,EAAoB,CAAA;AAAA,MACpB,gBAAA,EAAkB,GAAA;AAAA;AAAA;AAAA,MAGlB,eAAA,EAAiB,sBAAA;AAAA,MACjB,gBAAA,EAAkB,sBAAA;AAAA;AAAA,MAGlB,YAAA,EAAc;AAAA,KAClB;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACzDA,IAAA,cAAA,GAAA,EAAA;AAAA,QAAA,CAAA,cAAA,EAAA;AAAA,EAAA,MAAA,EAAA,MAAA,MAAA;AAAA,EAAA,SAAA,EAAA,MAAA,SAAA;AAAA,EAAA,WAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AAAA,IAOa,aAkCA,SAAA,EAuBA,MAAA;AAhEb,IAAA,WAAA,GAAA,KAAA,CAAA;AAAA,EAAA,kBAAA,GAAA;AAOO,IAAM,WAAA,GAAcA,uBAAY,sBAAA,EAAwB;AAAA,MAC3D,EAAA,EAAIC,mBAAQ,IAAI,CAAA,CAAE,WAAW,EAAE,aAAA,EAAe,MAAM,CAAA;AAAA;AAAA,MAGpD,QAAA,EAAUC,eAAA,CAAK,UAAU,CAAA,CAAE,OAAA,EAAQ;AAAA;AAAA,MAGnC,QAAA,EAAUA,eAAA,CAAK,UAAU,CAAA,CAAE,OAAA,EAAQ;AAAA,MACnC,MAAA,EAAQA,eAAA,CAAK,QAAQ,CAAA,CAAE,OAAA,EAAQ;AAAA,MAC/B,MAAA,EAAQD,kBAAA,CAAQ,QAAQ,CAAA,CAAE,OAAA,EAAQ;AAAA,MAClC,WAAA,EAAaA,kBAAA,CAAQ,aAAa,CAAA,CAAE,OAAA,EAAQ;AAAA;AAAA,MAG5C,WAAA,EAAaC,gBAAK,aAAa,CAAA;AAAA,MAC/B,WAAA,EAAaA,gBAAK,aAAa,CAAA;AAAA;AAAA,MAG/B,QAAA,EAAUA,gBAAK,UAAU,CAAA;AAAA,MACzB,QAAA,EAAUA,gBAAK,UAAU,CAAA;AAAA;AAAA,MAGzB,YAAA,EAAcA,gBAAK,cAAc,CAAA;AAAA,MACjC,UAAA,EAAYA,gBAAK,YAAY,CAAA;AAAA,MAC7B,UAAA,EAAYA,gBAAK,YAAY,CAAA;AAAA;AAAA,MAG7B,UAAA,EAAYD,mBAAQ,YAAA,EAAc,EAAE,MAAM,WAAA,EAAa,EAAE,OAAA;AAAQ,KACpE,CAAA;AAOM,IAAM,SAAA,GAAYD,uBAAY,mBAAA,EAAqB;AAAA,MACtD,EAAA,EAAIC,mBAAQ,IAAI,CAAA,CAAE,WAAW,EAAE,aAAA,EAAe,MAAM,CAAA;AAAA;AAAA,MAGpD,IAAA,EAAMC,eAAA,CAAK,MAAM,CAAA,CAAE,OAAA,EAAQ;AAAA,MAC3B,MAAA,EAAQA,eAAA,CAAK,QAAQ,CAAA,CAAE,OAAA,EAAQ;AAAA;AAAA;AAAA,MAI/B,eAAA,EAAiBA,gBAAK,iBAAiB,CAAA;AAAA;AAAA,MAGvC,gBAAA,EAAkBA,gBAAK,kBAAkB,CAAA;AAAA;AAAA,MAGzC,SAAA,EAAWD,mBAAQ,WAAA,EAAa,EAAE,MAAM,WAAA,EAAa,EAAE,OAAA;AAAQ,KAClE,CAAA;AAOM,IAAM,MAAA,GAASD,uBAAY,gBAAA,EAAkB;AAAA;AAAA,MAEhD,GAAA,EAAKE,eAAA,CAAK,KAAK,CAAA,CAAE,UAAA,EAAW;AAAA;AAAA,MAG5B,KAAA,EAAOA,eAAA,CAAK,OAAO,CAAA,CAAE,OAAA,EAAQ;AAAA;AAAA,MAG7B,YAAYD,kBAAA,CAAQ,YAAA,EAAc,EAAE,IAAA,EAAM,aAAa;AAAA,KAC1D,CAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACzED,IAAA,UAAA,GAAA,EAAA;AAAA,QAAA,CAAA,UAAA,EAAA;AAAA,EAAA,cAAA,EAAA,MAAA,cAAA;AAAA,EAAA,aAAA,EAAA,MAAA,aAAA;AAAA,EAAA,MAAA,EAAA,MAAA,MAAA;AAAA,EAAA,SAAA,EAAA,MAAA,SAAA;AAAA,EAAA,WAAA,EAAA,MAAA,WAAA;AAAA,EAAA,gBAAA,EAAA,MAAA,gBAAA;AAAA,EAAA,WAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AAcO,SAAS,YAAY,MAAA,EAAuD;AAC/E,EAAA,IAAI,EAAA,EAAI;AACJ,IAAA,OAAO,EAAA;AAAA,EACX;AAEA,EAAA,MAAM,YAAA,GAAe,MAAA,IAAU,OAAA,CAAQ,GAAA,CAAI,mBAAmB,YAAA,CAAa,eAAA;AAC3E,EAAA,MAAM,YAAA,GAAoBE,4BAAW,YAAY,CAAA,GAC3C,eACKA,gBAAA,CAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAI,EAAG,YAAY,CAAA;AAG3C,EAAA,MAAM,GAAA,GAAWA,yBAAQ,YAAY,CAAA;AACrC,EAAA,IAAI,CAAIC,cAAA,CAAA,UAAA,CAAW,GAAG,CAAA,EAAG;AACrB,IAAGA,cAAA,CAAA,SAAA,CAAU,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,EACzC;AAGA,EAAA,QAAA,GAAW,IAAIC,0BAAS,YAAY,CAAA;AAGpC,EAAA,QAAA,CAAS,OAAO,oBAAoB,CAAA;AAGpC,EAAA,EAAA,GAAKC,qBAAA,CAAQ,QAAA,EAAU,EAAE,MAAA,EAAA,cAAA,EAAQ,CAAA;AAEjC,EAAA,OAAO,EAAA;AACX;AAKO,SAAS,iBAAiB,QAAA,EAAuD;AACpF,EAAA,MAAM,QAAA,GAAW,YAAY,WAAA,EAAY;AAGzC,EAAA,QAAA,CAAS,GAAA,CAAIC,cAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAAA,CAiBd,CAAA;AAGC,EAAA,QAAA,CAAS,GAAA,CAAIA,cAAA;AAAA;AAAA;AAAA,EAAA,CAGd,CAAA;AAEC,EAAA,QAAA,CAAS,GAAA,CAAIA,cAAA;AAAA;AAAA;AAAA,EAAA,CAGd,CAAA;AAEC,EAAA,QAAA,CAAS,GAAA,CAAIA,cAAA;AAAA;AAAA;AAAA,EAAA,CAGd,CAAA;AAGC,EAAA,QAAA,CAAS,GAAA,CAAIA,cAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAAA,CAUd,CAAA;AAGC,EAAA,QAAA,CAAS,GAAA,CAAIA,cAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAAA,CAMd,CAAA;AACH;AAKO,SAAS,aAAA,GAAsB;AAClC,EAAA,IAAI,QAAA,EAAU;AACV,IAAA,QAAA,CAAS,KAAA,EAAM;AACf,IAAA,QAAA,GAAW,IAAA;AACX,IAAA,EAAA,GAAK,IAAA;AAAA,EACT;AACJ;AAKO,SAAS,cAAA,CAAe,OAAA,GAAkB,YAAA,CAAa,YAAA,EAAsB;AAChF,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,UAAA,uBAAiB,IAAA,EAAK;AAC5B,EAAA,UAAA,CAAW,OAAA,CAAQ,UAAA,CAAW,OAAA,EAAQ,GAAI,OAAO,CAAA;AAEjD,EAAA,MAAM,MAAA,GAAS,SAAS,GAAA,CAAIA,cAAA;AAAA;AAAA,uBAAA,EAEP,KAAK,KAAA,CAAM,UAAA,CAAW,OAAA,EAAQ,GAAI,GAAI,CAAC;AAAA,EAAA,CAC7D,CAAA;AAEC,EAAA,OAAO,MAAA,CAAO,OAAA;AAClB;AApIA,IAQI,EAAA,EACA,QAAA;AATJ,IAAA,OAAA,GAAA,KAAA,CAAA;AAAA,EAAA,iBAAA,GAAA;AAGA,IAAA,WAAA,EAAA;AACA,IAAA,WAAA,EAAA;AAmIA,IAAA,WAAA,EAAA;AA/HA,IAAI,EAAA,GAAkD,IAAA;AACtD,IAAI,QAAA,GAAqC,IAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACTzC,IAAA,eAAA,GAAA,UAAA,CAAA;AAAA,EAAA,cAAA,CAAAC,SAAA,EAAA,MAAA,EAAA;AAAA,IAAA,MAAA,CAAA,OAAA,GAAA;AAAA,MACE,IAAA,EAAQ,cAAA;AAAA,MACR,OAAA,EAAW,OAAA;AAAA,MACX,WAAA,EAAe,kGAAA;AAAA,MACf,IAAA,EAAQ,eAAA;AAAA,MACR,MAAA,EAAU,gBAAA;AAAA,MACV,KAAA,EAAS,iBAAA;AAAA,MACT,GAAA,EAAO;AAAA,QACL,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,KAAA,EAAS;AAAA,QACP;AAAA,OACF;AAAA,MACA,OAAA,EAAW;AAAA,QACT,KAAA,EAAS,MAAA;AAAA,QACT,GAAA,EAAO,cAAA;AAAA,QACP,IAAA,EAAQ,QAAA;AAAA,QACR,UAAA,EAAY,YAAA;AAAA,QACZ,IAAA,EAAQ,sBAAA;AAAA,QACR,MAAA,EAAU,sBAAA;AAAA,QACV,cAAA,EAAkB;AAAA,OACpB;AAAA,MACA,QAAA,EAAY;AAAA,QACV,KAAA;AAAA,QACA,eAAA;AAAA,QACA,YAAA;AAAA,QACA,SAAA;AAAA,QACA,YAAA;AAAA,QACA,SAAA;AAAA,QACA,WAAA;AAAA,QACA,eAAA;AAAA,QACA,SAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,MAAA,EAAU,SAAA;AAAA,MACV,OAAA,EAAW,KAAA;AAAA,MACX,UAAA,EAAc;AAAA,QACZ,IAAA,EAAQ,KAAA;AAAA,QACR,GAAA,EAAO;AAAA,OACT;AAAA,MACA,OAAA,EAAW;AAAA,QACT,IAAA,EAAQ;AAAA,OACV;AAAA,MACA,gBAAA,EAAoB;AAAA,QAClB,OAAA,EAAW;AAAA,OACb;AAAA,MACA,YAAA,EAAgB;AAAA,QACd,KAAA,EAAS,QAAA;AAAA,QACT,gBAAA,EAAkB,SAAA;AAAA,QAClB,KAAA,EAAS,QAAA;AAAA,QACT,SAAA,EAAa,SAAA;AAAA,QACb,aAAA,EAAe,SAAA;AAAA,QACf,QAAA,EAAY,QAAA;AAAA,QACZ,IAAA,EAAQ,QAAA;AAAA,QACR,GAAA,EAAO;AAAA,OACT;AAAA,MACA,eAAA,EAAmB;AAAA,QACjB,uBAAA,EAAyB,QAAA;AAAA,QACzB,gBAAA,EAAkB,UAAA;AAAA,QAClB,iBAAA,EAAmB,SAAA;AAAA,QACnB,aAAA,EAAe,UAAA;AAAA,QACf,aAAA,EAAe,QAAA;AAAA,QACf,aAAA,EAAe,SAAA;AAAA,QACf,MAAA,EAAU,SAAA;AAAA,QACV,OAAA,EAAW,SAAA;AAAA,QACX,QAAA,EAAY,QAAA;AAAA,QACZ,IAAA,EAAQ,QAAA;AAAA,QACR,UAAA,EAAc,QAAA;AAAA,QACd,MAAA,EAAU;AAAA;AACZ,KACF;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACrEA,WAAA,EAAA;AAYA,eAAsB,iBAAA,CAClB,UACA,MAAA,EACuB;AACvB,EAAA,IAAI;AACA,IAAA,MAAM,QAAA,GAAW,MAAMC,sBAAA,CAAM,IAAA;AAAA,MACzB,YAAY,QAAQ,CAAA;AAAA,MACpB,EAAE,QAAA,EAAS;AAAA,MACX;AAAA,QACI,OAAA,EAAS;AAAA,UACL,cAAA,EAAgB,kBAAA;AAAA,UAChB,oBAAA,EAAsB,QAAA;AAAA,UACtB,mBAAA,EAAqB;AAAA,SACzB;AAAA,QACA,OAAA,EAAS;AAAA;AACb,KACJ;AAEA,IAAA,OAAO,QAAA,CAAS,IAAA;AAAA,EACpB,SAAS,KAAA,EAAO;AACZ,IAAA,IAAIA,sBAAA,CAAM,YAAA,CAAa,KAAK,CAAA,EAAG;AAC3B,MAAA,IAAI,KAAA,CAAM,QAAA,EAAU,MAAA,KAAW,GAAA,EAAK;AAChC,QAAA,OAAO;AAAA,UACH,OAAA,EAAS,KAAA;AAAA,UACT,OAAA,EAAS;AAAA,SACb;AAAA,MACJ;AACA,MAAA,OAAO;AAAA,QACH,OAAA,EAAS,KAAA;AAAA,QACT,SAAS,KAAA,CAAM;AAAA,OACnB;AAAA,IACJ;AACA,IAAA,OAAO;AAAA,MACH,OAAA,EAAS,KAAA;AAAA,MACT,OAAA,EAAS;AAAA,KACb;AAAA,EACJ;AACJ;;;AC1CA,OAAA,EAAA;AACA,WAAA,EAAA;AAEA,IAAM,OAAA,GAAU,IAAIC,iBAAA,EAAQ;AAE5B,OAAA,CACK,IAAA,CAAK,cAAc,CAAA,CACnB,WAAA,CAAY,gDAAgD,CAAA,CAC5D,OAAA,CAAQ,kBAA8B,OAAO,CAAA;AAElD,OAAA,CACK,OAAA,CAAQ,MAAA,EAAQ,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA,CACnC,WAAA,CAAY,mBAAmB,CAAA,CAC/B,MAAA,CAAO,uBAAA,EAAyB,kBAAkB,CAAA,CAClD,MAAA,CAAO,iBAAA,EAAmB,iBAAiB,CAAA,CAC3C,MAAA,CAAO,eAAA,EAAiB,8BAA8B,CAAA,CACtD,MAAA,CAAO,SAAA,EAAW,kCAAkC,CAAA,CACpD,MAAA,CAAO,OAAO,OAAA,KAAY;AACvB,EAAA,OAAA,CAAQ,GAAA,CAAIC,sBAAA,CAAM,IAAA,CAAK,IAAA,CAAK,iCAA0B,CAAC,CAAA;AAGvD,EAAA,MAAM,UAAA,GAAkBC,gBAAA,CAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,UAAU,CAAA;AACtD,EAAA,MAAM,OAAA,GAAeA,gBAAA,CAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,MAAM,CAAA;AAE/C,EAAA,IAAOC,cAAA,CAAA,UAAA,CAAW,UAAU,CAAA,IAAK,CAAC,QAAQ,KAAA,EAAO;AAC7C,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAMC,yBAAA,CAAS,OAAO,CAAC;AAAA,MACvC,IAAA,EAAM,SAAA;AAAA,MACN,IAAA,EAAM,SAAA;AAAA,MACN,OAAA,EAAS,0DAAA;AAAA,MACT,OAAA,EAAS;AAAA,KACZ,CAAC,CAAA;AAEF,IAAA,IAAI,CAAC,OAAA,EAAS;AACV,MAAA,OAAA,CAAQ,GAAA,CAAIH,sBAAA,CAAM,MAAA,CAAO,kBAAkB,CAAC,CAAA;AAC5C,MAAA;AAAA,IACJ;AAAA,EACJ;AAGA,EAAA,IAAI,WAAW,OAAA,CAAQ,QAAA;AACvB,EAAA,IAAI,SAAS,OAAA,CAAQ,MAAA;AAGrB,EAAA,IAAOE,0BAAW,OAAO,CAAA,KAAM,CAAC,QAAA,IAAY,CAAC,MAAA,CAAA,EAAS;AAClD,IAAA,MAAM,UAAA,GAAgBA,cAAA,CAAA,YAAA,CAAa,OAAA,EAAS,OAAO,CAAA;AACnD,IAAA,MAAM,aAAA,GAAgB,UAAA,CAAW,KAAA,CAAM,uBAAuB,CAAA;AAC9D,IAAA,MAAM,WAAA,GAAc,UAAA,CAAW,KAAA,CAAM,sBAAsB,CAAA;AAE3D,IAAA,IAAI,iBAAiB,WAAA,EAAa;AAC9B,MAAA,MAAM,EAAE,WAAA,EAAY,GAAI,MAAMC,yBAAA,CAAS,OAAO,CAAC;AAAA,QAC3C,IAAA,EAAM,SAAA;AAAA,QACN,IAAA,EAAM,aAAA;AAAA,QACN,OAAA,EAAS,uDAAA;AAAA,QACT,OAAA,EAAS;AAAA,OACZ,CAAC,CAAA;AAEF,MAAA,IAAI,WAAA,EAAa;AACb,QAAA,QAAA,GAAW,aAAA,CAAc,CAAC,CAAA,CAAE,IAAA,EAAK;AACjC,QAAA,MAAA,GAAS,WAAA,CAAY,CAAC,CAAA,CAAE,IAAA,EAAK;AAAA,MACjC;AAAA,IACJ;AAAA,EACJ;AAGA,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,MAAA,EAAQ;AACtB,IAAA,OAAA,CAAQ,GAAA,CAAIH,sBAAA,CAAM,IAAA,CAAK,kEAAkE,CAAC,CAAA;AAE1F,IAAA,MAAM,OAAA,GAAU,MAAMG,yBAAA,CAAS,MAAA,CAAO;AAAA,MAClC;AAAA,QACI,IAAA,EAAM,OAAA;AAAA,QACN,IAAA,EAAM,UAAA;AAAA,QACN,OAAA,EAAS,8BAAA;AAAA,QACT,QAAA,EAAU,CAAC,KAAA,KAAU,KAAA,CAAM,SAAS,CAAA,IAAK;AAAA,OAC7C;AAAA,MACA;AAAA,QACI,IAAA,EAAM,UAAA;AAAA,QACN,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,qBAAA;AAAA,QACT,IAAA,EAAM,GAAA;AAAA,QACN,QAAA,EAAU,CAAC,KAAA,KAAU,KAAA,CAAM,SAAS,CAAA,IAAK;AAAA;AAC7C,KACH,CAAA;AAED,IAAA,QAAA,GAAW,OAAA,CAAQ,QAAA;AACnB,IAAA,MAAA,GAAS,OAAA,CAAQ,MAAA;AAAA,EACrB;AAGA,EAAA,IAAI,CAAC,QAAQ,UAAA,EAAY;AACrB,IAAA,OAAA,CAAQ,GAAA,CAAIH,sBAAA,CAAM,IAAA,CAAK,+CAA+C,CAAC,CAAA;AAEvE,IAAA,MAAM,YAAA,GAAe,MAAM,iBAAA,CAAkB,QAAA,EAAU,MAAM,CAAA;AAE7D,IAAA,IAAI,CAAC,aAAa,OAAA,EAAS;AACvB,MAAA,OAAA,CAAQ,GAAA,CAAIA,uBAAM,GAAA,CAAI;AAAA,4BAAA,EAA4B,YAAA,CAAa,OAAO,CAAA,CAAE,CAAC,CAAA;AACzE,MAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,MAAA,CAAO,4DAA4D,CAAC,CAAA;AACtF,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAClB;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,KAAA,CAAM,6BAAwB,CAAC,CAAA;AACjD,IAAA,IAAI,aAAa,WAAA,EAAa;AAC1B,MAAA,OAAA,CAAQ,IAAIA,sBAAA,CAAM,IAAA,CAAK,cAAc,YAAA,CAAa,WAAW,EAAE,CAAC,CAAA;AAAA,IACpE;AAAA,EACJ,CAAA,MAAO;AACH,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,MAAA,CAAO,yCAAoC,CAAC,CAAA;AAAA,EAClE;AAGA,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,yBAAyB,CAAC,CAAA;AAEjD,EAAA,IAAI,CAAIE,cAAA,CAAA,UAAA,CAAW,UAAU,CAAA,EAAG;AAC5B,IAAGA,cAAA,CAAA,SAAA,CAAU,UAAA,EAAY,EAAE,SAAA,EAAW,MAAM,CAAA;AAC5C,IAAA,OAAA,CAAQ,GAAA,CAAIF,sBAAA,CAAM,KAAA,CAAM,oCAA+B,CAAC,CAAA;AAAA,EAC5D;AAGA,EAAA,IAAI;AACA,IAAA,MAAM,MAAA,GAAcC,gBAAA,CAAA,IAAA,CAAK,UAAA,EAAY,aAAa,CAAA;AAClD,IAAA,OAAA,CAAQ,IAAI,eAAA,GAAkB,MAAA;AAC9B,IAAA,WAAA,CAAY,MAAM,CAAA;AAClB,IAAA,gBAAA,EAAiB;AACjB,IAAA,OAAA,CAAQ,GAAA,CAAID,sBAAA,CAAM,KAAA,CAAM,6BAAwB,CAAC,CAAA;AAAA,EACrD,SAAS,KAAA,EAAO;AACZ,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,GAAA,CAAI,uCAAA,EAAoC,KAAK,CAAC,CAAA;AAChE,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAClB;AAGA,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAMG,yBAAA,CAAS,OAAO,CAAC;AAAA,IACzC,IAAA,EAAM,SAAA;AAAA,IACN,IAAA,EAAM,WAAA;AAAA,IACN,OAAA,EAAS,uCAAA;AAAA,IACT,OAAA,EAAS;AAAA,GACZ,CAAC,CAAA;AAEF,EAAA,IAAI,SAAA,EAAW;AACX,IAAA,MAAM,QAAA,GAAW;AAAA,MACb,EAAA;AAAA,MACA,yBAAA;AAAA,MACA,oBAAoB,QAAQ,CAAA,CAAA;AAAA,MAC5B,mBAAmB,MAAM,CAAA,CAAA;AAAA,MACzB,sBAAA;AAAA,MACA;AAAA,KACJ,CAAE,KAAK,IAAI,CAAA;AAEX,IAAA,IAAOD,cAAA,CAAA,UAAA,CAAW,OAAO,CAAA,EAAG;AAExB,MAAA,IAAI,UAAA,GAAgBA,cAAA,CAAA,YAAA,CAAa,OAAA,EAAS,OAAO,CAAA;AAEjD,MAAA,IAAI,UAAA,CAAW,QAAA,CAAS,kBAAkB,CAAA,EAAG;AAEzC,QAAA,UAAA,GAAa,UAAA,CAAW,OAAA,CAAQ,qBAAA,EAAuB,CAAA,iBAAA,EAAoB,QAAQ,CAAA,CAAE,CAAA;AACrF,QAAA,UAAA,GAAa,UAAA,CAAW,OAAA,CAAQ,oBAAA,EAAsB,CAAA,gBAAA,EAAmB,MAAM,CAAA,CAAE,CAAA;AACjF,QAAGA,cAAA,CAAA,aAAA,CAAc,SAAS,UAAU,CAAA;AAAA,MACxC,CAAA,MAAO;AAEH,QAAGA,cAAA,CAAA,cAAA,CAAe,SAAS,QAAQ,CAAA;AAAA,MACvC;AAAA,IACJ,CAAA,MAAO;AACH,MAAGA,cAAA,CAAA,aAAA,CAAc,OAAA,EAAS,QAAA,CAAS,IAAA,KAAS,IAAI,CAAA;AAAA,IACpD;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAIF,sBAAA,CAAM,KAAA,CAAM,0BAAqB,CAAC,CAAA;AAAA,EAClD;AAGA,EAAA,MAAM,aAAA,GAAqBC,gBAAA,CAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,YAAY,CAAA;AAC3D,EAAA,IAAOC,cAAA,CAAA,UAAA,CAAW,aAAa,CAAA,EAAG;AAC9B,IAAA,MAAM,gBAAA,GAAsBA,cAAA,CAAA,YAAA,CAAa,aAAA,EAAe,OAAO,CAAA;AAC/D,IAAA,IAAI,CAAC,gBAAA,CAAiB,QAAA,CAAS,UAAU,CAAA,EAAG;AACxC,MAAGA,cAAA,CAAA,cAAA,CAAe,eAAe,0BAA0B,CAAA;AAC3D,MAAA,OAAA,CAAQ,GAAA,CAAIF,sBAAA,CAAM,KAAA,CAAM,qCAAgC,CAAC,CAAA;AAAA,IAC7D;AAAA,EACJ;AAGA,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,IAAA,CAAK,kDAA6C,CAAC,CAAA;AAE1E,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,KAAA,CAAM,eAAe,CAAC,CAAA;AACxC,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,8CAA8C,CAAC,CAAA;AACtE,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,KAAA,CAAM,CAAA,2CAAA,CAA6C,CAAC,CAAA;AACtE,EAAA,OAAA,CAAQ,GAAA,CAAIA,uBAAM,KAAA,CAAM,CAAA;AAAA,CAA+B,CAAC,CAAA;AACxD,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,+CAA+C,CAAC,CAAA;AACvE,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,uBAAuB,CAAC,CAAA;AAC/C,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,0CAA0C,CAAC,CAAA;AACtE,CAAC,CAAA;AAEL,OAAA,CACK,QAAQ,QAAQ,CAAA,CAChB,YAAY,0BAA0B,CAAA,CACtC,OAAO,YAAY;AAChB,EAAA,MAAM,UAAA,GAAkBC,gBAAA,CAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,UAAU,CAAA;AACtD,EAAA,MAAM,MAAA,GAAcA,gBAAA,CAAA,IAAA,CAAK,UAAA,EAAY,aAAa,CAAA;AAElD,EAAA,OAAA,CAAQ,GAAA,CAAID,sBAAA,CAAM,IAAA,CAAK,IAAA,CAAK,8BAAuB,CAAC,CAAA;AAGpD,EAAA,IAAI,CAAIE,cAAA,CAAA,UAAA,CAAW,UAAU,CAAA,EAAG;AAC5B,IAAA,OAAA,CAAQ,GAAA,CAAIF,sBAAA,CAAM,MAAA,CAAO,oEAA+D,CAAC,CAAA;AACzF,IAAA;AAAA,EACJ;AAEA,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,KAAA,CAAM,+BAA0B,CAAC,CAAA;AAGnD,EAAA,IAAOE,cAAA,CAAA,UAAA,CAAW,MAAM,CAAA,EAAG;AACvB,IAAA,MAAM,KAAA,GAAWA,wBAAS,MAAM,CAAA;AAChC,IAAA,OAAA,CAAQ,GAAA,CAAIF,sBAAA,CAAM,KAAA,CAAM,CAAA,iBAAA,EAAA,CAAgB,KAAA,CAAM,IAAA,GAAO,IAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,CAAK,CAAC,CAAA;AAAA,EAC/E;AAGA,EAAA,MAAM,QAAA,GAAW,QAAQ,GAAA,CAAI,gBAAA;AAC7B,EAAA,MAAM,MAAA,GAAS,QAAQ,GAAA,CAAI,eAAA;AAC3B,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,eAAA,KAAoB,OAAA;AAEhD,EAAA,IAAI,YAAY,MAAA,EAAQ;AACpB,IAAA,OAAA,CAAQ,IAAIA,sBAAA,CAAM,KAAA,CAAM,CAAA,+BAAA,EAA6B,QAAQ,GAAG,CAAC,CAAA;AAAA,EACrE,CAAA,MAAO;AACH,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,MAAA,CAAO,6CAAwC,CAAC,CAAA;AAAA,EACtE;AAEA,EAAA,OAAA,CAAQ,GAAA;AAAA,IAAI,UACNA,sBAAA,CAAM,KAAA,CAAM,uBAAkB,CAAA,GAC9BA,sBAAA,CAAM,IAAI,gDAA2C;AAAA,GAC3D;AAGA,EAAA,IAAI,YAAY,MAAA,EAAQ;AACpB,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,kCAAkC,CAAC,CAAA;AAC1D,IAAA,MAAM,MAAA,GAAS,MAAM,iBAAA,CAAkB,QAAA,EAAU,MAAM,CAAA;AACvD,IAAA,OAAA,CAAQ,GAAA;AAAA,MAAI,MAAA,CAAO,OAAA,GACbA,sBAAA,CAAM,KAAA,CAAM,2BAAsB,CAAA,GAClCA,sBAAA,CAAM,GAAA,CAAI,CAAA,gCAAA,EAA8B,MAAA,CAAO,OAAO,CAAA,CAAE;AAAA,KAC9D;AAAA,EACJ;AAEA,EAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAClB,CAAC,CAAA;AAEL,OAAA,CACK,QAAQ,SAAS,CAAA,CACjB,WAAA,CAAY,mBAAmB,EAC/B,MAAA,CAAO,eAAA,EAAiB,+BAAA,EAAiC,MAAA,CAAO,aAAa,YAAY,CAAC,CAAA,CAC1F,MAAA,CAAO,OAAO,OAAA,KAAY;AACvB,EAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,IAAA,CAAK,+BAAwB,CAAC,CAAA;AAErD,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,OAAA,CAAQ,IAAI,CAAA;AAClC,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAMG,yBAAA,CAAS,OAAO,CAAC;AAAA,IACvC,IAAA,EAAM,SAAA;AAAA,IACN,IAAA,EAAM,SAAA;AAAA,IACN,OAAA,EAAS,0BAA0B,IAAI,CAAA,MAAA,CAAA;AAAA,IACvC,OAAA,EAAS;AAAA,GACZ,CAAC,CAAA;AAEF,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA,OAAA,CAAQ,GAAA,CAAIH,sBAAA,CAAM,MAAA,CAAO,sBAAsB,CAAC,CAAA;AAChD,IAAA;AAAA,EACJ;AAEA,EAAA,IAAI;AACA,IAAA,MAAM,EAAE,cAAA,EAAAI,eAAAA,EAAe,GAAI,MAAM,OAAA,CAAA,OAAA,EAAA,CAAA,IAAA,CAAA,OAAA,OAAA,EAAA,EAAA,UAAA,CAAA,CAAA;AACjC,IAAA,MAAM,OAAA,GAAUA,gBAAe,IAAI,CAAA;AACnC,IAAA,OAAA,CAAQ,GAAA,CAAIJ,sBAAA,CAAM,KAAA,CAAM,CAAA,eAAA,EAAa,OAAO,CAAA;AAAA,CAAoB,CAAC,CAAA;AAAA,EACrE,SAAS,KAAA,EAAO;AACZ,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,GAAA,CAAI,wBAAA,EAAqB,KAAK,CAAC,CAAA;AAAA,EACrD;AACJ,CAAC,CAAA;AAEL,OAAA,CAAQ,KAAA,EAAM","file":"gateops-init.js","sourcesContent":["/**\n * GateOps SDK Configuration\n * \n * Panel API endpoints are centralized here for easy modification.\n * Change these values if the Panel API structure changes.\n */\n\n// Panel base URL - change this if hosting changes\nexport const PANEL_BASE_URL = process.env.GATEOPS_PANEL_URL || 'https://gateops.sleeksoulsmedia.com';\n\n/**\n * Panel API Endpoints\n * \n * Modify these paths if the Panel API structure changes.\n * All paths are relative to PANEL_BASE_URL.\n */\nexport const PANEL_ENDPOINTS = {\n // Verify API key during initialization\n VERIFY: '/api/sdk/verify',\n\n // Send batched logs to Panel\n LOGS: '/api/sdk/logs',\n\n // Fetch remote configuration (optional)\n CONFIG: '/api/sdk/config',\n\n // Send discovered endpoints/routes\n ENDPOINTS: '/api/sdk/endpoints',\n\n // Heartbeat/health check\n HEARTBEAT: '/api/sdk/heartbeat'\n} as const;\n\n/**\n * SDK Default Configuration\n */\nexport const SDK_DEFAULTS = {\n // Buffer settings\n BUFFER_MAX_SIZE: 50, // Flush when buffer reaches this size\n BUFFER_FLUSH_INTERVAL: 10000, // Flush every 10 seconds (ms)\n\n // Payload limits\n MAX_BODY_SIZE: 10240, // 10KB max for req/res bodies\n\n // Log retention\n LOG_TTL_DAYS: 15, // Auto-cleanup logs older than 15 days\n\n // Retry settings\n MAX_RETRY_ATTEMPTS: 3,\n RETRY_DELAY_BASE: 1000, // Base delay for exponential backoff (ms)\n\n // Database\n DEFAULT_DB_PATH: '.gateops/data.sqlite',\n BUFFER_FILE_PATH: '.gateops/buffer.json',\n\n // Route prefix for exposed endpoints\n ROUTE_PREFIX: '/.well-known/gateops'\n} as const;\n\n/**\n * Sensitive field patterns for sanitization\n */\nexport const SENSITIVE_PATTERNS = {\n // Field names to redact (case-insensitive)\n FIELD_NAMES: [\n 'password',\n 'passwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'api-key',\n 'authorization',\n 'auth',\n 'bearer',\n 'credential',\n 'private',\n 'ssn',\n 'credit_card',\n 'creditcard',\n 'card_number',\n 'cvv',\n 'pin'\n ],\n\n // Regex patterns for value-based detection\n VALUE_PATTERNS: {\n // Credit card (basic pattern)\n CREDIT_CARD: /\\b\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}\\b/g,\n // SSN pattern\n SSN: /\\b\\d{3}[-]?\\d{2}[-]?\\d{4}\\b/g\n },\n\n // Replacement text\n REDACTED: '[REDACTED]',\n MASKED_CARD: '****-****-****-****'\n} as const;\n\n/**\n * Get full Panel endpoint URL\n */\nexport function getPanelUrl(endpoint: keyof typeof PANEL_ENDPOINTS): string {\n return `${PANEL_BASE_URL}${PANEL_ENDPOINTS[endpoint]}`;\n}\n\nexport type PanelEndpointKey = keyof typeof PANEL_ENDPOINTS;\n","import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';\n\n/**\n * Traffic logs table - stores all captured API requests/responses\n * \n * TTL: 15 days (cleanup handled by SDK)\n */\nexport const trafficLogs = sqliteTable('gateops_traffic_logs', {\n id: integer('id').primaryKey({ autoIncrement: true }),\n\n // Unique identifier for request tracing\n trace_id: text('trace_id').notNull(),\n\n // Request info\n endpoint: text('endpoint').notNull(),\n method: text('method').notNull(),\n status: integer('status').notNull(),\n duration_ms: integer('duration_ms').notNull(),\n\n // Headers (JSON strings)\n req_headers: text('req_headers'),\n res_headers: text('res_headers'),\n\n // Bodies (JSON strings, sanitized, max 10KB each)\n req_body: text('req_body'),\n res_body: text('res_body'),\n\n // Additional context\n query_params: text('query_params'),\n ip_address: text('ip_address'),\n user_agent: text('user_agent'),\n\n // Timestamp (stored as Unix timestamp)\n created_at: integer('created_at', { mode: 'timestamp' }).notNull()\n});\n\n/**\n * Endpoints table - stores discovered routes for documentation\n * \n * Updated on each app startup + when new routes are hit\n */\nexport const endpoints = sqliteTable('gateops_endpoints', {\n id: integer('id').primaryKey({ autoIncrement: true }),\n\n // Route identification (unique constraint on path + method)\n path: text('path').notNull(),\n method: text('method').notNull(),\n\n // Inferred request/response schema (JSON string)\n // Deep inference captures nested structures\n detected_schema: text('detected_schema'),\n\n // List of middleware names (JSON array)\n middleware_names: text('middleware_names'),\n\n // Last time this endpoint was hit\n last_seen: integer('last_seen', { mode: 'timestamp' }).notNull()\n});\n\n/**\n * Config table - key/value store for SDK configuration\n * \n * Used for storing latency rules, custom settings, etc.\n */\nexport const config = sqliteTable('gateops_config', {\n // Unique key name\n key: text('key').primaryKey(),\n\n // Value as JSON string\n value: text('value').notNull(),\n\n // When this config was last updated\n updated_at: integer('updated_at', { mode: 'timestamp' })\n});\n\n// Export table types for Drizzle\nexport type TrafficLogInsert = typeof trafficLogs.$inferInsert;\nexport type TrafficLogSelect = typeof trafficLogs.$inferSelect;\n\nexport type EndpointInsert = typeof endpoints.$inferInsert;\nexport type EndpointSelect = typeof endpoints.$inferSelect;\n\nexport type ConfigInsert = typeof config.$inferInsert;\nexport type ConfigSelect = typeof config.$inferSelect;\n","import Database from 'better-sqlite3';\nimport { drizzle, BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';\nimport { sql } from 'drizzle-orm';\nimport * as schema from './schema';\nimport { SDK_DEFAULTS } from '../config';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nlet db: BetterSQLite3Database<typeof schema> | null = null;\nlet sqliteDb: Database.Database | null = null;\n\n/**\n * Get or create the database connection\n */\nexport function getDatabase(dbPath?: string): BetterSQLite3Database<typeof schema> {\n if (db) {\n return db;\n }\n\n const resolvedPath = dbPath || process.env.GATEOPS_DB_PATH || SDK_DEFAULTS.DEFAULT_DB_PATH;\n const absolutePath = path.isAbsolute(resolvedPath)\n ? resolvedPath\n : path.join(process.cwd(), resolvedPath);\n\n // Ensure directory exists\n const dir = path.dirname(absolutePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Create SQLite connection\n sqliteDb = new Database(absolutePath);\n\n // Enable WAL mode for better concurrent performance\n sqliteDb.pragma('journal_mode = WAL');\n\n // Create Drizzle instance\n db = drizzle(sqliteDb, { schema });\n\n return db;\n}\n\n/**\n * Initialize database schema (create tables if not exist)\n */\nexport function initializeSchema(database?: BetterSQLite3Database<typeof schema>): void {\n const targetDb = database || getDatabase();\n\n // Create traffic_logs table\n targetDb.run(sql`\n CREATE TABLE IF NOT EXISTS gateops_traffic_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n trace_id TEXT NOT NULL,\n endpoint TEXT NOT NULL,\n method TEXT NOT NULL,\n status INTEGER NOT NULL,\n duration_ms INTEGER NOT NULL,\n req_headers TEXT,\n res_headers TEXT,\n req_body TEXT,\n res_body TEXT,\n query_params TEXT,\n ip_address TEXT,\n user_agent TEXT,\n created_at INTEGER NOT NULL\n )\n `);\n\n // Create indexes for common queries\n targetDb.run(sql`\n CREATE INDEX IF NOT EXISTS idx_traffic_logs_created_at \n ON gateops_traffic_logs(created_at)\n `);\n\n targetDb.run(sql`\n CREATE INDEX IF NOT EXISTS idx_traffic_logs_endpoint \n ON gateops_traffic_logs(endpoint, method)\n `);\n\n targetDb.run(sql`\n CREATE INDEX IF NOT EXISTS idx_traffic_logs_status \n ON gateops_traffic_logs(status)\n `);\n\n // Create endpoints table\n targetDb.run(sql`\n CREATE TABLE IF NOT EXISTS gateops_endpoints (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT NOT NULL,\n method TEXT NOT NULL,\n detected_schema TEXT,\n middleware_names TEXT,\n last_seen INTEGER NOT NULL,\n UNIQUE(path, method)\n )\n `);\n\n // Create config table\n targetDb.run(sql`\n CREATE TABLE IF NOT EXISTS gateops_config (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n updated_at INTEGER\n )\n `);\n}\n\n/**\n * Close database connection\n */\nexport function closeDatabase(): void {\n if (sqliteDb) {\n sqliteDb.close();\n sqliteDb = null;\n db = null;\n }\n}\n\n/**\n * Clean up old logs based on TTL\n */\nexport function cleanupOldLogs(ttlDays: number = SDK_DEFAULTS.LOG_TTL_DAYS): number {\n const database = getDatabase();\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - ttlDays);\n\n const result = database.run(sql`\n DELETE FROM gateops_traffic_logs \n WHERE created_at < ${Math.floor(cutoffDate.getTime() / 1000)}\n `);\n\n return result.changes;\n}\n\n// Re-export schema\nexport * from './schema';\n","{\n \"name\": \"gateops-core\",\n \"version\": \"0.1.0\",\n \"description\": \"Lightweight API observability SDK for Express.js - Zero-config, privacy-first traffic monitoring\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"bin\": {\n \"gateops-init\": \"dist/bin/gateops-init.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\",\n \"lint\": \"eslint src --ext .ts\",\n \"format\": \"prettier --write src\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"keywords\": [\n \"api\",\n \"observability\",\n \"monitoring\",\n \"express\",\n \"middleware\",\n \"logging\",\n \"debugging\",\n \"documentation\",\n \"swagger\",\n \"openapi\"\n ],\n \"author\": \"GateOps\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/gateops/gateops-core\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"peerDependencies\": {\n \"express\": \"^4.18.0 || ^5.0.0\"\n },\n \"dependencies\": {\n \"axios\": \"^1.6.0\",\n \"better-sqlite3\": \"^11.0.0\",\n \"chalk\": \"^4.1.2\",\n \"commander\": \"^12.0.0\",\n \"drizzle-orm\": \"^0.29.0\",\n \"inquirer\": \"^8.2.6\",\n \"uuid\": \"^9.0.0\",\n \"zod\": \"^3.22.0\"\n },\n \"devDependencies\": {\n \"@types/better-sqlite3\": \"^7.6.8\",\n \"@types/express\": \"^4.17.21\",\n \"@types/inquirer\": \"^8.2.10\",\n \"@types/node\": \"^20.10.0\",\n \"@types/uuid\": \"^9.0.7\",\n \"drizzle-kit\": \"^0.20.0\",\n \"eslint\": \"^8.56.0\",\n \"express\": \"^4.18.2\",\n \"prettier\": \"^3.2.0\",\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.3.0\",\n \"vitest\": \"^1.2.0\"\n }\n}\n","import axios from 'axios';\nimport { getPanelUrl, SDK_DEFAULTS } from './config';\nimport { TrafficLog, EndpointInfo, VerifyResponse, LogSubmitResponse } from './types';\n\n/**\n * Panel Sync Module\n * \n * Handles communication with the GateOps Panel API.\n */\n\n/**\n * Verify credentials with the Panel\n */\nexport async function verifyCredentials(\n username: string,\n apiKey: string\n): Promise<VerifyResponse> {\n try {\n const response = await axios.post<VerifyResponse>(\n getPanelUrl('VERIFY'),\n { username },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'x-gateops-username': username,\n 'x-gateops-api-key': apiKey\n },\n timeout: 10000\n }\n );\n\n return response.data;\n } catch (error) {\n if (axios.isAxiosError(error)) {\n if (error.response?.status === 401) {\n return {\n success: false,\n message: 'Invalid credentials'\n };\n }\n return {\n success: false,\n message: error.message\n };\n }\n return {\n success: false,\n message: 'Connection failed'\n };\n }\n}\n\n/**\n * Send logs to the Panel\n */\nexport async function sendLogs(\n logs: TrafficLog[],\n username: string,\n apiKey: string,\n retryCount: number = 0\n): Promise<LogSubmitResponse> {\n try {\n const response = await axios.post<LogSubmitResponse>(\n getPanelUrl('LOGS'),\n {\n logs: logs.map(log => ({\n ...log,\n created_at: log.created_at instanceof Date\n ? log.created_at.toISOString()\n : log.created_at\n }))\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'x-gateops-username': username,\n 'x-gateops-api-key': apiKey\n },\n timeout: 15000\n }\n );\n\n return response.data;\n } catch (error) {\n // Retry with exponential backoff\n if (retryCount < SDK_DEFAULTS.MAX_RETRY_ATTEMPTS) {\n const delay = SDK_DEFAULTS.RETRY_DELAY_BASE * Math.pow(2, retryCount);\n await sleep(delay);\n return sendLogs(logs, username, apiKey, retryCount + 1);\n }\n\n if (axios.isAxiosError(error)) {\n return {\n success: false,\n received: 0,\n message: error.message\n };\n }\n\n return {\n success: false,\n received: 0,\n message: 'Failed to send logs'\n };\n }\n}\n\n/**\n * Send discovered endpoints to the Panel\n */\nexport async function sendEndpoints(\n routes: EndpointInfo[],\n username: string,\n apiKey: string\n): Promise<boolean> {\n try {\n await axios.post(\n getPanelUrl('ENDPOINTS'),\n {\n endpoints: routes.map(r => ({\n path: r.path,\n method: r.method,\n detected_schema: r.detected_schema,\n middleware_names: r.middleware_names,\n last_seen: r.last_seen instanceof Date\n ? r.last_seen.toISOString()\n : r.last_seen\n }))\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'x-gateops-username': username,\n 'x-gateops-api-key': apiKey\n },\n timeout: 10000\n }\n );\n\n return true;\n } catch (error) {\n console.warn('[GateOps] Failed to send endpoints to Panel:',\n axios.isAxiosError(error) ? error.message : error\n );\n return false;\n }\n}\n\n/**\n * Send heartbeat to Panel\n */\nexport async function sendHeartbeat(\n username: string,\n apiKey: string\n): Promise<boolean> {\n try {\n await axios.post(\n getPanelUrl('HEARTBEAT'),\n {\n timestamp: new Date().toISOString(),\n sdkVersion: require('../package.json').version\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'x-gateops-username': username,\n 'x-gateops-api-key': apiKey\n },\n timeout: 5000\n }\n );\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Sleep helper\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport inquirer from 'inquirer';\nimport chalk from 'chalk';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { verifyCredentials } from '../sync';\nimport { getDatabase, initializeSchema } from '../db';\nimport { SDK_DEFAULTS } from '../config';\n\nconst program = new Command();\n\nprogram\n .name('gateops-init')\n .description('Initialize GateOps SDK in your Express project')\n .version(require('../../package.json').version);\n\nprogram\n .command('init', { isDefault: true })\n .description('Setup GateOps SDK')\n .option('--username <username>', 'GateOps username')\n .option('--api-key <key>', 'GateOps API key')\n .option('--skip-verify', 'Skip credential verification')\n .option('--force', 'Overwrite existing configuration')\n .action(async (options) => {\n console.log(chalk.cyan.bold('\\n๐Ÿš€ GateOps SDK Setup\\n'));\n\n // Check if already initialized\n const gateopsDir = path.join(process.cwd(), '.gateops');\n const envPath = path.join(process.cwd(), '.env');\n\n if (fs.existsSync(gateopsDir) && !options.force) {\n const { proceed } = await inquirer.prompt([{\n type: 'confirm',\n name: 'proceed',\n message: 'GateOps appears to be already initialized. Reinitialize?',\n default: false\n }]);\n\n if (!proceed) {\n console.log(chalk.yellow('Setup cancelled.'));\n return;\n }\n }\n\n // Get credentials\n let username = options.username;\n let apiKey = options.apiKey;\n\n // Try to read from existing .env\n if (fs.existsSync(envPath) && (!username || !apiKey)) {\n const envContent = fs.readFileSync(envPath, 'utf-8');\n const usernameMatch = envContent.match(/GATEOPS_USERNAME=(.+)/);\n const apiKeyMatch = envContent.match(/GATEOPS_API_KEY=(.+)/);\n\n if (usernameMatch && apiKeyMatch) {\n const { useExisting } = await inquirer.prompt([{\n type: 'confirm',\n name: 'useExisting',\n message: 'Found existing GateOps credentials in .env. Use them?',\n default: true\n }]);\n\n if (useExisting) {\n username = usernameMatch[1].trim();\n apiKey = apiKeyMatch[1].trim();\n }\n }\n }\n\n // Prompt for credentials if not provided\n if (!username || !apiKey) {\n console.log(chalk.gray('Get your credentials from: https://gateops.sleeksoulsmedia.com\\n'));\n\n const answers = await inquirer.prompt([\n {\n type: 'input',\n name: 'username',\n message: 'Enter your GateOps Username:',\n validate: (input) => input.length > 0 || 'Username is required'\n },\n {\n type: 'password',\n name: 'apiKey',\n message: 'Enter your API Key:',\n mask: '*',\n validate: (input) => input.length > 0 || 'API Key is required'\n }\n ]);\n\n username = answers.username;\n apiKey = answers.apiKey;\n }\n\n // Verify credentials with Panel\n if (!options.skipVerify) {\n console.log(chalk.gray('\\nVerifying credentials with GateOps Panel...'));\n\n const verification = await verifyCredentials(username, apiKey);\n\n if (!verification.success) {\n console.log(chalk.red(`\\nโœ— Verification failed: ${verification.message}`));\n console.log(chalk.yellow('Use --skip-verify to skip verification (not recommended)\\n'));\n process.exit(1);\n }\n\n console.log(chalk.green('โœ“ Credentials verified'));\n if (verification.projectName) {\n console.log(chalk.gray(` Project: ${verification.projectName}`));\n }\n } else {\n console.log(chalk.yellow('โš  Skipping credential verification'));\n }\n\n // Create .gateops directory\n console.log(chalk.gray('\\nSetting up GateOps...'));\n\n if (!fs.existsSync(gateopsDir)) {\n fs.mkdirSync(gateopsDir, { recursive: true });\n console.log(chalk.green('โœ“ Created .gateops/ directory'));\n }\n\n // Initialize database\n try {\n const dbPath = path.join(gateopsDir, 'data.sqlite');\n process.env.GATEOPS_DB_PATH = dbPath;\n getDatabase(dbPath);\n initializeSchema();\n console.log(chalk.green('โœ“ Initialized database'));\n } catch (error) {\n console.log(chalk.red('โœ— Failed to initialize database:', error));\n process.exit(1);\n }\n\n // Update .env file\n const { updateEnv } = await inquirer.prompt([{\n type: 'confirm',\n name: 'updateEnv',\n message: 'Add GateOps credentials to .env file?',\n default: true\n }]);\n\n if (updateEnv) {\n const envLines = [\n '',\n '# GateOps Configuration',\n `GATEOPS_USERNAME=${username}`,\n `GATEOPS_API_KEY=${apiKey}`,\n 'GATEOPS_ENABLED=true',\n ''\n ].join('\\n');\n\n if (fs.existsSync(envPath)) {\n // Check if GateOps vars already exist\n let envContent = fs.readFileSync(envPath, 'utf-8');\n\n if (envContent.includes('GATEOPS_USERNAME')) {\n // Update existing\n envContent = envContent.replace(/GATEOPS_USERNAME=.+/, `GATEOPS_USERNAME=${username}`);\n envContent = envContent.replace(/GATEOPS_API_KEY=.+/, `GATEOPS_API_KEY=${apiKey}`);\n fs.writeFileSync(envPath, envContent);\n } else {\n // Append\n fs.appendFileSync(envPath, envLines);\n }\n } else {\n fs.writeFileSync(envPath, envLines.trim() + '\\n');\n }\n\n console.log(chalk.green('โœ“ Updated .env file'));\n }\n\n // Add .gateops to .gitignore\n const gitignorePath = path.join(process.cwd(), '.gitignore');\n if (fs.existsSync(gitignorePath)) {\n const gitignoreContent = fs.readFileSync(gitignorePath, 'utf-8');\n if (!gitignoreContent.includes('.gateops')) {\n fs.appendFileSync(gitignorePath, '\\n# GateOps\\n.gateops/\\n');\n console.log(chalk.green('โœ“ Added .gateops to .gitignore'));\n }\n }\n\n // Success message\n console.log(chalk.cyan.bold('\\nโœจ GateOps SDK initialized successfully!\\n'));\n\n console.log(chalk.white('Next steps:\\n'));\n console.log(chalk.gray('1. Add the middleware to your Express app:\\n'));\n console.log(chalk.white(` const gateops = require('gateops-core');`));\n console.log(chalk.white(` app.use(gateops.init());\\n`));\n console.log(chalk.gray('2. Start your server and make some requests\\n'));\n console.log(chalk.gray('3. View your logs at:'));\n console.log(chalk.blue(' https://gateops.sleeksoulsmedia.com\\n'));\n });\n\nprogram\n .command('status')\n .description('Check GateOps SDK status')\n .action(async () => {\n const gateopsDir = path.join(process.cwd(), '.gateops');\n const dbPath = path.join(gateopsDir, 'data.sqlite');\n\n console.log(chalk.cyan.bold('\\n๐Ÿ“Š GateOps Status\\n'));\n\n // Check initialization\n if (!fs.existsSync(gateopsDir)) {\n console.log(chalk.yellow('โš  GateOps is not initialized. Run `npx gateops-init` first.\\n'));\n return;\n }\n\n console.log(chalk.green('โœ“ GateOps is initialized'));\n\n // Check database\n if (fs.existsSync(dbPath)) {\n const stats = fs.statSync(dbPath);\n console.log(chalk.green(`โœ“ Database: ${(stats.size / 1024).toFixed(2)} KB`));\n }\n\n // Check env vars\n const username = process.env.GATEOPS_USERNAME;\n const apiKey = process.env.GATEOPS_API_KEY;\n const enabled = process.env.GATEOPS_ENABLED !== 'false';\n\n if (username && apiKey) {\n console.log(chalk.green(`โœ“ Credentials configured (${username})`));\n } else {\n console.log(chalk.yellow('โš  Credentials not found in environment'));\n }\n\n console.log(enabled\n ? chalk.green('โœ“ SDK is enabled')\n : chalk.red('โœ— SDK is disabled (GATEOPS_ENABLED=false)')\n );\n\n // Check Panel connectivity\n if (username && apiKey) {\n console.log(chalk.gray('\\nChecking Panel connectivity...'));\n const result = await verifyCredentials(username, apiKey);\n console.log(result.success\n ? chalk.green('โœ“ Connected to Panel')\n : chalk.red(`โœ— Panel connection failed: ${result.message}`)\n );\n }\n\n console.log('');\n });\n\nprogram\n .command('cleanup')\n .description('Clean up old logs')\n .option('--days <days>', 'Delete logs older than N days', String(SDK_DEFAULTS.LOG_TTL_DAYS))\n .action(async (options) => {\n console.log(chalk.cyan.bold('\\n๐Ÿงน GateOps Cleanup\\n'));\n\n const days = parseInt(options.days);\n const { confirm } = await inquirer.prompt([{\n type: 'confirm',\n name: 'confirm',\n message: `Delete logs older than ${days} days?`,\n default: true\n }]);\n\n if (!confirm) {\n console.log(chalk.yellow('Cleanup cancelled.\\n'));\n return;\n }\n\n try {\n const { cleanupOldLogs } = await import('../db');\n const deleted = cleanupOldLogs(days);\n console.log(chalk.green(`โœ“ Deleted ${deleted} old log entries\\n`));\n } catch (error) {\n console.log(chalk.red('โœ— Cleanup failed:', error));\n }\n });\n\nprogram.parse();\n"]}