@onurege3467/zerohelper 10.2.5 → 10.2.6

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 (36) hide show
  1. package/README.md +432 -54
  2. package/dist/bin/commands/cache.d.ts +2 -0
  3. package/dist/bin/commands/cache.js +92 -0
  4. package/dist/bin/commands/db-backup.d.ts +3 -0
  5. package/dist/bin/commands/db-backup.js +118 -0
  6. package/dist/bin/commands/db.d.ts +2 -0
  7. package/dist/bin/commands/db.js +334 -0
  8. package/dist/bin/commands/import-export.d.ts +3 -0
  9. package/dist/bin/commands/import-export.js +123 -0
  10. package/dist/bin/commands/init.d.ts +2 -0
  11. package/dist/bin/commands/init.js +85 -0
  12. package/dist/bin/commands/migrate.d.ts +3 -0
  13. package/dist/bin/commands/migrate.js +167 -0
  14. package/dist/bin/commands/repl.d.ts +2 -0
  15. package/dist/bin/commands/repl.js +96 -0
  16. package/dist/bin/commands/seed.d.ts +2 -0
  17. package/dist/bin/commands/seed.js +76 -0
  18. package/dist/bin/commands/zpack.d.ts +2 -0
  19. package/dist/bin/commands/zpack.js +36 -0
  20. package/dist/bin/index.d.ts +2 -0
  21. package/dist/bin/index.js +28 -0
  22. package/dist/bin/types.d.ts +22 -0
  23. package/dist/bin/types.js +2 -0
  24. package/dist/bin/utils/config.d.ts +3 -0
  25. package/dist/bin/utils/config.js +78 -0
  26. package/dist/bin/utils/prompts.d.ts +3 -0
  27. package/dist/bin/utils/prompts.js +115 -0
  28. package/dist/bin/zero.js +789 -81
  29. package/dist/migrations/1767521950635_test_migration.d.ts +3 -0
  30. package/dist/migrations/1767521950635_test_migration.js +11 -0
  31. package/dist/migrations/1767522158826_create_users_table.d.ts +2 -0
  32. package/dist/migrations/1767522158826_create_users_table.js +11 -0
  33. package/dist/package.json +79 -0
  34. package/dist/zero.config.d.ts +10 -0
  35. package/dist/zero.config.js +13 -0
  36. package/package.json +2 -2
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.cacheCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const config_1 = require("../utils/config");
11
+ exports.cacheCommand = new commander_1.Command().name('cache');
12
+ exports.cacheCommand
13
+ .command('clear')
14
+ .description('Clear all cache')
15
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
16
+ .action(async (options) => {
17
+ const spinner = (0, ora_1.default)('Clearing cache...').start();
18
+ try {
19
+ const db = await (0, config_1.getDatabase)(options.config);
20
+ const metrics = db.getMetrics();
21
+ const beforeHits = metrics.cache?.hits || 0;
22
+ const beforeMisses = metrics.cache?.misses || 0;
23
+ await db.insert('_cache_clear', { timestamp: Date.now() });
24
+ await db.delete('_cache_clear', { timestamp: Date.now() });
25
+ const afterMetrics = db.getMetrics();
26
+ const afterHits = afterMetrics.cache?.hits || 0;
27
+ const afterMisses = afterMetrics.cache?.misses || 0;
28
+ spinner.succeed(chalk_1.default.green('✅ Cache cleared'));
29
+ console.log(chalk_1.default.gray(` Previous hits: ${beforeHits}`));
30
+ console.log(chalk_1.default.gray(` Previous misses: ${beforeMisses}`));
31
+ await db.close();
32
+ }
33
+ catch (error) {
34
+ spinner.fail(chalk_1.default.red('❌ Cache clear failed'));
35
+ console.error(chalk_1.default.red(error.message));
36
+ process.exit(1);
37
+ }
38
+ });
39
+ exports.cacheCommand
40
+ .command('stats')
41
+ .description('Show detailed cache statistics')
42
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
43
+ .action(async (options) => {
44
+ try {
45
+ const db = await (0, config_1.getDatabase)(options.config);
46
+ const metrics = db.getMetrics();
47
+ console.log(chalk_1.default.bold('\n📊 Cache Statistics'));
48
+ console.log(chalk_1.default.gray('─'.repeat(50)));
49
+ if (!metrics.cache) {
50
+ console.log(chalk_1.default.yellow(' No cache statistics available'));
51
+ console.log(chalk_1.default.gray(' Cache may not be enabled for this adapter'));
52
+ }
53
+ else {
54
+ const hits = metrics.cache.hits || 0;
55
+ const misses = metrics.cache.misses || 0;
56
+ const total = hits + misses;
57
+ const hitRate = total > 0 ? (hits / total) * 100 : 0;
58
+ console.log(chalk_1.default.cyan(' Cache Hits:'), chalk_1.default.green(hits.toLocaleString()));
59
+ console.log(chalk_1.default.cyan(' Cache Misses:'), chalk_1.default.red(misses.toLocaleString()));
60
+ console.log(chalk_1.default.cyan(' Total Requests:'), chalk_1.default.white(total.toLocaleString()));
61
+ console.log(chalk_1.default.cyan(' Hit Rate:'), chalk_1.default.white(`${hitRate.toFixed(2)}%`));
62
+ let healthStatus = '❌';
63
+ let healthColor = chalk_1.default.red;
64
+ if (hitRate >= 90) {
65
+ healthStatus = '✅ Excellent';
66
+ healthColor = chalk_1.default.green;
67
+ }
68
+ else if (hitRate >= 70) {
69
+ healthStatus = '⚠️ Good';
70
+ healthColor = chalk_1.default.yellow;
71
+ }
72
+ else if (hitRate >= 50) {
73
+ healthStatus = '⚠️ Fair';
74
+ healthColor = chalk_1.default.yellow;
75
+ }
76
+ else {
77
+ healthStatus = '❌ Poor';
78
+ healthColor = chalk_1.default.red;
79
+ }
80
+ console.log(chalk_1.default.cyan(' Health:'), healthColor(healthStatus));
81
+ if (hitRate < 70) {
82
+ console.log(chalk_1.default.gray('\n 💡 Tip: Consider increasing cache TTL for better hit rate'));
83
+ }
84
+ }
85
+ console.log(chalk_1.default.gray('\n' + '─'.repeat(50)));
86
+ await db.close();
87
+ }
88
+ catch (error) {
89
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
90
+ process.exit(1);
91
+ }
92
+ });
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const dbBackupCommand: Command;
3
+ export declare const dbRestoreCommand: Command;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.dbRestoreCommand = exports.dbBackupCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const config_1 = require("../utils/config");
13
+ const prompts_1 = require("../utils/prompts");
14
+ exports.dbBackupCommand = new commander_1.Command().name('db');
15
+ exports.dbBackupCommand
16
+ .command('backup')
17
+ .description('Backup database to timestamped file')
18
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
19
+ .option('-o, --output <dir>', 'Output directory for backups', './backups')
20
+ .action(async (options) => {
21
+ const spinner = (0, ora_1.default)('Creating backup...').start();
22
+ try {
23
+ const db = await (0, config_1.getDatabase)(options.config);
24
+ const config = (0, config_1.loadConfig)(options.config);
25
+ const backupDir = path_1.default.resolve(process.cwd(), options.output);
26
+ if (!fs_1.default.existsSync(backupDir)) {
27
+ fs_1.default.mkdirSync(backupDir, { recursive: true });
28
+ }
29
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
30
+ const backupFile = path_1.default.join(backupDir, `backup_${timestamp}.zerohelper.json`);
31
+ let tables = [];
32
+ if (config.adapter === 'json' && config.config.path) {
33
+ const dbPath = path_1.default.resolve(process.cwd(), config.config.path);
34
+ if (fs_1.default.existsSync(dbPath)) {
35
+ const dbContent = JSON.parse(fs_1.default.readFileSync(dbPath, 'utf-8'));
36
+ tables = Object.keys(dbContent);
37
+ }
38
+ }
39
+ else if (config.adapter === 'sqlite' && config.config.path) {
40
+ tables = await db.tables?.() || [];
41
+ }
42
+ else if (config.adapter === 'zpack' && config.config.path) {
43
+ tables = await db.tables?.() || [];
44
+ }
45
+ else {
46
+ tables = ['users', 'products', 'orders', 'migrations', 'migration_test', 'test_backup'];
47
+ }
48
+ const backupData = {
49
+ version: '10.2.5',
50
+ timestamp: new Date().toISOString(),
51
+ config: config,
52
+ data: {}
53
+ };
54
+ for (const table of tables) {
55
+ try {
56
+ const records = await db.select(table);
57
+ if (records.length > 0) {
58
+ backupData.data[table] = records;
59
+ }
60
+ }
61
+ catch (err) {
62
+ // Table doesn't exist or can't be accessed
63
+ }
64
+ }
65
+ fs_1.default.writeFileSync(backupFile, JSON.stringify(backupData, null, 2));
66
+ const fileSize = fs_1.default.statSync(backupFile).size;
67
+ spinner.succeed(chalk_1.default.green(`✅ Backup created: ${backupFile}`));
68
+ console.log(chalk_1.default.gray(` Size: ${(0, config_1.formatBytes)(fileSize)}`));
69
+ console.log(chalk_1.default.gray(` Tables: ${Object.keys(backupData.data).join(', ') || 'none'}`));
70
+ await db.close();
71
+ }
72
+ catch (error) {
73
+ spinner.fail(chalk_1.default.red('❌ Backup failed'));
74
+ console.error(chalk_1.default.red(error.message));
75
+ process.exit(1);
76
+ }
77
+ });
78
+ exports.dbRestoreCommand = new commander_1.Command().name('db');
79
+ exports.dbRestoreCommand
80
+ .command('restore')
81
+ .description('Restore database from backup file')
82
+ .argument('<backup-file>', 'Path to backup file')
83
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
84
+ .action(async (backupFile, options) => {
85
+ if (!fs_1.default.existsSync(backupFile)) {
86
+ console.error(chalk_1.default.red(`Error: Backup file not found: ${backupFile}`));
87
+ process.exit(1);
88
+ }
89
+ const backupData = JSON.parse(fs_1.default.readFileSync(backupFile, 'utf-8'));
90
+ const confirmed = await (0, prompts_1.confirmAction)(chalk_1.default.yellow(`⚠️ This will restore data from backup. Are you sure?`));
91
+ if (!confirmed) {
92
+ console.log(chalk_1.default.yellow('Restore cancelled'));
93
+ return;
94
+ }
95
+ const spinner = (0, ora_1.default)('Restoring database...').start();
96
+ try {
97
+ const db = await (0, config_1.getDatabase)(options.config);
98
+ for (const [table, records] of Object.entries(backupData.data)) {
99
+ const rows = records;
100
+ if (Array.isArray(rows) && rows.length > 0) {
101
+ try {
102
+ await db.bulkInsert(table, rows);
103
+ spinner.text = `✅ ${table}: ${rows.length} records`;
104
+ }
105
+ catch (err) {
106
+ spinner.text = `⚠️ ${table}: failed`;
107
+ }
108
+ }
109
+ }
110
+ spinner.succeed(chalk_1.default.green(`✅ Database restored from ${backupFile}`));
111
+ await db.close();
112
+ }
113
+ catch (error) {
114
+ spinner.fail(chalk_1.default.red('❌ Restore failed'));
115
+ console.error(chalk_1.default.red(error.message));
116
+ process.exit(1);
117
+ }
118
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const dbCommand: Command;
@@ -0,0 +1,334 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.dbCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const index_1 = require("../../index");
13
+ const package_json_1 = require("../../package.json");
14
+ const config_1 = require("../utils/config");
15
+ const prompts_1 = require("../utils/prompts");
16
+ exports.dbCommand = new commander_1.Command().name('db');
17
+ exports.dbCommand
18
+ .command('test')
19
+ .description('Test database connection and show basic stats')
20
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
21
+ .action(async (options) => {
22
+ const spinner = (0, ora_1.default)('Testing database connection...').start();
23
+ try {
24
+ const db = await (0, config_1.getDatabase)(options.config);
25
+ spinner.succeed(chalk_1.default.green('✅ Database connection successful'));
26
+ console.log(chalk_1.default.bold('\n📊 Database Stats:'));
27
+ console.log(chalk_1.default.cyan(' Adapter:'), chalk_1.default.white(db.constructor.name));
28
+ console.log(chalk_1.default.cyan(' Status:'), chalk_1.default.green('Connected'));
29
+ try {
30
+ const metrics = db.getMetrics();
31
+ console.log(chalk_1.default.cyan(' Operations:'), chalk_1.default.white(metrics.database.count));
32
+ console.log(chalk_1.default.cyan(' Avg Latency:'), chalk_1.default.white(`${metrics.database.averageDuration.toFixed(2)}ms`));
33
+ }
34
+ catch (err) {
35
+ console.log(chalk_1.default.yellow(' Note: Metrics not available for this adapter'));
36
+ }
37
+ await db.close();
38
+ }
39
+ catch (error) {
40
+ spinner.fail(chalk_1.default.red('❌ Connection failed'));
41
+ console.error(chalk_1.default.red(error.message));
42
+ process.exit(1);
43
+ }
44
+ });
45
+ exports.dbCommand
46
+ .command('stats')
47
+ .description('Show detailed database performance metrics')
48
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
49
+ .action(async (options) => {
50
+ try {
51
+ const db = await (0, config_1.getDatabase)(options.config);
52
+ const metrics = db.getMetrics();
53
+ console.log(chalk_1.default.bold('\n📊 Database Performance Dashboard'));
54
+ console.log(chalk_1.default.gray('─'.repeat(50)));
55
+ console.log(chalk_1.default.bold('\n🔹 Database Operations:'));
56
+ if (metrics.database) {
57
+ const count = metrics.database.count ?? 0;
58
+ const totalDuration = metrics.database.totalDuration ?? 0;
59
+ const avgLatency = metrics.database.averageDuration ?? 0;
60
+ const minDuration = metrics.database.minDuration ?? 0;
61
+ const maxDuration = metrics.database.maxDuration ?? 0;
62
+ const formatNum = (n) => typeof n === 'number' ? n.toFixed(2) : n;
63
+ console.log(` Total Operations: ${chalk_1.default.cyan(count)}`);
64
+ console.log(` Total Duration: ${chalk_1.default.cyan(`${formatNum(totalDuration)} ms`)}`);
65
+ console.log(` Avg Latency: ${chalk_1.default.green(`${formatNum(avgLatency)} ms`)}`);
66
+ console.log(` Min Duration: ${chalk_1.default.yellow(`${formatNum(minDuration)} ms`)}`);
67
+ console.log(` Max Duration: ${chalk_1.default.yellow(`${formatNum(maxDuration)} ms`)}`);
68
+ }
69
+ else {
70
+ console.log(chalk_1.default.gray(' No metrics available for this adapter'));
71
+ }
72
+ if (metrics.cache) {
73
+ console.log(chalk_1.default.bold('\n🔹 Cache Performance:'));
74
+ console.log(` Total Requests: ${chalk_1.default.cyan((metrics.cache.hits || 0) + (metrics.cache.misses || 0))}`);
75
+ console.log(` Cache Hits: ${chalk_1.default.green(metrics.cache.hits || 0)}`);
76
+ console.log(` Cache Misses: ${chalk_1.default.red(metrics.cache.misses || 0)}`);
77
+ const hits = metrics.cache.hits || 0;
78
+ const misses = metrics.cache.misses || 0;
79
+ const total = hits + misses;
80
+ if (total > 0) {
81
+ const ratio = (hits / total) * 100;
82
+ console.log(` Hit Ratio: ${ratio.toFixed(1)}% ${ratio > 80 ? '✅' : ratio > 50 ? '⚠️' : '❌'}`);
83
+ }
84
+ }
85
+ console.log(chalk_1.default.gray('\n' + '─'.repeat(50)));
86
+ await db.close();
87
+ }
88
+ catch (error) {
89
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
90
+ process.exit(1);
91
+ }
92
+ });
93
+ exports.dbCommand
94
+ .command('seed')
95
+ .description('Seed table with mock data')
96
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
97
+ .option('-t, --table <name>', 'Table name')
98
+ .option('-n, --count <number>', 'Number of records', '10')
99
+ .action(async (options) => {
100
+ if (!options.table) {
101
+ console.error(chalk_1.default.red('Error: --table option is required'));
102
+ process.exit(1);
103
+ }
104
+ const spinner = (0, ora_1.default)(`Seeding ${options.table}...`).start();
105
+ try {
106
+ const db = await (0, config_1.getDatabase)(options.config);
107
+ const seeder = new index_1.database.DataSeeder(db);
108
+ const schema = {};
109
+ const fieldTypes = ['string', 'number', 'email', 'boolean', 'date'];
110
+ for (let i = 0; i < 3; i++) {
111
+ const fieldType = fieldTypes[Math.floor(Math.random() * fieldTypes.length)];
112
+ schema[`field_${i + 1}`] = { type: fieldType };
113
+ }
114
+ const count = await seeder.seed(options.table, parseInt(options.count), schema);
115
+ spinner.succeed(chalk_1.default.green(`✅ Seeded ${count} records into ${options.table}`));
116
+ await db.close();
117
+ }
118
+ catch (error) {
119
+ spinner.fail(chalk_1.default.red('❌ Seeding failed'));
120
+ console.error(chalk_1.default.red(error.message));
121
+ process.exit(1);
122
+ }
123
+ });
124
+ exports.dbCommand
125
+ .command('backup')
126
+ .description('Backup database to timestamped file')
127
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
128
+ .option('-o, --output <dir>', 'Output directory for backups', './backups')
129
+ .action(async (options) => {
130
+ const spinner = (0, ora_1.default)('Creating backup...').start();
131
+ try {
132
+ const db = await (0, config_1.getDatabase)(options.config);
133
+ const config = (0, config_1.loadConfig)(options.config);
134
+ const backupDir = path_1.default.resolve(process.cwd(), options.output);
135
+ if (!fs_1.default.existsSync(backupDir)) {
136
+ fs_1.default.mkdirSync(backupDir, { recursive: true });
137
+ }
138
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
139
+ const backupFile = path_1.default.join(backupDir, `backup_${timestamp}.zerohelper.json`);
140
+ let tables = [];
141
+ if (config.adapter === 'json' && config.config.path) {
142
+ const dbPath = path_1.default.resolve(process.cwd(), config.config.path);
143
+ if (fs_1.default.existsSync(dbPath)) {
144
+ const dbContent = JSON.parse(fs_1.default.readFileSync(dbPath, 'utf-8'));
145
+ tables = Object.keys(dbContent);
146
+ }
147
+ }
148
+ else if (config.adapter === 'sqlite' && config.config.path) {
149
+ tables = await db.tables?.() || [];
150
+ }
151
+ else if (config.adapter === 'zpack' && config.config.path) {
152
+ tables = await db.tables?.() || [];
153
+ }
154
+ else {
155
+ tables = ['users', 'products', 'orders', 'migrations', 'migration_test', 'test_backup'];
156
+ }
157
+ const backupData = {
158
+ version: package_json_1.version,
159
+ timestamp: new Date().toISOString(),
160
+ config: config,
161
+ data: {}
162
+ };
163
+ for (const table of tables) {
164
+ try {
165
+ const records = await db.select(table);
166
+ if (records.length > 0) {
167
+ backupData.data[table] = records;
168
+ }
169
+ }
170
+ catch (err) {
171
+ // Table doesn't exist or can't be accessed
172
+ }
173
+ }
174
+ fs_1.default.writeFileSync(backupFile, JSON.stringify(backupData, null, 2));
175
+ const fileSize = fs_1.default.statSync(backupFile).size;
176
+ spinner.succeed(chalk_1.default.green(`✅ Backup created: ${backupFile}`));
177
+ console.log(chalk_1.default.gray(` Size: ${(0, config_1.formatBytes)(fileSize)}`));
178
+ console.log(chalk_1.default.gray(` Tables: ${Object.keys(backupData.data).join(', ') || 'none'}`));
179
+ await db.close();
180
+ }
181
+ catch (error) {
182
+ spinner.fail(chalk_1.default.red('❌ Backup failed'));
183
+ console.error(chalk_1.default.red(error.message));
184
+ process.exit(1);
185
+ }
186
+ });
187
+ exports.dbCommand
188
+ .command('restore')
189
+ .description('Restore database from backup file')
190
+ .argument('<backup-file>', 'Path to backup file')
191
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
192
+ .action(async (backupFile, options) => {
193
+ if (!fs_1.default.existsSync(backupFile)) {
194
+ console.error(chalk_1.default.red(`Error: Backup file not found: ${backupFile}`));
195
+ process.exit(1);
196
+ }
197
+ const backupData = JSON.parse(fs_1.default.readFileSync(backupFile, 'utf-8'));
198
+ const confirmed = await (0, prompts_1.confirmAction)(chalk_1.default.yellow(`⚠️ This will restore data from backup. Are you sure?`));
199
+ if (!confirmed) {
200
+ console.log(chalk_1.default.yellow('Restore cancelled'));
201
+ return;
202
+ }
203
+ const spinner = (0, ora_1.default)('Restoring database...').start();
204
+ try {
205
+ const db = await (0, config_1.getDatabase)(options.config);
206
+ for (const [table, records] of Object.entries(backupData.data)) {
207
+ const rows = records;
208
+ if (Array.isArray(rows) && rows.length > 0) {
209
+ try {
210
+ await db.bulkInsert(table, rows);
211
+ spinner.text = `✅ ${table}: ${rows.length} records`;
212
+ }
213
+ catch (err) {
214
+ spinner.text = `⚠️ ${table}: failed`;
215
+ }
216
+ }
217
+ }
218
+ spinner.succeed(chalk_1.default.green(`✅ Database restored from ${backupFile}`));
219
+ await db.close();
220
+ }
221
+ catch (error) {
222
+ spinner.fail(chalk_1.default.red('❌ Restore failed'));
223
+ console.error(chalk_1.default.red(error.message));
224
+ process.exit(1);
225
+ }
226
+ });
227
+ exports.dbCommand
228
+ .command('export')
229
+ .description('Export table data to file')
230
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
231
+ .option('-t, --table <name>', 'Table name to export')
232
+ .option('-f, --format <format>', 'Output format (json|csv)', 'json')
233
+ .option('-o, --output <file>', 'Output file path')
234
+ .action(async (options) => {
235
+ if (!options.table) {
236
+ console.error(chalk_1.default.red('Error: --table option is required'));
237
+ process.exit(1);
238
+ }
239
+ const spinner = (0, ora_1.default)(`Exporting ${options.table}...`).start();
240
+ try {
241
+ const db = await (0, config_1.getDatabase)(options.config);
242
+ const records = await db.select(options.table);
243
+ if (records.length === 0) {
244
+ spinner.warn(chalk_1.default.yellow(`⚠️ No records found in ${options.table}`));
245
+ await db.close();
246
+ return;
247
+ }
248
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
249
+ const ext = options.format === 'csv' ? 'csv' : 'json';
250
+ const defaultFile = `${options.table}_export_${timestamp}.${ext}`;
251
+ const outputFile = options.output || path_1.default.join(process.cwd(), 'exports', defaultFile);
252
+ const outputDir = path_1.default.dirname(outputFile);
253
+ if (!fs_1.default.existsSync(outputDir)) {
254
+ fs_1.default.mkdirSync(outputDir, { recursive: true });
255
+ }
256
+ let content = '';
257
+ if (options.format === 'csv') {
258
+ const headers = Object.keys(records[0]);
259
+ const csvRows = [
260
+ headers.join(','),
261
+ ...records.map((row) => headers.map(h => {
262
+ const val = row[h];
263
+ return typeof val === 'string' && val.includes(',') ? `"${val}"` : val;
264
+ }).join(','))
265
+ ];
266
+ content = csvRows.join('\n');
267
+ }
268
+ else {
269
+ content = JSON.stringify(records, null, 2);
270
+ }
271
+ fs_1.default.writeFileSync(outputFile, content);
272
+ const fileSize = fs_1.default.statSync(outputFile).size;
273
+ spinner.succeed(chalk_1.default.green(`✅ Exported ${records.length} records to ${outputFile}`));
274
+ console.log(chalk_1.default.gray(` Size: ${(0, config_1.formatBytes)(fileSize)}`));
275
+ console.log(chalk_1.default.gray(` Format: ${options.format.toUpperCase()}`));
276
+ await db.close();
277
+ }
278
+ catch (error) {
279
+ spinner.fail(chalk_1.default.red('❌ Export failed'));
280
+ console.error(chalk_1.default.red(error.message));
281
+ process.exit(1);
282
+ }
283
+ });
284
+ exports.dbCommand
285
+ .command('import')
286
+ .description('Import data from file to table')
287
+ .argument('<file>', 'Input file path')
288
+ .option('-c, --config <path>', 'Path to config file', 'zero.config.ts')
289
+ .option('-t, --table <name>', 'Table name')
290
+ .option('-f, --format <format>', 'Input format (json|csv)', 'json')
291
+ .action(async (inputFile, options) => {
292
+ if (!options.table) {
293
+ console.error(chalk_1.default.red('Error: --table option is required'));
294
+ process.exit(1);
295
+ }
296
+ if (!fs_1.default.existsSync(inputFile)) {
297
+ console.error(chalk_1.default.red(`Error: File not found: ${inputFile}`));
298
+ process.exit(1);
299
+ }
300
+ const confirmed = await (0, prompts_1.confirmAction)(chalk_1.default.yellow(`⚠️ This will import data to ${options.table}. Are you sure?`));
301
+ if (!confirmed) {
302
+ console.log(chalk_1.default.yellow('Import cancelled'));
303
+ return;
304
+ }
305
+ const spinner = (0, ora_1.default)(`Importing to ${options.table}...`).start();
306
+ try {
307
+ const db = await (0, config_1.getDatabase)(options.config);
308
+ const content = fs_1.default.readFileSync(inputFile, 'utf-8');
309
+ let data = [];
310
+ if (options.format === 'csv') {
311
+ const lines = content.trim().split('\n');
312
+ const headers = lines[0].split(',');
313
+ data = lines.slice(1).map((line) => {
314
+ const values = line.split(',');
315
+ const row = {};
316
+ headers.forEach((h, i) => {
317
+ row[h] = values[i]?.replace(/"/g, '').trim();
318
+ });
319
+ return row;
320
+ });
321
+ }
322
+ else {
323
+ data = JSON.parse(content);
324
+ }
325
+ const count = await db.bulkInsert(options.table, data);
326
+ spinner.succeed(chalk_1.default.green(`✅ Imported ${count} records to ${options.table}`));
327
+ await db.close();
328
+ }
329
+ catch (error) {
330
+ spinner.fail(chalk_1.default.red('❌ Import failed'));
331
+ console.error(chalk_1.default.red(error.message));
332
+ process.exit(1);
333
+ }
334
+ });
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const exportCommand: Command;
3
+ export declare const importCommand: Command;