@semics-tech/mongolite 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +54 -3
  2. package/dist/adapters/node-sqlite.d.ts +4 -0
  3. package/dist/adapters/node-sqlite.js +80 -35
  4. package/dist/adapters/node-sqlite.js.map +1 -1
  5. package/dist/bin/mongolite-debug.d.ts +6 -1
  6. package/dist/bin/mongolite-debug.js +6 -113
  7. package/dist/bin/mongolite-debug.js.map +1 -1
  8. package/dist/bin/mongolite.d.ts +13 -0
  9. package/dist/bin/mongolite.js +172 -0
  10. package/dist/bin/mongolite.js.map +1 -0
  11. package/dist/cjs/adapters/node-sqlite.js +84 -35
  12. package/dist/cjs/bin/mongolite-debug.js +6 -149
  13. package/dist/cjs/bin/mongolite.js +207 -0
  14. package/dist/cjs/cli/discover.js +156 -0
  15. package/dist/cjs/cli/explorer.js +929 -0
  16. package/dist/cjs/cli/filter-builder.js +276 -0
  17. package/dist/cjs/cli/format.js +161 -0
  18. package/dist/cjs/cli/schema.js +211 -0
  19. package/dist/cjs/cli/ui.js +431 -0
  20. package/dist/cjs/collection.js +53 -14
  21. package/dist/cjs/cursors/findCursor.js +108 -19
  22. package/dist/cjs/db.js +87 -40
  23. package/dist/cjs/utils/connection-registry.js +122 -0
  24. package/dist/cli/discover.d.ts +40 -0
  25. package/dist/cli/discover.js +146 -0
  26. package/dist/cli/discover.js.map +1 -0
  27. package/dist/cli/explorer.d.ts +59 -0
  28. package/dist/cli/explorer.js +923 -0
  29. package/dist/cli/explorer.js.map +1 -0
  30. package/dist/cli/filter-builder.d.ts +52 -0
  31. package/dist/cli/filter-builder.js +268 -0
  32. package/dist/cli/filter-builder.js.map +1 -0
  33. package/dist/cli/format.d.ts +29 -0
  34. package/dist/cli/format.js +153 -0
  35. package/dist/cli/format.js.map +1 -0
  36. package/dist/cli/schema.d.ts +58 -0
  37. package/dist/cli/schema.js +205 -0
  38. package/dist/cli/schema.js.map +1 -0
  39. package/dist/cli/ui.d.ts +71 -0
  40. package/dist/cli/ui.js +379 -0
  41. package/dist/cli/ui.js.map +1 -0
  42. package/dist/collection.d.ts +25 -0
  43. package/dist/collection.js +53 -14
  44. package/dist/collection.js.map +1 -1
  45. package/dist/cursors/findCursor.d.ts +70 -0
  46. package/dist/cursors/findCursor.js +108 -19
  47. package/dist/cursors/findCursor.js.map +1 -1
  48. package/dist/db.d.ts +23 -0
  49. package/dist/db.js +85 -39
  50. package/dist/db.js.map +1 -1
  51. package/dist/utils/connection-registry.d.ts +74 -0
  52. package/dist/utils/connection-registry.js +117 -0
  53. package/dist/utils/connection-registry.js.map +1 -0
  54. package/package.json +2 -1
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Finding things for the user so they do not have to type paths or remember
3
+ * collection names: SQLite files on disk, and MongoLite-shaped tables inside
4
+ * a database.
5
+ */
6
+ import { readdirSync, statSync, existsSync } from 'node:fs';
7
+ import path from 'node:path';
8
+ const DB_EXTENSIONS = ['.db', '.sqlite', '.sqlite3', '.db3'];
9
+ const SKIP_DIRS = new Set([
10
+ 'node_modules',
11
+ '.git',
12
+ 'dist',
13
+ 'build',
14
+ 'coverage',
15
+ '.next',
16
+ '.cache',
17
+ 'vendor',
18
+ '.venv',
19
+ 'venv',
20
+ '__pycache__',
21
+ ]);
22
+ /**
23
+ * Walk `root` looking for SQLite-looking files, skipping the usual noisy
24
+ * directories. Results are newest-first, since the file you just wrote is
25
+ * almost always the one you want.
26
+ */
27
+ export function findDatabaseFiles(root = process.cwd(), options = {}) {
28
+ const maxDepth = options.depth ?? 2;
29
+ const limit = options.limit ?? 50;
30
+ const found = [];
31
+ const walk = (dir, depth) => {
32
+ if (found.length >= limit || depth > maxDepth)
33
+ return;
34
+ let entries;
35
+ try {
36
+ entries = readdirSync(dir, { withFileTypes: true });
37
+ }
38
+ catch {
39
+ return; // Unreadable directory - nothing useful to say about it.
40
+ }
41
+ for (const entry of entries) {
42
+ if (found.length >= limit)
43
+ return;
44
+ const full = path.join(dir, entry.name);
45
+ if (entry.isDirectory()) {
46
+ if (SKIP_DIRS.has(entry.name) || entry.name.startsWith('.'))
47
+ continue;
48
+ walk(full, depth + 1);
49
+ continue;
50
+ }
51
+ if (!entry.isFile())
52
+ continue;
53
+ if (!DB_EXTENSIONS.includes(path.extname(entry.name).toLowerCase()))
54
+ continue;
55
+ // WAL/SHM siblings are not databases you can open directly.
56
+ if (/-(wal|shm)$/.test(entry.name))
57
+ continue;
58
+ try {
59
+ const stats = statSync(full);
60
+ found.push({
61
+ path: full,
62
+ relativePath: path.relative(root, full) || entry.name,
63
+ sizeBytes: stats.size,
64
+ modified: stats.mtime,
65
+ });
66
+ }
67
+ catch {
68
+ // File vanished between readdir and stat - ignore.
69
+ }
70
+ }
71
+ };
72
+ walk(root, 0);
73
+ found.sort((a, b) => b.modified.getTime() - a.modified.getTime());
74
+ return found;
75
+ }
76
+ export function formatBytes(bytes) {
77
+ if (bytes < 1024)
78
+ return `${bytes} B`;
79
+ const units = ['KB', 'MB', 'GB', 'TB'];
80
+ let value = bytes / 1024;
81
+ let unit = 0;
82
+ while (value >= 1024 && unit < units.length - 1) {
83
+ value /= 1024;
84
+ unit += 1;
85
+ }
86
+ return `${value >= 10 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`;
87
+ }
88
+ export function formatRelativeTime(date, now = new Date()) {
89
+ const seconds = Math.max(0, Math.round((now.getTime() - date.getTime()) / 1000));
90
+ if (seconds < 60)
91
+ return 'just now';
92
+ const minutes = Math.round(seconds / 60);
93
+ if (minutes < 60)
94
+ return `${minutes}m ago`;
95
+ const hours = Math.round(minutes / 60);
96
+ if (hours < 24)
97
+ return `${hours}h ago`;
98
+ const days = Math.round(hours / 24);
99
+ if (days < 30)
100
+ return `${days}d ago`;
101
+ return date.toISOString().slice(0, 10);
102
+ }
103
+ /**
104
+ * List the tables in the database, flagging which ones look like MongoLite
105
+ * collections (an `_id` column plus a `data` column). Foreign tables are still
106
+ * reported so a user pointed at the wrong file gets a useful message rather
107
+ * than an empty list.
108
+ */
109
+ export async function listCollectionInfo(db) {
110
+ const tables = await db.all(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`);
111
+ const infos = [];
112
+ for (const { name } of tables) {
113
+ let isMongoLite = false;
114
+ try {
115
+ const columns = await db.all(`PRAGMA table_info("${name}")`);
116
+ const columnNames = new Set(columns.map((column) => column.name));
117
+ isMongoLite = columnNames.has('_id') && columnNames.has('data');
118
+ }
119
+ catch {
120
+ isMongoLite = false;
121
+ }
122
+ let count = 0;
123
+ try {
124
+ const row = await db.get(`SELECT COUNT(*) as count FROM "${name}"`);
125
+ count = row?.count ?? 0;
126
+ }
127
+ catch {
128
+ count = 0;
129
+ }
130
+ infos.push({ name, count, isMongoLite });
131
+ }
132
+ return infos;
133
+ }
134
+ /** Resolve a user-supplied database path, allowing `:memory:` and `~` shorthand. */
135
+ export function resolveDatabasePath(input) {
136
+ if (input === ':memory:')
137
+ return input;
138
+ const expanded = input.startsWith('~')
139
+ ? path.join(process.env.HOME ?? '', input.slice(1))
140
+ : input;
141
+ return path.resolve(expanded);
142
+ }
143
+ export function databaseExists(dbPath) {
144
+ return dbPath === ':memory:' || existsSync(dbPath);
145
+ }
146
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/cli/discover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ export interface ExplorerOptions {
2
+ database?: string;
3
+ collection?: string;
4
+ verbose?: boolean;
5
+ /** How many documents to sample when inferring the schema. Default 200. */
6
+ sampleSize?: number;
7
+ /** Rows shown per page of results. Default 20. */
8
+ pageSize?: number;
9
+ }
10
+ export declare class Explorer {
11
+ private readonly options;
12
+ private client;
13
+ private dbPath;
14
+ private collectionName;
15
+ private schema;
16
+ private lastSql;
17
+ private lastQuery;
18
+ /**
19
+ * `-d`/`-c` are a starting point, not a preference. Once they have been
20
+ * honoured they are forgotten, otherwise "open a different database" would
21
+ * take you straight back to the one on the command line.
22
+ */
23
+ private startingDatabaseUsed;
24
+ private startingCollectionUsed;
25
+ private readonly sampleSize;
26
+ private readonly pageSize;
27
+ constructor(options?: ExplorerOptions);
28
+ run(): Promise<void>;
29
+ private disconnect;
30
+ private chooseDatabase;
31
+ private connect;
32
+ private chooseCollection;
33
+ private useCollection;
34
+ private collectionMenu;
35
+ private guidedFind;
36
+ /** Collect conditions until the user is done. Returns null when cancelled. */
37
+ private buildConditions;
38
+ private buildOneCondition;
39
+ /**
40
+ * Ask for one value. When the field has few distinct values in the sample we
41
+ * offer them as a menu — no typing, no guessing at spelling or casing.
42
+ */
43
+ private askForValue;
44
+ private chooseSort;
45
+ private runQuery;
46
+ private chooseColumns;
47
+ private exportDocuments;
48
+ private countFlow;
49
+ private distinctFlow;
50
+ private groupFlow;
51
+ private pickField;
52
+ private showSchema;
53
+ private showIndexes;
54
+ private jsonFilterFlow;
55
+ private runRawSql;
56
+ private showLastSql;
57
+ private requireClient;
58
+ private collection;
59
+ }