@tryhuset/foundation-utils 4.84.2
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/README.md +117 -0
- package/dist/jest.config.d.ts +3 -0
- package/dist/jest.config.js +33 -0
- package/dist/jest.config.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +17 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/db/end.d.ts +9 -0
- package/dist/src/commands/db/end.js +52 -0
- package/dist/src/commands/db/end.js.map +1 -0
- package/dist/src/commands/db/export.d.ts +13 -0
- package/dist/src/commands/db/export.js +39 -0
- package/dist/src/commands/db/export.js.map +1 -0
- package/dist/src/commands/db/import.d.ts +14 -0
- package/dist/src/commands/db/import.js +54 -0
- package/dist/src/commands/db/import.js.map +1 -0
- package/dist/src/commands/db/index.d.ts +12 -0
- package/dist/src/commands/db/index.js +50 -0
- package/dist/src/commands/db/index.js.map +1 -0
- package/dist/src/commands/db/list.d.ts +16 -0
- package/dist/src/commands/db/list.js +77 -0
- package/dist/src/commands/db/list.js.map +1 -0
- package/dist/src/commands/db/restore.d.ts +15 -0
- package/dist/src/commands/db/restore.js +70 -0
- package/dist/src/commands/db/restore.js.map +1 -0
- package/dist/src/commands/dbEnd.d.ts +8 -0
- package/dist/src/commands/dbEnd.js +51 -0
- package/dist/src/commands/dbEnd.js.map +1 -0
- package/dist/src/commands/dbExport.d.ts +12 -0
- package/dist/src/commands/dbExport.js +37 -0
- package/dist/src/commands/dbExport.js.map +1 -0
- package/dist/src/commands/dbImport.d.ts +14 -0
- package/dist/src/commands/dbImport.js +54 -0
- package/dist/src/commands/dbImport.js.map +1 -0
- package/dist/src/commands/dbList.d.ts +15 -0
- package/dist/src/commands/dbList.js +76 -0
- package/dist/src/commands/dbList.js.map +1 -0
- package/dist/src/commands/dbRestore.d.ts +14 -0
- package/dist/src/commands/dbRestore.js +69 -0
- package/dist/src/commands/dbRestore.js.map +1 -0
- package/dist/src/commands/docker/backup.d.ts +16 -0
- package/dist/src/commands/docker/backup.js +83 -0
- package/dist/src/commands/docker/backup.js.map +1 -0
- package/dist/src/commands/docker/docker.d.ts +23 -0
- package/dist/src/commands/docker/docker.js +176 -0
- package/dist/src/commands/docker/docker.js.map +1 -0
- package/dist/src/commands/docker/index.d.ts +11 -0
- package/dist/src/commands/docker/index.js +51 -0
- package/dist/src/commands/docker/index.js.map +1 -0
- package/dist/src/commands/docker/list.d.ts +9 -0
- package/dist/src/commands/docker/list.js +14 -0
- package/dist/src/commands/docker/list.js.map +1 -0
- package/dist/src/commands/docker/resolveComposeFile.d.ts +5 -0
- package/dist/src/commands/docker/resolveComposeFile.js +22 -0
- package/dist/src/commands/docker/resolveComposeFile.js.map +1 -0
- package/dist/src/commands/docker/restart.d.ts +11 -0
- package/dist/src/commands/docker/restart.js +16 -0
- package/dist/src/commands/docker/restart.js.map +1 -0
- package/dist/src/commands/docker/update.d.ts +15 -0
- package/dist/src/commands/docker/update.js +87 -0
- package/dist/src/commands/docker/update.js.map +1 -0
- package/dist/src/commands/docker.d.ts +23 -0
- package/dist/src/commands/docker.js +176 -0
- package/dist/src/commands/docker.js.map +1 -0
- package/dist/src/commands/index.d.ts +8 -0
- package/dist/src/commands/index.js +13 -0
- package/dist/src/commands/index.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/utils/dbConfig.d.ts +9 -0
- package/dist/src/utils/dbConfig.js +11 -0
- package/dist/src/utils/dbConfig.js.map +1 -0
- package/dist/src/utils/loadEnv.d.ts +5 -0
- package/dist/src/utils/loadEnv.js +14 -0
- package/dist/src/utils/loadEnv.js.map +1 -0
- package/dist/src/utils/processExit.d.ts +6 -0
- package/dist/src/utils/processExit.js +9 -0
- package/dist/src/utils/processExit.js.map +1 -0
- package/dist/src/utils/resolveComposeFile.d.ts +6 -0
- package/dist/src/utils/resolveComposeFile.js +25 -0
- package/dist/src/utils/resolveComposeFile.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# @tryhuset/foundation-utils
|
|
2
|
+
|
|
3
|
+
Public utility CLI tools for Foundation server framework. Provides generic tools for database and Docker management that can be installed without GitHub Personal Access Tokens.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @tryhuset/foundation-utils
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Database management
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
foundation-utils db list # List sessions
|
|
17
|
+
foundation-utils db restore # Restore a session by ID (ends current active if any)
|
|
18
|
+
foundation-utils db export # Export database to mongodump backup
|
|
19
|
+
foundation-utils db import # Import database from mongodump backup
|
|
20
|
+
foundation-utils db end # End all active sessions
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Requires `STORAGE_URL` environment variable. Use `-e, --env <path>` to load from a .env file.
|
|
24
|
+
|
|
25
|
+
**db list** – List sessions (default 50, newest first). Use `-a, --active` for active only, `-l, --limit <n>` to change limit.
|
|
26
|
+
|
|
27
|
+
**db restore** – Restore a session by ID. Ends the current active session if one exists. Requires `-i, --id <sessionId>`. Restart the server to pick up the restored session.
|
|
28
|
+
|
|
29
|
+
**db export** – Create mongodump backup. Requires `-o, --out <path>` for output directory.
|
|
30
|
+
|
|
31
|
+
**db import** – Import from mongodump backup. Requires `-p, --path <path>` to dump directory.
|
|
32
|
+
|
|
33
|
+
**db end** – Ends all sessions by updating endedAt with `null` to have the current date.
|
|
34
|
+
|
|
35
|
+
### Docker Compose management
|
|
36
|
+
|
|
37
|
+
Uses `./compose.yaml` by default. Override with `-f, --file <path>`.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Update images with backup (default: ./compose.yaml)
|
|
41
|
+
foundation-utils docker update
|
|
42
|
+
|
|
43
|
+
# Create backup only
|
|
44
|
+
foundation-utils docker backup
|
|
45
|
+
|
|
46
|
+
# Restore stack from a backup compose file (from docker backup output)
|
|
47
|
+
foundation-utils docker backup --restore ./docker_image_backups/docker-compose_20260101T120000.yaml
|
|
48
|
+
|
|
49
|
+
# Update without backup
|
|
50
|
+
foundation-utils docker update --no-backup
|
|
51
|
+
|
|
52
|
+
# Force without confirmation (e.g. restore)
|
|
53
|
+
foundation-utils docker backup --restore ./docker_image_backups/docker-compose_20260101T120000.yaml --force
|
|
54
|
+
foundation-utils docker update --force
|
|
55
|
+
|
|
56
|
+
# Restart a specific service
|
|
57
|
+
foundation-utils docker restart -s <service-name>
|
|
58
|
+
|
|
59
|
+
# List containers (docker compose ps)
|
|
60
|
+
foundation-utils docker list
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Programmatic Usage
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { Command } from 'commander';
|
|
67
|
+
import {
|
|
68
|
+
registerCommands,
|
|
69
|
+
dbEnd,
|
|
70
|
+
dbExport,
|
|
71
|
+
dbImport,
|
|
72
|
+
dbList,
|
|
73
|
+
dbRestore,
|
|
74
|
+
dockerBackup,
|
|
75
|
+
dockerList,
|
|
76
|
+
dockerRestart,
|
|
77
|
+
dockerUpdate
|
|
78
|
+
} from '@tryhuset/foundation-utils';
|
|
79
|
+
|
|
80
|
+
// Attach all db + docker subcommands to a Commander program
|
|
81
|
+
const program = new Command();
|
|
82
|
+
registerCommands(program);
|
|
83
|
+
|
|
84
|
+
// End all active sessions
|
|
85
|
+
await dbEnd();
|
|
86
|
+
|
|
87
|
+
// List sessions
|
|
88
|
+
await dbList({ active: true });
|
|
89
|
+
|
|
90
|
+
// Restore a session by ID
|
|
91
|
+
await dbRestore({ sessionId: 'abc123', force: true });
|
|
92
|
+
|
|
93
|
+
// Export database backup
|
|
94
|
+
await dbExport({ path: './backup' });
|
|
95
|
+
|
|
96
|
+
// Import from backup
|
|
97
|
+
await dbImport({ path: './backup' });
|
|
98
|
+
|
|
99
|
+
// Create backup only
|
|
100
|
+
await dockerBackup();
|
|
101
|
+
|
|
102
|
+
// Update Docker images (default: ./compose.yaml)
|
|
103
|
+
await dockerUpdate({ force: true });
|
|
104
|
+
|
|
105
|
+
// Restore stack from backup compose file (same as: docker backup --restore <path>)
|
|
106
|
+
await dockerUpdate({ backupFile: './docker_image_backups/docker-compose_20260101T120000.yaml', force: true });
|
|
107
|
+
|
|
108
|
+
// Restart a service
|
|
109
|
+
await dockerRestart({ service: 'api' });
|
|
110
|
+
|
|
111
|
+
// List containers
|
|
112
|
+
await dockerList();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
MIT
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const config = {
|
|
2
|
+
preset: 'ts-jest/presets/default-esm',
|
|
3
|
+
roots: ['<rootDir>/src'],
|
|
4
|
+
collectCoverageFrom: [
|
|
5
|
+
'./src/**/*',
|
|
6
|
+
'!**/coverage/**',
|
|
7
|
+
'!**/node_modules/**',
|
|
8
|
+
'!*.config.js',
|
|
9
|
+
'!**/__tests__/**'
|
|
10
|
+
],
|
|
11
|
+
testMatch: ['**/*.spec.ts'],
|
|
12
|
+
transform: {
|
|
13
|
+
'^.+\\.m?ts$': [
|
|
14
|
+
'ts-jest',
|
|
15
|
+
{
|
|
16
|
+
useESM: true,
|
|
17
|
+
tsconfig: 'tsconfig.spec.json'
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
extensionsToTreatAsEsm: ['.ts', '.tsx'],
|
|
22
|
+
transformIgnorePatterns: ['node_modules/(?!(#ansi-styles|#supports-color|#has-flag|#chalk)/)'],
|
|
23
|
+
moduleNameMapper: {
|
|
24
|
+
'^(\\.{1,2}/.*)\\.js$': '$1'
|
|
25
|
+
},
|
|
26
|
+
moduleDirectories: ['node_modules', '../../node_modules', 'src'],
|
|
27
|
+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node', 'mjs'],
|
|
28
|
+
verbose: true,
|
|
29
|
+
forceExit: true,
|
|
30
|
+
testTimeout: 30000
|
|
31
|
+
};
|
|
32
|
+
export default config;
|
|
33
|
+
//# sourceMappingURL=jest.config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jest.config.js","sourceRoot":"","sources":["../jest.config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAA0B;IACpC,MAAM,EAAE,6BAA6B;IACrC,KAAK,EAAE,CAAC,eAAe,CAAC;IACxB,mBAAmB,EAAE;QACnB,YAAY;QACZ,iBAAiB;QACjB,qBAAqB;QACrB,cAAc;QACd,kBAAkB;KACnB;IACD,SAAS,EAAE,CAAC,cAAc,CAAC;IAC3B,SAAS,EAAE;QACT,aAAa,EAAE;YACb,SAAS;YACT;gBACE,MAAM,EAAE,IAAI;gBACZ,QAAQ,EAAE,oBAAoB;aAC/B;SACF;KACF;IACD,sBAAsB,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;IACvC,uBAAuB,EAAE,CAAC,mEAAmE,CAAC;IAC9F,gBAAgB,EAAE;QAChB,sBAAsB,EAAE,IAAI;KAC7B;IACD,iBAAiB,EAAE,CAAC,cAAc,EAAE,oBAAoB,EAAE,KAAK,CAAC;IAChE,oBAAoB,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC;IACvE,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,KAAK;CACnB,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
import { readFileSync } from 'fs';
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { registerCommands } from './commands/index.js';
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8'));
|
|
10
|
+
const program = new Command();
|
|
11
|
+
program
|
|
12
|
+
.name('foundation-utils')
|
|
13
|
+
.description('Utility CLI tools for Foundation server framework')
|
|
14
|
+
.version(pkg.version);
|
|
15
|
+
registerCommands(program);
|
|
16
|
+
program.parse();
|
|
17
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAElC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAE3F,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,kBAAkB,CAAC;KACxB,WAAW,CAAC,mDAAmD,CAAC;KAChE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAExB,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ends all active sessions in the Foundation database by updating
|
|
3
|
+
* sessions with null endedAt to have the current date.
|
|
4
|
+
* @param [options] Optional settings.
|
|
5
|
+
* @param [options.env] Path to .env file to load before reading STORAGE_URL.
|
|
6
|
+
*/
|
|
7
|
+
export declare const dbEnd: (options?: {
|
|
8
|
+
env?: string;
|
|
9
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles managing the Foundation database.
|
|
3
|
+
* This command will handle any necessary database operations.
|
|
4
|
+
*
|
|
5
|
+
* Currently supports:
|
|
6
|
+
* - Updating sessions with null endedAt to have the current date
|
|
7
|
+
*/
|
|
8
|
+
import { MongoClient } from 'mongodb';
|
|
9
|
+
import inquirer from 'inquirer';
|
|
10
|
+
import { exitProcess } from '../../utils/processExit.js';
|
|
11
|
+
import { loadEnv } from '../../utils/loadEnv.js';
|
|
12
|
+
import { getDbConfig } from '../../utils/dbConfig.js';
|
|
13
|
+
/**
|
|
14
|
+
* Ends all active sessions in the Foundation database by updating
|
|
15
|
+
* sessions with null endedAt to have the current date.
|
|
16
|
+
* @param [options] Optional settings.
|
|
17
|
+
* @param [options.env] Path to .env file to load before reading STORAGE_URL.
|
|
18
|
+
*/
|
|
19
|
+
export const dbEnd = async (options) => {
|
|
20
|
+
loadEnv(options?.env);
|
|
21
|
+
const { storageUrl, dbCollection } = getDbConfig();
|
|
22
|
+
if (!storageUrl) {
|
|
23
|
+
console.error('STORAGE_URL environment variable not set');
|
|
24
|
+
exitProcess(1);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const { confirm } = await inquirer.prompt([
|
|
28
|
+
{
|
|
29
|
+
type: 'confirm',
|
|
30
|
+
name: 'confirm',
|
|
31
|
+
message: 'This will update all sessions with null endedAt to have the current date. Continue?',
|
|
32
|
+
default: false
|
|
33
|
+
}
|
|
34
|
+
]);
|
|
35
|
+
if (!confirm) {
|
|
36
|
+
console.log('Operation cancelled');
|
|
37
|
+
exitProcess(0);
|
|
38
|
+
}
|
|
39
|
+
const client = await MongoClient.connect(storageUrl);
|
|
40
|
+
const db = client.db();
|
|
41
|
+
const result = await db
|
|
42
|
+
.collection(dbCollection)
|
|
43
|
+
.updateMany({ endedAt: null }, { $set: { endedAt: new Date() } });
|
|
44
|
+
console.log(`Updated ${result.modifiedCount} sessions`);
|
|
45
|
+
await client.close();
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error('Failed to update sessions:', error);
|
|
49
|
+
exitProcess(1);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=end.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"end.js","sourceRoot":"","sources":["../../../../src/commands/db/end.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAAE,OAA0B,EAAE,EAAE;IACxD,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,WAAW,EAAE,CAAC;IAEnD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,WAAW,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YACxC;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,SAAS;gBACf,OAAO,EACL,qFAAqF;gBACvF,OAAO,EAAE,KAAK;aACf;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;YACnC,WAAW,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,UAAW,CAAC,CAAC;QACtD,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,EAAE,CAAC;QAEvB,MAAM,MAAM,GAAG,MAAM,EAAE;aACpB,UAAU,CAAC,YAAY,CAAC;aACxB,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAEpE,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,aAAa,WAAW,CAAC,CAAC;QACxD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;QACnD,WAAW,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface DbExportOptions {
|
|
2
|
+
env?: string;
|
|
3
|
+
path: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Exports the database to a mongodump backup directory.
|
|
7
|
+
* Requires mongodump to be installed (MongoDB Database Tools).
|
|
8
|
+
* @param options Export options.
|
|
9
|
+
* @param [options.env] Path to .env file.
|
|
10
|
+
* @param options.path Output directory for the dump.
|
|
11
|
+
*/
|
|
12
|
+
export declare const dbExport: (options: DbExportOptions) => Promise<void>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exports the Foundation database to a mongodump backup.
|
|
3
|
+
*/
|
|
4
|
+
import { execFileSync } from 'child_process';
|
|
5
|
+
import { mkdirSync, existsSync } from 'fs';
|
|
6
|
+
import { exitProcess } from '../../utils/processExit.js';
|
|
7
|
+
import { loadEnv } from '../../utils/loadEnv.js';
|
|
8
|
+
import { getDbConfig } from '../../utils/dbConfig.js';
|
|
9
|
+
/**
|
|
10
|
+
* Exports the database to a mongodump backup directory.
|
|
11
|
+
* Requires mongodump to be installed (MongoDB Database Tools).
|
|
12
|
+
* @param options Export options.
|
|
13
|
+
* @param [options.env] Path to .env file.
|
|
14
|
+
* @param options.path Output directory for the dump.
|
|
15
|
+
*/
|
|
16
|
+
export const dbExport = async (options) => {
|
|
17
|
+
loadEnv(options?.env);
|
|
18
|
+
const { storageUrl } = getDbConfig();
|
|
19
|
+
if (!storageUrl) {
|
|
20
|
+
console.error('STORAGE_URL environment variable not set');
|
|
21
|
+
exitProcess(1);
|
|
22
|
+
}
|
|
23
|
+
const uri = storageUrl;
|
|
24
|
+
const outPath = options.path;
|
|
25
|
+
try {
|
|
26
|
+
if (!existsSync(outPath)) {
|
|
27
|
+
mkdirSync(outPath, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
execFileSync('mongodump', ['--uri', uri, '--out', outPath], {
|
|
30
|
+
stdio: 'inherit'
|
|
31
|
+
});
|
|
32
|
+
console.log(`Export completed to ${outPath}`);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error('Failed to export:', error);
|
|
36
|
+
exitProcess(1);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../../../src/commands/db/export.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAE3C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAOtD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAE,OAAwB,EAAE,EAAE;IACzD,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,GAAG,WAAW,EAAE,CAAC;IAErC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,WAAW,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,GAAG,GAAG,UAAoB,CAAC;IACjC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAE7B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,CAAC;QAED,YAAY,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;YAC1D,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;QAC1C,WAAW,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface DbImportOptions {
|
|
2
|
+
env?: string;
|
|
3
|
+
path: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Imports the database from a mongodump backup directory.
|
|
7
|
+
* Requires mongorestore to be installed (MongoDB Database Tools).
|
|
8
|
+
* Always prompts for confirmation.
|
|
9
|
+
* @param options Import options.
|
|
10
|
+
* @param [options.env] Path to .env file.
|
|
11
|
+
* @param options.path Dump directory (mongodump output).
|
|
12
|
+
*/
|
|
13
|
+
export declare const dbImport: (options: DbImportOptions) => Promise<void>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Imports the Foundation database from a mongodump backup.
|
|
3
|
+
*/
|
|
4
|
+
import { execFileSync } from 'child_process';
|
|
5
|
+
import { existsSync } from 'fs';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import { exitProcess } from '../../utils/processExit.js';
|
|
8
|
+
import { loadEnv } from '../../utils/loadEnv.js';
|
|
9
|
+
import { getDbConfig } from '../../utils/dbConfig.js';
|
|
10
|
+
/**
|
|
11
|
+
* Imports the database from a mongodump backup directory.
|
|
12
|
+
* Requires mongorestore to be installed (MongoDB Database Tools).
|
|
13
|
+
* Always prompts for confirmation.
|
|
14
|
+
* @param options Import options.
|
|
15
|
+
* @param [options.env] Path to .env file.
|
|
16
|
+
* @param options.path Dump directory (mongodump output).
|
|
17
|
+
*/
|
|
18
|
+
export const dbImport = async (options) => {
|
|
19
|
+
loadEnv(options?.env);
|
|
20
|
+
const { storageUrl } = getDbConfig();
|
|
21
|
+
if (!storageUrl) {
|
|
22
|
+
console.error('STORAGE_URL environment variable not set');
|
|
23
|
+
exitProcess(1);
|
|
24
|
+
}
|
|
25
|
+
const uri = storageUrl;
|
|
26
|
+
const dumpPath = options.path;
|
|
27
|
+
if (!existsSync(dumpPath)) {
|
|
28
|
+
console.error(`Dump path not found: ${dumpPath}`);
|
|
29
|
+
exitProcess(1);
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const { confirm } = await inquirer.prompt([
|
|
33
|
+
{
|
|
34
|
+
type: 'confirm',
|
|
35
|
+
name: 'confirm',
|
|
36
|
+
message: `Import database from ${dumpPath}? This will overwrite existing data.`,
|
|
37
|
+
default: false
|
|
38
|
+
}
|
|
39
|
+
]);
|
|
40
|
+
if (!confirm) {
|
|
41
|
+
console.log('Operation cancelled');
|
|
42
|
+
exitProcess(0);
|
|
43
|
+
}
|
|
44
|
+
execFileSync('mongorestore', ['--uri', uri, dumpPath], {
|
|
45
|
+
stdio: 'inherit'
|
|
46
|
+
});
|
|
47
|
+
console.log('Import completed');
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error('Failed to import:', error);
|
|
51
|
+
exitProcess(1);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../../../src/commands/db/import.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEhC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAOtD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAE,OAAwB,EAAE,EAAE;IACzD,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,GAAG,WAAW,EAAE,CAAC;IAErC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,WAAW,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,GAAG,GAAG,UAAoB,CAAC;IACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAE9B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAC;QAClD,WAAW,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YACxC;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,wBAAwB,QAAQ,sCAAsC;gBAC/E,OAAO,EAAE,KAAK;aACf;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;YACnC,WAAW,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,YAAY,CAAC,cAAc,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE;YACrD,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;QAC1C,WAAW,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { dbEnd } from './end.js';
|
|
3
|
+
import { dbExport } from './export.js';
|
|
4
|
+
import { dbImport } from './import.js';
|
|
5
|
+
import { dbList } from './list.js';
|
|
6
|
+
import { dbRestore } from './restore.js';
|
|
7
|
+
export { dbEnd, dbExport, dbImport, dbList, dbRestore };
|
|
8
|
+
/**
|
|
9
|
+
* Registers `db` subcommands on the given Commander program.
|
|
10
|
+
* @param program Commander root or parent command.
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerDbCommands(program: Command): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { dbEnd } from './end.js';
|
|
2
|
+
import { dbExport } from './export.js';
|
|
3
|
+
import { dbImport } from './import.js';
|
|
4
|
+
import { dbList } from './list.js';
|
|
5
|
+
import { dbRestore } from './restore.js';
|
|
6
|
+
export { dbEnd, dbExport, dbImport, dbList, dbRestore };
|
|
7
|
+
/**
|
|
8
|
+
* Registers `db` subcommands on the given Commander program.
|
|
9
|
+
* @param program Commander root or parent command.
|
|
10
|
+
*/
|
|
11
|
+
export function registerDbCommands(program) {
|
|
12
|
+
const db = program.command('db').description('Database management');
|
|
13
|
+
db.command('list')
|
|
14
|
+
.description('List sessions in the Foundation database')
|
|
15
|
+
.option('-e, --env <path>', 'Path to .env file')
|
|
16
|
+
.option('-l, --limit <n>', 'Max sessions to show', '50')
|
|
17
|
+
.option('-a, --active', 'Only show active sessions')
|
|
18
|
+
.option('-f, --fields <fields>', 'Additional fields to show (comma-separated, e.g. currentDay,category)')
|
|
19
|
+
.action((opts) => dbList({
|
|
20
|
+
...opts,
|
|
21
|
+
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
22
|
+
fields: opts.fields
|
|
23
|
+
? opts.fields
|
|
24
|
+
.split(',')
|
|
25
|
+
.map((s) => s.trim())
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
: undefined
|
|
28
|
+
}));
|
|
29
|
+
db.command('restore')
|
|
30
|
+
.description('Restore a session by ID (ends current active session if any)')
|
|
31
|
+
.requiredOption('-i, --id <sessionId>', 'Session ID to restore')
|
|
32
|
+
.option('-e, --env <path>', 'Path to .env file')
|
|
33
|
+
.option('--force', 'Skip confirmation prompt')
|
|
34
|
+
.action((opts) => dbRestore({ ...opts, sessionId: opts.id }));
|
|
35
|
+
db.command('export')
|
|
36
|
+
.description('Export database to mongodump backup')
|
|
37
|
+
.requiredOption('-o, --out <path>', 'Output directory for dump')
|
|
38
|
+
.option('-e, --env <path>', 'Path to .env file')
|
|
39
|
+
.action(dbExport);
|
|
40
|
+
db.command('import')
|
|
41
|
+
.description('Import database from mongodump backup')
|
|
42
|
+
.requiredOption('-p, --path <path>', 'Path to dump directory')
|
|
43
|
+
.option('-e, --env <path>', 'Path to .env file')
|
|
44
|
+
.action(dbImport);
|
|
45
|
+
db.command('end')
|
|
46
|
+
.description('End all sessions in the Foundation database')
|
|
47
|
+
.option('-e, --env <path>', 'Path to .env file')
|
|
48
|
+
.action(dbEnd);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/db/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAExD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,qBAAqB,CAAC,CAAC;IAEpE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;SAC/C,MAAM,CAAC,iBAAiB,EAAE,sBAAsB,EAAE,IAAI,CAAC;SACvD,MAAM,CAAC,cAAc,EAAE,2BAA2B,CAAC;SACnD,MAAM,CACL,uBAAuB,EACvB,uEAAuE,CACxE;SACA,MAAM,CAAC,CAAC,IAAyE,EAAE,EAAE,CACpF,MAAM,CAAC;QACL,GAAG,IAAI;QACP,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QACxD,MAAM,EAAE,IAAI,CAAC,MAAM;YACjB,CAAC,CAAC,IAAI,CAAC,MAAM;iBACR,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBAC5B,MAAM,CAAC,OAAO,CAAC;YACpB,CAAC,CAAC,SAAS;KACd,CAAC,CACH,CAAC;IAEJ,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,8DAA8D,CAAC;SAC3E,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;SAC/D,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;SAC/C,MAAM,CAAC,SAAS,EAAE,0BAA0B,CAAC;SAC7C,MAAM,CAAC,CAAC,IAAmD,EAAE,EAAE,CAC9D,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAC3C,CAAC;IAEJ,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,qCAAqC,CAAC;SAClD,cAAc,CAAC,kBAAkB,EAAE,2BAA2B,CAAC;SAC/D,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;SAC/C,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEpB,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,uCAAuC,CAAC;SACpD,cAAc,CAAC,mBAAmB,EAAE,wBAAwB,CAAC;SAC7D,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;SAC/C,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEpB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;SAC/C,MAAM,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface DbListOptions {
|
|
2
|
+
env?: string;
|
|
3
|
+
limit?: number;
|
|
4
|
+
active?: boolean;
|
|
5
|
+
fields?: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Lists sessions in the Foundation database.
|
|
9
|
+
* @param [options] List filters and display options.
|
|
10
|
+
* @param [options.env] Path to .env file.
|
|
11
|
+
* @param [options.limit] Max sessions to show (default 50).
|
|
12
|
+
* @param [options.active] If true, only sessions with null endedAt.
|
|
13
|
+
* @param [options.fields] Extra session fields to show (comma-separated); missing values show '-'.
|
|
14
|
+
*/
|
|
15
|
+
export declare const dbList: (options?: DbListOptions) => Promise<void>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lists sessions in the Foundation database.
|
|
3
|
+
*/
|
|
4
|
+
import { MongoClient } from 'mongodb';
|
|
5
|
+
import { exitProcess } from '../../utils/processExit.js';
|
|
6
|
+
import { loadEnv } from '../../utils/loadEnv.js';
|
|
7
|
+
import { getDbConfig } from '../../utils/dbConfig.js';
|
|
8
|
+
const formatFieldValue = (value) => {
|
|
9
|
+
if (value === null || value === undefined)
|
|
10
|
+
return '-';
|
|
11
|
+
if (value instanceof Date)
|
|
12
|
+
return value.toISOString();
|
|
13
|
+
if (typeof value === 'object')
|
|
14
|
+
return JSON.stringify(value);
|
|
15
|
+
return String(value);
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Lists sessions in the Foundation database.
|
|
19
|
+
* @param [options] List filters and display options.
|
|
20
|
+
* @param [options.env] Path to .env file.
|
|
21
|
+
* @param [options.limit] Max sessions to show (default 50).
|
|
22
|
+
* @param [options.active] If true, only sessions with null endedAt.
|
|
23
|
+
* @param [options.fields] Extra session fields to show (comma-separated); missing values show '-'.
|
|
24
|
+
*/
|
|
25
|
+
export const dbList = async (options) => {
|
|
26
|
+
loadEnv(options?.env);
|
|
27
|
+
const { storageUrl, dbCollection } = getDbConfig();
|
|
28
|
+
if (!storageUrl) {
|
|
29
|
+
console.error('STORAGE_URL environment variable not set');
|
|
30
|
+
exitProcess(1);
|
|
31
|
+
}
|
|
32
|
+
const extraFields = options?.fields ?? [];
|
|
33
|
+
const project = { id: 1, name: 1, startedAt: 1, endedAt: 1 };
|
|
34
|
+
for (const f of extraFields) {
|
|
35
|
+
if (f.trim())
|
|
36
|
+
project[f.trim()] = 1;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const client = await MongoClient.connect(storageUrl);
|
|
40
|
+
const db = client.db();
|
|
41
|
+
const filter = {};
|
|
42
|
+
if (options?.active) {
|
|
43
|
+
filter.endedAt = null;
|
|
44
|
+
}
|
|
45
|
+
const limit = options?.limit ?? 50;
|
|
46
|
+
const sessions = await db
|
|
47
|
+
.collection(dbCollection)
|
|
48
|
+
.find(filter)
|
|
49
|
+
.sort({ startedAt: -1 })
|
|
50
|
+
.limit(limit)
|
|
51
|
+
.project(project)
|
|
52
|
+
.toArray();
|
|
53
|
+
await client.close();
|
|
54
|
+
if (sessions.length === 0) {
|
|
55
|
+
console.log('No sessions found');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const baseHeaders = ['ID', 'Name', 'Started', 'Ended'];
|
|
59
|
+
const headers = [...baseHeaders, ...extraFields.map((f) => f.trim()).filter(Boolean)];
|
|
60
|
+
const rows = sessions.map((s) => {
|
|
61
|
+
const started = s.startedAt ? new Date(s.startedAt).toISOString() : '-';
|
|
62
|
+
const ended = s.endedAt ? new Date(s.endedAt).toISOString() : 'active';
|
|
63
|
+
const base = [s.id, String(s.name || '-'), started, ended];
|
|
64
|
+
const extras = extraFields.map((f) => formatFieldValue(s[f.trim()]));
|
|
65
|
+
return [...base, ...extras].join('\t');
|
|
66
|
+
});
|
|
67
|
+
console.log(headers.join('\t'));
|
|
68
|
+
console.log('-'.repeat(Math.min(80, headers.join('\t').length + 20)));
|
|
69
|
+
rows.forEach((r) => console.log(r));
|
|
70
|
+
console.log(`\nTotal: ${sessions.length} session(s)`);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error('Failed to list sessions:', error);
|
|
74
|
+
exitProcess(1);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/commands/db/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface DbRestoreOptions {
|
|
2
|
+
env?: string;
|
|
3
|
+
sessionId: string;
|
|
4
|
+
force?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Restores a session by ID. Ends any active session first, then sets the target session as active.
|
|
8
|
+
* Restart the server to pick up the restored session.
|
|
9
|
+
* @param options Restore options.
|
|
10
|
+
* @param [options.env] Path to .env file.
|
|
11
|
+
* @param options.sessionId Session ID to restore (from db list).
|
|
12
|
+
* @param [options.force] Skip confirmation prompt.
|
|
13
|
+
*/
|
|
14
|
+
export declare const dbRestore: (options: DbRestoreOptions) => Promise<void>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Restores a session by ID, making it active. Ends the current active session if one exists.
|
|
3
|
+
*/
|
|
4
|
+
import { MongoClient } from 'mongodb';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import { exitProcess } from '../../utils/processExit.js';
|
|
7
|
+
import { loadEnv } from '../../utils/loadEnv.js';
|
|
8
|
+
import { getDbConfig } from '../../utils/dbConfig.js';
|
|
9
|
+
/**
|
|
10
|
+
* Restores a session by ID. Ends any active session first, then sets the target session as active.
|
|
11
|
+
* Restart the server to pick up the restored session.
|
|
12
|
+
* @param options Restore options.
|
|
13
|
+
* @param [options.env] Path to .env file.
|
|
14
|
+
* @param options.sessionId Session ID to restore (from db list).
|
|
15
|
+
* @param [options.force] Skip confirmation prompt.
|
|
16
|
+
*/
|
|
17
|
+
export const dbRestore = async (options) => {
|
|
18
|
+
loadEnv(options?.env);
|
|
19
|
+
const { storageUrl, dbCollection } = getDbConfig();
|
|
20
|
+
if (!storageUrl) {
|
|
21
|
+
console.error('STORAGE_URL environment variable not set');
|
|
22
|
+
exitProcess(1);
|
|
23
|
+
}
|
|
24
|
+
const sessionId = options.sessionId;
|
|
25
|
+
try {
|
|
26
|
+
const client = await MongoClient.connect(storageUrl);
|
|
27
|
+
const db = client.db();
|
|
28
|
+
const collection = db.collection(dbCollection);
|
|
29
|
+
const targetSession = await collection.findOne({ id: sessionId });
|
|
30
|
+
if (!targetSession) {
|
|
31
|
+
console.error(`Session not found: ${sessionId}`);
|
|
32
|
+
await client.close();
|
|
33
|
+
exitProcess(1);
|
|
34
|
+
}
|
|
35
|
+
const sessionName = targetSession.name ?? sessionId;
|
|
36
|
+
if (!options.force) {
|
|
37
|
+
const { confirm } = await inquirer.prompt([
|
|
38
|
+
{
|
|
39
|
+
type: 'confirm',
|
|
40
|
+
name: 'confirm',
|
|
41
|
+
message: `Restore session "${sessionName}"? This will end the current active session if one exists.`,
|
|
42
|
+
default: false
|
|
43
|
+
}
|
|
44
|
+
]);
|
|
45
|
+
if (!confirm) {
|
|
46
|
+
console.log('Operation cancelled');
|
|
47
|
+
await client.close();
|
|
48
|
+
exitProcess(0);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const now = new Date();
|
|
52
|
+
const endResult = await collection.updateMany({ id: { $ne: sessionId }, endedAt: null }, { $set: { endedAt: now } });
|
|
53
|
+
const restoreResult = await collection.updateOne({ id: sessionId }, { $set: { endedAt: null } });
|
|
54
|
+
await client.close();
|
|
55
|
+
if (endResult.modifiedCount > 0) {
|
|
56
|
+
console.log(`Ended ${endResult.modifiedCount} active session(s)`);
|
|
57
|
+
}
|
|
58
|
+
if (restoreResult.modifiedCount > 0) {
|
|
59
|
+
console.log(`Restored session ${sessionId}. Restart the server to pick it up.`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.log(`Session ${sessionId} is already active.`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error('Failed to restore session:', error);
|
|
67
|
+
exitProcess(1);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=restore.js.map
|