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.
- package/dist/bin/gateops-init.js +570 -0
- package/dist/bin/gateops-init.js.map +1 -0
- package/dist/index.d.mts +725 -0
- package/dist/index.d.ts +725 -0
- package/dist/index.js +1227 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1176 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +71 -0
|
@@ -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":"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","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"]}
|