@vipin733/nodescope 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,145 @@
1
+ import {
2
+ defaultEntryCounts
3
+ } from "./chunk-OF6NKXP5.js";
4
+
5
+ // src/storage/memory.ts
6
+ var MemoryStorage = class {
7
+ entries = /* @__PURE__ */ new Map();
8
+ entriesByBatch = /* @__PURE__ */ new Map();
9
+ entriesByType = /* @__PURE__ */ new Map();
10
+ maxEntries;
11
+ constructor(options = {}) {
12
+ this.maxEntries = options.maxEntries ?? 1e3;
13
+ }
14
+ async initialize() {
15
+ }
16
+ async save(entry) {
17
+ if (this.entries.size >= this.maxEntries) {
18
+ const toRemove = Math.floor(this.maxEntries * 0.1);
19
+ const iterator = this.entries.keys();
20
+ for (let i = 0; i < toRemove; i++) {
21
+ const oldestKey = iterator.next().value;
22
+ if (oldestKey) {
23
+ const oldEntry = this.entries.get(oldestKey);
24
+ if (oldEntry) {
25
+ this.removeFromIndexes(oldEntry);
26
+ }
27
+ this.entries.delete(oldestKey);
28
+ }
29
+ }
30
+ }
31
+ this.entries.set(entry.id, entry);
32
+ this.addToIndexes(entry);
33
+ }
34
+ async saveBatch(entries) {
35
+ for (const entry of entries) {
36
+ await this.save(entry);
37
+ }
38
+ }
39
+ async find(id) {
40
+ return this.entries.get(id) ?? null;
41
+ }
42
+ async list(options = {}) {
43
+ const { type, batchId, tags, search, before, after, limit = 50, offset = 0 } = options;
44
+ let results = [];
45
+ if (type) {
46
+ const typeIds = this.entriesByType.get(type);
47
+ if (typeIds) {
48
+ results = Array.from(typeIds).map((id) => this.entries.get(id)).filter((e) => e !== void 0);
49
+ }
50
+ } else if (batchId) {
51
+ const batchIds = this.entriesByBatch.get(batchId);
52
+ if (batchIds) {
53
+ results = Array.from(batchIds).map((id) => this.entries.get(id)).filter((e) => e !== void 0);
54
+ }
55
+ } else {
56
+ results = Array.from(this.entries.values());
57
+ }
58
+ if (tags && tags.length > 0) {
59
+ results = results.filter((e) => tags.some((t) => e.tags.includes(t)));
60
+ }
61
+ if (search) {
62
+ const searchLower = search.toLowerCase();
63
+ results = results.filter(
64
+ (e) => JSON.stringify(e.content).toLowerCase().includes(searchLower)
65
+ );
66
+ }
67
+ if (before) {
68
+ results = results.filter((e) => e.createdAt < before);
69
+ }
70
+ if (after) {
71
+ results = results.filter((e) => e.createdAt > after);
72
+ }
73
+ results.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
74
+ const total = results.length;
75
+ const paginatedResults = results.slice(offset, offset + limit);
76
+ return {
77
+ data: paginatedResults,
78
+ total,
79
+ limit,
80
+ offset,
81
+ hasMore: offset + limit < total
82
+ };
83
+ }
84
+ async findByBatch(batchId) {
85
+ const ids = this.entriesByBatch.get(batchId);
86
+ if (!ids) return [];
87
+ return Array.from(ids).map((id) => this.entries.get(id)).filter((e) => e !== void 0).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
88
+ }
89
+ async prune(beforeDate) {
90
+ let pruned = 0;
91
+ for (const [id, entry] of this.entries) {
92
+ if (entry.createdAt < beforeDate) {
93
+ this.removeFromIndexes(entry);
94
+ this.entries.delete(id);
95
+ pruned++;
96
+ }
97
+ }
98
+ return pruned;
99
+ }
100
+ async clear() {
101
+ this.entries.clear();
102
+ this.entriesByBatch.clear();
103
+ this.entriesByType.clear();
104
+ }
105
+ async stats() {
106
+ const entriesByType = defaultEntryCounts();
107
+ let oldestEntry;
108
+ let newestEntry;
109
+ for (const entry of this.entries.values()) {
110
+ entriesByType[entry.type]++;
111
+ if (!oldestEntry || entry.createdAt < oldestEntry) {
112
+ oldestEntry = entry.createdAt;
113
+ }
114
+ if (!newestEntry || entry.createdAt > newestEntry) {
115
+ newestEntry = entry.createdAt;
116
+ }
117
+ }
118
+ return {
119
+ totalEntries: this.entries.size,
120
+ entriesByType,
121
+ oldestEntry,
122
+ newestEntry
123
+ };
124
+ }
125
+ async close() {
126
+ }
127
+ addToIndexes(entry) {
128
+ if (!this.entriesByBatch.has(entry.batchId)) {
129
+ this.entriesByBatch.set(entry.batchId, /* @__PURE__ */ new Set());
130
+ }
131
+ this.entriesByBatch.get(entry.batchId).add(entry.id);
132
+ if (!this.entriesByType.has(entry.type)) {
133
+ this.entriesByType.set(entry.type, /* @__PURE__ */ new Set());
134
+ }
135
+ this.entriesByType.get(entry.type).add(entry.id);
136
+ }
137
+ removeFromIndexes(entry) {
138
+ this.entriesByBatch.get(entry.batchId)?.delete(entry.id);
139
+ this.entriesByType.get(entry.type)?.delete(entry.id);
140
+ }
141
+ };
142
+
143
+ export {
144
+ MemoryStorage
145
+ };
@@ -0,0 +1,163 @@
1
+ import {
2
+ defaultEntryCounts
3
+ } from "./chunk-OF6NKXP5.js";
4
+
5
+ // src/storage/sqlite.ts
6
+ var SQLiteStorage = class {
7
+ db;
8
+ dbPath;
9
+ constructor(dbPath) {
10
+ this.dbPath = dbPath;
11
+ }
12
+ async initialize() {
13
+ const Database = (await import("better-sqlite3")).default;
14
+ this.db = new Database(this.dbPath);
15
+ this.db.pragma("journal_mode = WAL");
16
+ this.db.exec(`
17
+ CREATE TABLE IF NOT EXISTS entries (
18
+ id TEXT PRIMARY KEY,
19
+ batch_id TEXT NOT NULL,
20
+ type TEXT NOT NULL,
21
+ content TEXT NOT NULL,
22
+ tags TEXT NOT NULL,
23
+ created_at TEXT NOT NULL,
24
+ duration INTEGER,
25
+ memory_usage INTEGER
26
+ );
27
+
28
+ CREATE INDEX IF NOT EXISTS idx_entries_batch_id ON entries(batch_id);
29
+ CREATE INDEX IF NOT EXISTS idx_entries_type ON entries(type);
30
+ CREATE INDEX IF NOT EXISTS idx_entries_created_at ON entries(created_at);
31
+ `);
32
+ }
33
+ async save(entry) {
34
+ const stmt = this.db.prepare(`
35
+ INSERT OR REPLACE INTO entries (id, batch_id, type, content, tags, created_at, duration, memory_usage)
36
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
37
+ `);
38
+ stmt.run(
39
+ entry.id,
40
+ entry.batchId,
41
+ entry.type,
42
+ JSON.stringify(entry.content),
43
+ JSON.stringify(entry.tags),
44
+ entry.createdAt.toISOString(),
45
+ entry.duration ?? null,
46
+ entry.memoryUsage ?? null
47
+ );
48
+ }
49
+ async saveBatch(entries) {
50
+ const stmt = this.db.prepare(`
51
+ INSERT OR REPLACE INTO entries (id, batch_id, type, content, tags, created_at, duration, memory_usage)
52
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
53
+ `);
54
+ const insertMany = this.db.transaction((entries2) => {
55
+ for (const entry of entries2) {
56
+ stmt.run(
57
+ entry.id,
58
+ entry.batchId,
59
+ entry.type,
60
+ JSON.stringify(entry.content),
61
+ JSON.stringify(entry.tags),
62
+ entry.createdAt.toISOString(),
63
+ entry.duration ?? null,
64
+ entry.memoryUsage ?? null
65
+ );
66
+ }
67
+ });
68
+ insertMany(entries);
69
+ }
70
+ async find(id) {
71
+ const row = this.db.prepare("SELECT * FROM entries WHERE id = ?").get(id);
72
+ if (!row) return null;
73
+ return this.rowToEntry(row);
74
+ }
75
+ async list(options = {}) {
76
+ const { type, batchId, tags, search, before, after, limit = 50, offset = 0 } = options;
77
+ let where = "1=1";
78
+ const params = [];
79
+ if (type) {
80
+ where += " AND type = ?";
81
+ params.push(type);
82
+ }
83
+ if (batchId) {
84
+ where += " AND batch_id = ?";
85
+ params.push(batchId);
86
+ }
87
+ if (before) {
88
+ where += " AND created_at < ?";
89
+ params.push(before.toISOString());
90
+ }
91
+ if (after) {
92
+ where += " AND created_at > ?";
93
+ params.push(after.toISOString());
94
+ }
95
+ if (search) {
96
+ where += " AND content LIKE ?";
97
+ params.push(`%${search}%`);
98
+ }
99
+ const countRow = this.db.prepare(`SELECT COUNT(*) as count FROM entries WHERE ${where}`).get(...params);
100
+ const total = countRow.count;
101
+ const rows = this.db.prepare(
102
+ `SELECT * FROM entries WHERE ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`
103
+ ).all(...params, limit, offset);
104
+ const data = rows.map((row) => this.rowToEntry(row));
105
+ let filteredData = data;
106
+ if (tags && tags.length > 0) {
107
+ filteredData = data.filter((e) => tags.some((t) => e.tags.includes(t)));
108
+ }
109
+ return {
110
+ data: filteredData,
111
+ total,
112
+ limit,
113
+ offset,
114
+ hasMore: offset + limit < total
115
+ };
116
+ }
117
+ async findByBatch(batchId) {
118
+ const rows = this.db.prepare("SELECT * FROM entries WHERE batch_id = ? ORDER BY created_at ASC").all(batchId);
119
+ return rows.map((row) => this.rowToEntry(row));
120
+ }
121
+ async prune(beforeDate) {
122
+ const result = this.db.prepare("DELETE FROM entries WHERE created_at < ?").run(beforeDate.toISOString());
123
+ return result.changes;
124
+ }
125
+ async clear() {
126
+ this.db.prepare("DELETE FROM entries").run();
127
+ }
128
+ async stats() {
129
+ const entriesByType = defaultEntryCounts();
130
+ const typeRows = this.db.prepare("SELECT type, COUNT(*) as count FROM entries GROUP BY type").all();
131
+ for (const row of typeRows) {
132
+ entriesByType[row.type] = row.count;
133
+ }
134
+ const totalRow = this.db.prepare("SELECT COUNT(*) as count FROM entries").get();
135
+ const oldestRow = this.db.prepare("SELECT MIN(created_at) as oldest FROM entries").get();
136
+ const newestRow = this.db.prepare("SELECT MAX(created_at) as newest FROM entries").get();
137
+ return {
138
+ totalEntries: totalRow.count,
139
+ entriesByType,
140
+ oldestEntry: oldestRow.oldest ? new Date(oldestRow.oldest) : void 0,
141
+ newestEntry: newestRow.newest ? new Date(newestRow.newest) : void 0
142
+ };
143
+ }
144
+ async close() {
145
+ this.db.close();
146
+ }
147
+ rowToEntry(row) {
148
+ return {
149
+ id: row.id,
150
+ batchId: row.batch_id,
151
+ type: row.type,
152
+ content: JSON.parse(row.content),
153
+ tags: JSON.parse(row.tags),
154
+ createdAt: new Date(row.created_at),
155
+ duration: row.duration ?? void 0,
156
+ memoryUsage: row.memory_usage ?? void 0
157
+ };
158
+ }
159
+ };
160
+
161
+ export {
162
+ SQLiteStorage
163
+ };
@@ -0,0 +1,44 @@
1
+ // src/storage/adapter.ts
2
+ async function createStorageAdapter(driver, options) {
3
+ switch (driver) {
4
+ case "memory":
5
+ const { MemoryStorage } = await import("./memory-5GF7O2HJ.js");
6
+ return new MemoryStorage();
7
+ case "sqlite":
8
+ const { SQLiteStorage } = await import("./sqlite-DMOIPBIO.js");
9
+ return new SQLiteStorage(options?.databaseUrl || "./nodescope.db");
10
+ case "postgresql":
11
+ const { PostgreSQLStorage } = await import("./postgresql-XD7N5SFI.js");
12
+ if (!options?.databaseUrl) {
13
+ throw new Error("PostgreSQL requires a databaseUrl");
14
+ }
15
+ return new PostgreSQLStorage(options.databaseUrl);
16
+ case "mysql":
17
+ const { MySQLStorage } = await import("./mysql-KNBA3N7P.js");
18
+ if (!options?.databaseUrl) {
19
+ throw new Error("MySQL requires a databaseUrl");
20
+ }
21
+ return new MySQLStorage(options.databaseUrl);
22
+ default:
23
+ throw new Error(`Unknown storage driver: ${driver}`);
24
+ }
25
+ }
26
+ function defaultEntryCounts() {
27
+ return {
28
+ request: 0,
29
+ query: 0,
30
+ cache: 0,
31
+ log: 0,
32
+ exception: 0,
33
+ http_client: 0,
34
+ event: 0,
35
+ job: 0,
36
+ schedule: 0,
37
+ dump: 0
38
+ };
39
+ }
40
+
41
+ export {
42
+ createStorageAdapter,
43
+ defaultEntryCounts
44
+ };
@@ -0,0 +1,195 @@
1
+ import {
2
+ defaultEntryCounts
3
+ } from "./chunk-OF6NKXP5.js";
4
+
5
+ // src/storage/mysql.ts
6
+ var MySQLStorage = class {
7
+ pool;
8
+ connectionString;
9
+ constructor(connectionString) {
10
+ this.connectionString = connectionString;
11
+ }
12
+ async initialize() {
13
+ const mysql = await import("mysql2/promise");
14
+ this.pool = mysql.createPool(this.connectionString);
15
+ await this.pool.execute(`
16
+ CREATE TABLE IF NOT EXISTS nodescope_entries (
17
+ id VARCHAR(36) PRIMARY KEY,
18
+ batch_id VARCHAR(36) NOT NULL,
19
+ type VARCHAR(50) NOT NULL,
20
+ content JSON NOT NULL,
21
+ tags JSON NOT NULL,
22
+ created_at DATETIME(3) NOT NULL,
23
+ duration INT,
24
+ memory_usage INT,
25
+ INDEX idx_batch_id (batch_id),
26
+ INDEX idx_type (type),
27
+ INDEX idx_created_at (created_at)
28
+ )
29
+ `);
30
+ }
31
+ async save(entry) {
32
+ await this.pool.execute(
33
+ `INSERT INTO nodescope_entries (id, batch_id, type, content, tags, created_at, duration, memory_usage)
34
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
35
+ ON DUPLICATE KEY UPDATE
36
+ content = VALUES(content),
37
+ tags = VALUES(tags),
38
+ duration = VALUES(duration),
39
+ memory_usage = VALUES(memory_usage)`,
40
+ [
41
+ entry.id,
42
+ entry.batchId,
43
+ entry.type,
44
+ JSON.stringify(entry.content),
45
+ JSON.stringify(entry.tags),
46
+ entry.createdAt,
47
+ entry.duration ?? null,
48
+ entry.memoryUsage ?? null
49
+ ]
50
+ );
51
+ }
52
+ async saveBatch(entries) {
53
+ const connection = await this.pool.getConnection();
54
+ try {
55
+ await connection.beginTransaction();
56
+ for (const entry of entries) {
57
+ await connection.execute(
58
+ `INSERT INTO nodescope_entries (id, batch_id, type, content, tags, created_at, duration, memory_usage)
59
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
60
+ ON DUPLICATE KEY UPDATE
61
+ content = VALUES(content),
62
+ tags = VALUES(tags),
63
+ duration = VALUES(duration),
64
+ memory_usage = VALUES(memory_usage)`,
65
+ [
66
+ entry.id,
67
+ entry.batchId,
68
+ entry.type,
69
+ JSON.stringify(entry.content),
70
+ JSON.stringify(entry.tags),
71
+ entry.createdAt,
72
+ entry.duration ?? null,
73
+ entry.memoryUsage ?? null
74
+ ]
75
+ );
76
+ }
77
+ await connection.commit();
78
+ } catch (error) {
79
+ await connection.rollback();
80
+ throw error;
81
+ } finally {
82
+ connection.release();
83
+ }
84
+ }
85
+ async find(id) {
86
+ const [rows] = await this.pool.execute(
87
+ "SELECT * FROM nodescope_entries WHERE id = ?",
88
+ [id]
89
+ );
90
+ if (rows.length === 0) return null;
91
+ return this.rowToEntry(rows[0]);
92
+ }
93
+ async list(options = {}) {
94
+ const { type, batchId, tags, search, before, after, limit = 50, offset = 0 } = options;
95
+ let where = "1=1";
96
+ const params = [];
97
+ if (type) {
98
+ where += " AND type = ?";
99
+ params.push(type);
100
+ }
101
+ if (batchId) {
102
+ where += " AND batch_id = ?";
103
+ params.push(batchId);
104
+ }
105
+ if (before) {
106
+ where += " AND created_at < ?";
107
+ params.push(before);
108
+ }
109
+ if (after) {
110
+ where += " AND created_at > ?";
111
+ params.push(after);
112
+ }
113
+ if (search) {
114
+ where += ' AND JSON_SEARCH(content, "one", ?) IS NOT NULL';
115
+ params.push(`%${search}%`);
116
+ }
117
+ const [countRows] = await this.pool.execute(
118
+ `SELECT COUNT(*) as count FROM nodescope_entries WHERE ${where}`,
119
+ params
120
+ );
121
+ const total = countRows[0].count;
122
+ const [dataRows] = await this.pool.execute(
123
+ `SELECT * FROM nodescope_entries WHERE ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`,
124
+ [...params, limit, offset]
125
+ );
126
+ let data = dataRows.map((row) => this.rowToEntry(row));
127
+ if (tags && tags.length > 0) {
128
+ data = data.filter((e) => tags.some((t) => e.tags.includes(t)));
129
+ }
130
+ return {
131
+ data,
132
+ total,
133
+ limit,
134
+ offset,
135
+ hasMore: offset + limit < total
136
+ };
137
+ }
138
+ async findByBatch(batchId) {
139
+ const [rows] = await this.pool.execute(
140
+ "SELECT * FROM nodescope_entries WHERE batch_id = ? ORDER BY created_at ASC",
141
+ [batchId]
142
+ );
143
+ return rows.map((row) => this.rowToEntry(row));
144
+ }
145
+ async prune(beforeDate) {
146
+ const [result] = await this.pool.execute(
147
+ "DELETE FROM nodescope_entries WHERE created_at < ?",
148
+ [beforeDate]
149
+ );
150
+ return result.affectedRows;
151
+ }
152
+ async clear() {
153
+ await this.pool.execute("DELETE FROM nodescope_entries");
154
+ }
155
+ async stats() {
156
+ const entriesByType = defaultEntryCounts();
157
+ const [typeRows] = await this.pool.execute(
158
+ "SELECT type, COUNT(*) as count FROM nodescope_entries GROUP BY type"
159
+ );
160
+ for (const row of typeRows) {
161
+ entriesByType[row.type] = row.count;
162
+ }
163
+ const [totalRows] = await this.pool.execute(
164
+ "SELECT COUNT(*) as count FROM nodescope_entries"
165
+ );
166
+ const [rangeRows] = await this.pool.execute(
167
+ "SELECT MIN(created_at) as oldest, MAX(created_at) as newest FROM nodescope_entries"
168
+ );
169
+ return {
170
+ totalEntries: totalRows[0].count,
171
+ entriesByType,
172
+ oldestEntry: rangeRows[0].oldest ? new Date(rangeRows[0].oldest) : void 0,
173
+ newestEntry: rangeRows[0].newest ? new Date(rangeRows[0].newest) : void 0
174
+ };
175
+ }
176
+ async close() {
177
+ await this.pool.end();
178
+ }
179
+ rowToEntry(row) {
180
+ return {
181
+ id: row.id,
182
+ batchId: row.batch_id,
183
+ type: row.type,
184
+ content: typeof row.content === "string" ? JSON.parse(row.content) : row.content,
185
+ tags: typeof row.tags === "string" ? JSON.parse(row.tags) : row.tags,
186
+ createdAt: new Date(row.created_at),
187
+ duration: row.duration ?? void 0,
188
+ memoryUsage: row.memory_usage ?? void 0
189
+ };
190
+ }
191
+ };
192
+
193
+ export {
194
+ MySQLStorage
195
+ };