@tryhuset/foundation-utils 4.84.5 → 4.85.1
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 +35 -2
- package/dist/src/commands/docker/backup.d.ts +2 -0
- package/dist/src/commands/docker/backup.js +3 -1
- package/dist/src/commands/docker/backup.js.map +1 -1
- package/dist/src/commands/docker/composeServices.d.ts +5 -0
- package/dist/src/commands/docker/composeServices.js +58 -0
- package/dist/src/commands/docker/composeServices.js.map +1 -0
- package/dist/src/commands/docker/index.d.ts +3 -1
- package/dist/src/commands/docker/index.js +40 -4
- package/dist/src/commands/docker/index.js.map +1 -1
- package/dist/src/commands/docker/logs.d.ts +20 -0
- package/dist/src/commands/docker/logs.js +28 -0
- package/dist/src/commands/docker/logs.js.map +1 -0
- package/dist/src/commands/docker/restart.d.ts +7 -5
- package/dist/src/commands/docker/restart.js +18 -6
- package/dist/src/commands/docker/restart.js.map +1 -1
- package/dist/src/commands/docker/restore.d.ts +13 -0
- package/dist/src/commands/docker/restore.js +63 -0
- package/dist/src/commands/docker/restore.js.map +1 -0
- package/dist/src/commands/index.d.ts +1 -1
- package/dist/src/commands/index.js +1 -1
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,13 +53,33 @@ foundation-utils docker update --no-backup
|
|
|
53
53
|
foundation-utils docker backup --restore ./docker_image_backups/docker-compose_20260101T120000.yaml --force
|
|
54
54
|
foundation-utils docker update --force
|
|
55
55
|
|
|
56
|
-
# Restart
|
|
56
|
+
# Restart service(s) (interactive multi-select, or -s to skip)
|
|
57
|
+
foundation-utils docker restart
|
|
57
58
|
foundation-utils docker restart -s <service-name>
|
|
59
|
+
foundation-utils docker restart -s api worker
|
|
58
60
|
|
|
59
61
|
# List containers (docker compose ps)
|
|
60
62
|
foundation-utils docker list
|
|
63
|
+
|
|
64
|
+
# Container logs (interactive service picker; or pass -s / --all)
|
|
65
|
+
foundation-utils docker logs
|
|
66
|
+
foundation-utils docker logs --all
|
|
67
|
+
foundation-utils docker logs -s <service-name> --follow
|
|
68
|
+
foundation-utils docker logs -n 200
|
|
69
|
+
|
|
70
|
+
# Restore stack from a saved backup (interactive list of docker-compose_*.yaml)
|
|
71
|
+
foundation-utils docker restore
|
|
72
|
+
foundation-utils docker restore -d ./docker_image_backups
|
|
73
|
+
foundation-utils docker restore ./docker_image_backups/docker-compose_20260101T120000.yaml
|
|
74
|
+
foundation-utils docker restore --force
|
|
61
75
|
```
|
|
62
76
|
|
|
77
|
+
**docker logs** – Runs `docker compose logs`. With no `-s`, opens an interactive list (all services or a single service from `docker compose config --services`). Use `--all` to skip the picker and show every service. Use `-s, --service` to target one service without prompting. `--follow` and `-n, --tail` work as in Docker.
|
|
78
|
+
|
|
79
|
+
**docker restart** – Runs `docker compose restart`. With no `-s`, opens an interactive **checkbox** (space to toggle, enter to confirm) from `docker compose config --services`. Use `-s, --service <names...>` for one or more services without prompting, e.g. `-s api worker`.
|
|
80
|
+
|
|
81
|
+
**docker restore** – Lists backups under `./docker_image_backups` (newest first) and prompts you to pick one, then runs the same flow as `docker backup --restore`. Pass a path to skip the list. Use `-d, --dir` to scan another folder.
|
|
82
|
+
|
|
63
83
|
## Programmatic Usage
|
|
64
84
|
|
|
65
85
|
```typescript
|
|
@@ -73,7 +93,9 @@ import {
|
|
|
73
93
|
dbRestore,
|
|
74
94
|
dockerBackup,
|
|
75
95
|
dockerList,
|
|
96
|
+
dockerLogs,
|
|
76
97
|
dockerRestart,
|
|
98
|
+
dockerRestore,
|
|
77
99
|
dockerUpdate
|
|
78
100
|
} from '@tryhuset/foundation-utils';
|
|
79
101
|
|
|
@@ -105,8 +127,19 @@ await dockerUpdate({ force: true });
|
|
|
105
127
|
// Restore stack from backup compose file (same as: docker backup --restore <path>)
|
|
106
128
|
await dockerUpdate({ backupFile: './docker_image_backups/docker-compose_20260101T120000.yaml', force: true });
|
|
107
129
|
|
|
108
|
-
//
|
|
130
|
+
// Interactive restore (list backups, then pick) or pass a path
|
|
131
|
+
await dockerRestore();
|
|
132
|
+
await dockerRestore({ backupCompose: './docker_image_backups/docker-compose_20260101T120000.yaml' });
|
|
133
|
+
|
|
134
|
+
// Logs: interactive picker, or allServices / explicit service
|
|
135
|
+
await dockerLogs({ follow: true, tail: 200 });
|
|
136
|
+
await dockerLogs({ allServices: true, follow: true });
|
|
137
|
+
await dockerLogs({ follow: true, tail: 200, service: 'api' });
|
|
138
|
+
|
|
139
|
+
// Restart (interactive multi-select) or pass service(s)
|
|
140
|
+
await dockerRestart();
|
|
109
141
|
await dockerRestart({ service: 'api' });
|
|
142
|
+
await dockerRestart({ services: ['api', 'worker'] });
|
|
110
143
|
|
|
111
144
|
// List containers
|
|
112
145
|
await dockerList();
|
|
@@ -3,7 +3,9 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
|
3
3
|
import { Chalk } from 'chalk';
|
|
4
4
|
import { resolveComposeFile } from '../../utils/resolveComposeFile.js';
|
|
5
5
|
const chalk = new Chalk();
|
|
6
|
-
|
|
6
|
+
/** Default directory for backup compose files and image info (see docker backup). */
|
|
7
|
+
export const DOCKER_IMAGE_BACKUP_DIR = './docker_image_backups';
|
|
8
|
+
const BACKUP_DIR = DOCKER_IMAGE_BACKUP_DIR;
|
|
7
9
|
/**
|
|
8
10
|
* Creates a backup of current Docker images (tags and compose file).
|
|
9
11
|
* Does not pull or restart anything.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backup.js","sourceRoot":"","sources":["../../../../src/commands/docker/backup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;AAE1B,MAAM,
|
|
1
|
+
{"version":3,"file":"backup.js","sourceRoot":"","sources":["../../../../src/commands/docker/backup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Sentinel for logs picker: stream all services. */
|
|
2
|
+
export declare const ALL_SERVICES_LOGS_VALUE = "__all__";
|
|
3
|
+
export declare function listComposeServiceNames(composeFile: string): string[];
|
|
4
|
+
export declare function promptComposeServiceForLogs(composeFile: string): Promise<string | undefined>;
|
|
5
|
+
export declare function promptComposeServiceForRestart(composeFile: string): Promise<string[]>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { Chalk } from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { exitProcess } from '../../utils/processExit.js';
|
|
5
|
+
const chalk = new Chalk();
|
|
6
|
+
/** Sentinel for logs picker: stream all services. */
|
|
7
|
+
export const ALL_SERVICES_LOGS_VALUE = '__all__';
|
|
8
|
+
export function listComposeServiceNames(composeFile) {
|
|
9
|
+
const out = execSync(`docker compose -f "${composeFile}" config --services`, {
|
|
10
|
+
encoding: 'utf8'
|
|
11
|
+
})
|
|
12
|
+
.trim()
|
|
13
|
+
.split('\n')
|
|
14
|
+
.map((s) => s.trim())
|
|
15
|
+
.filter(Boolean);
|
|
16
|
+
return [...new Set(out)].sort((a, b) => a.localeCompare(b));
|
|
17
|
+
}
|
|
18
|
+
export async function promptComposeServiceForLogs(composeFile) {
|
|
19
|
+
const services = listComposeServiceNames(composeFile);
|
|
20
|
+
if (services.length === 0) {
|
|
21
|
+
console.error(chalk.red('No services found in the compose file.'));
|
|
22
|
+
exitProcess(1);
|
|
23
|
+
}
|
|
24
|
+
console.log(chalk.blue(`Compose services (${composeFile}):`));
|
|
25
|
+
const { selected } = await inquirer.prompt([
|
|
26
|
+
{
|
|
27
|
+
type: 'list',
|
|
28
|
+
name: 'selected',
|
|
29
|
+
message: 'Select service for logs',
|
|
30
|
+
choices: [
|
|
31
|
+
{ name: 'All services', value: ALL_SERVICES_LOGS_VALUE },
|
|
32
|
+
...services.map((s) => ({ name: s, value: s }))
|
|
33
|
+
],
|
|
34
|
+
pageSize: Math.min(20, Math.max(10, services.length + 1))
|
|
35
|
+
}
|
|
36
|
+
]);
|
|
37
|
+
return selected === ALL_SERVICES_LOGS_VALUE ? undefined : selected;
|
|
38
|
+
}
|
|
39
|
+
export async function promptComposeServiceForRestart(composeFile) {
|
|
40
|
+
const services = listComposeServiceNames(composeFile);
|
|
41
|
+
if (services.length === 0) {
|
|
42
|
+
console.error(chalk.red('No services found in the compose file.'));
|
|
43
|
+
exitProcess(1);
|
|
44
|
+
}
|
|
45
|
+
console.log(chalk.blue(`Compose services (${composeFile}):`));
|
|
46
|
+
const { selected } = await inquirer.prompt([
|
|
47
|
+
{
|
|
48
|
+
type: 'checkbox',
|
|
49
|
+
name: 'selected',
|
|
50
|
+
message: 'Select service(s) to restart (space to toggle, enter to confirm)',
|
|
51
|
+
choices: services.map((s) => ({ name: s, value: s })),
|
|
52
|
+
pageSize: Math.min(20, Math.max(10, services.length)),
|
|
53
|
+
validate: (answer) => answer.length > 0 ? true : 'Select at least one service'
|
|
54
|
+
}
|
|
55
|
+
]);
|
|
56
|
+
return selected;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=composeServices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composeServices.js","sourceRoot":"","sources":["../../../../src/commands/docker/composeServices.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
2
|
import { dockerBackup } from './backup.js';
|
|
3
3
|
import { dockerList } from './list.js';
|
|
4
|
+
import { dockerLogs } from './logs.js';
|
|
4
5
|
import { dockerRestart } from './restart.js';
|
|
6
|
+
import { dockerRestore } from './restore.js';
|
|
5
7
|
import { dockerUpdate } from './update.js';
|
|
6
|
-
export { dockerBackup, dockerList, dockerRestart, dockerUpdate };
|
|
8
|
+
export { dockerBackup, dockerList, dockerLogs, dockerRestart, dockerRestore, dockerUpdate };
|
|
7
9
|
/**
|
|
8
10
|
* Registers `docker` subcommands on the given Commander program.
|
|
9
11
|
* @param program Commander root or parent command.
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { dockerBackup } from './backup.js';
|
|
2
2
|
import { dockerList } from './list.js';
|
|
3
|
+
import { dockerLogs } from './logs.js';
|
|
3
4
|
import { dockerRestart } from './restart.js';
|
|
5
|
+
import { dockerRestore } from './restore.js';
|
|
4
6
|
import { dockerUpdate } from './update.js';
|
|
5
|
-
export { dockerBackup, dockerList, dockerRestart, dockerUpdate };
|
|
7
|
+
export { dockerBackup, dockerList, dockerLogs, dockerRestart, dockerRestore, dockerUpdate };
|
|
6
8
|
/**
|
|
7
9
|
* Registers `docker` subcommands on the given Commander program.
|
|
8
10
|
* @param program Commander root or parent command.
|
|
@@ -38,14 +40,48 @@ export function registerDockerCommands(program) {
|
|
|
38
40
|
}));
|
|
39
41
|
docker
|
|
40
42
|
.command('restart')
|
|
41
|
-
.description('Restart
|
|
42
|
-
.
|
|
43
|
+
.description('Restart service(s) (interactive multi-select if no -s)')
|
|
44
|
+
.option('-s, --service <names...>', 'Service(s) to restart, e.g. -s api worker (skips interactive picker)')
|
|
43
45
|
.option('-f, --file <path>', 'Path to compose file (default: ./compose.yaml)')
|
|
44
|
-
.action((opts) =>
|
|
46
|
+
.action((opts) => {
|
|
47
|
+
const raw = opts.service;
|
|
48
|
+
const services = raw === undefined ? undefined : Array.isArray(raw) ? raw : [raw];
|
|
49
|
+
return dockerRestart({ file: opts.file, services });
|
|
50
|
+
});
|
|
45
51
|
docker
|
|
46
52
|
.command('list')
|
|
47
53
|
.description('List containers (docker compose ps)')
|
|
48
54
|
.option('-f, --file <path>', 'Path to compose file (default: ./compose.yaml)')
|
|
49
55
|
.action((opts) => dockerList(opts));
|
|
56
|
+
docker
|
|
57
|
+
.command('logs')
|
|
58
|
+
.description('Stream or print container logs (docker compose logs)')
|
|
59
|
+
.option('-f, --file <path>', 'Path to compose file (default: ./compose.yaml)')
|
|
60
|
+
.option('--follow', 'Follow log output')
|
|
61
|
+
.option('-n, --tail <n>', 'Number of lines to show from the end of the logs')
|
|
62
|
+
.option('-s, --service <name>', 'Service name (skips interactive picker)')
|
|
63
|
+
.option('--all', 'All services without prompting (skip the picker)')
|
|
64
|
+
.action((opts) => {
|
|
65
|
+
const tailNum = opts.tail !== undefined ? parseInt(opts.tail, 10) : undefined;
|
|
66
|
+
const tail = tailNum !== undefined && Number.isFinite(tailNum) && tailNum > 0 ? tailNum : undefined;
|
|
67
|
+
return dockerLogs({
|
|
68
|
+
file: opts.file,
|
|
69
|
+
follow: opts.follow,
|
|
70
|
+
tail,
|
|
71
|
+
service: opts.service,
|
|
72
|
+
allServices: opts.all === true
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
docker
|
|
76
|
+
.command('restore')
|
|
77
|
+
.description('Restore stack from a backup compose file (interactive list, or pass a path)')
|
|
78
|
+
.argument('[backup]', 'Path to backup compose file (optional)')
|
|
79
|
+
.option('-d, --dir <path>', 'Directory to scan for backups (default: ./docker_image_backups)')
|
|
80
|
+
.option('--force', 'Skip confirmation before restore')
|
|
81
|
+
.action((backup, opts) => dockerRestore({
|
|
82
|
+
backupCompose: backup,
|
|
83
|
+
backupDir: opts.dir,
|
|
84
|
+
force: opts.force
|
|
85
|
+
}));
|
|
50
86
|
}
|
|
51
87
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/docker/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/docker/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface DockerLogsOptions {
|
|
2
|
+
file?: string;
|
|
3
|
+
/** Follow log output (docker compose logs -f). */
|
|
4
|
+
follow?: boolean;
|
|
5
|
+
/** Number of lines from the end (docker compose logs --tail). */
|
|
6
|
+
tail?: number;
|
|
7
|
+
/** Compose service name; skips the picker when set. */
|
|
8
|
+
service?: string;
|
|
9
|
+
/**
|
|
10
|
+
* When true, show logs for all services without prompting.
|
|
11
|
+
* Use when `service` is omitted and you do not want the interactive picker.
|
|
12
|
+
*/
|
|
13
|
+
allServices?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Streams or prints logs from the compose stack (docker compose logs).
|
|
17
|
+
* With no service and without allServices, prompts for a service (or all).
|
|
18
|
+
* @param options Logs options.
|
|
19
|
+
*/
|
|
20
|
+
export declare function dockerLogs(options?: DockerLogsOptions): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { resolveComposeFile } from '../../utils/resolveComposeFile.js';
|
|
3
|
+
import { promptComposeServiceForLogs } from './composeServices.js';
|
|
4
|
+
/**
|
|
5
|
+
* Streams or prints logs from the compose stack (docker compose logs).
|
|
6
|
+
* With no service and without allServices, prompts for a service (or all).
|
|
7
|
+
* @param options Logs options.
|
|
8
|
+
*/
|
|
9
|
+
export async function dockerLogs(options = {}) {
|
|
10
|
+
const composeFile = resolveComposeFile(options.file);
|
|
11
|
+
const { follow, tail, allServices } = options;
|
|
12
|
+
let service = options.service;
|
|
13
|
+
if (!service && !allServices) {
|
|
14
|
+
service = await promptComposeServiceForLogs(composeFile);
|
|
15
|
+
}
|
|
16
|
+
const parts = [`docker compose -f "${composeFile}" logs`];
|
|
17
|
+
if (tail != null && tail > 0) {
|
|
18
|
+
parts.push(`--tail ${Math.floor(tail)}`);
|
|
19
|
+
}
|
|
20
|
+
if (follow) {
|
|
21
|
+
parts.push('-f');
|
|
22
|
+
}
|
|
23
|
+
if (service) {
|
|
24
|
+
parts.push(`"${service}"`);
|
|
25
|
+
}
|
|
26
|
+
execSync(parts.join(' '), { stdio: 'inherit' });
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../../src/commands/docker/logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAiBnE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAA6B,EAAE;IAC9D,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAE9C,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAE9B,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7B,OAAO,GAAG,MAAM,2BAA2B,CAAC,WAAW,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,sBAAsB,WAAW,QAAQ,CAAC,CAAC;IAC1D,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export interface DockerRestartOptions {
|
|
2
2
|
file?: string;
|
|
3
|
-
service
|
|
3
|
+
/** One service (skips picker); merged with `services` if both are set. */
|
|
4
|
+
service?: string;
|
|
5
|
+
/** One or more services (skips picker when non-empty). */
|
|
6
|
+
services?: string[];
|
|
4
7
|
}
|
|
5
8
|
/**
|
|
6
|
-
* Restarts
|
|
9
|
+
* Restarts container(s) in the compose stack.
|
|
10
|
+
* With no explicit services, prompts for one or more (checkbox).
|
|
7
11
|
* @param options Restart options.
|
|
8
|
-
* @param [options.file] Path to compose file (default ./compose.yaml).
|
|
9
|
-
* @param options.service Service name to restart.
|
|
10
12
|
*/
|
|
11
|
-
export declare function dockerRestart(options
|
|
13
|
+
export declare function dockerRestart(options?: DockerRestartOptions): Promise<void>;
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import { execSync } from 'child_process';
|
|
2
2
|
import { resolveComposeFile } from '../../utils/resolveComposeFile.js';
|
|
3
|
+
import { promptComposeServiceForRestart } from './composeServices.js';
|
|
4
|
+
function resolveExplicitServices(options) {
|
|
5
|
+
const merged = [...(options.services ?? []), ...(options.service ? [options.service] : [])];
|
|
6
|
+
const uniq = [...new Set(merged.map((s) => s.trim()).filter(Boolean))];
|
|
7
|
+
return uniq.length > 0 ? uniq : undefined;
|
|
8
|
+
}
|
|
9
|
+
function quoteServiceArg(name) {
|
|
10
|
+
return `"${name.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
11
|
+
}
|
|
3
12
|
/**
|
|
4
|
-
* Restarts
|
|
13
|
+
* Restarts container(s) in the compose stack.
|
|
14
|
+
* With no explicit services, prompts for one or more (checkbox).
|
|
5
15
|
* @param options Restart options.
|
|
6
|
-
* @param [options.file] Path to compose file (default ./compose.yaml).
|
|
7
|
-
* @param options.service Service name to restart.
|
|
8
16
|
*/
|
|
9
|
-
export async function dockerRestart(options) {
|
|
17
|
+
export async function dockerRestart(options = {}) {
|
|
10
18
|
const composeFile = resolveComposeFile(options.file);
|
|
11
|
-
|
|
12
|
-
|
|
19
|
+
let services = resolveExplicitServices(options);
|
|
20
|
+
if (!services?.length) {
|
|
21
|
+
services = await promptComposeServiceForRestart(composeFile);
|
|
22
|
+
}
|
|
23
|
+
const restartArgs = services.map(quoteServiceArg).join(' ');
|
|
24
|
+
execSync(`docker compose -f "${composeFile}" restart ${restartArgs}`, {
|
|
13
25
|
stdio: 'inherit'
|
|
14
26
|
});
|
|
15
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restart.js","sourceRoot":"","sources":["../../../../src/commands/docker/restart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"restart.js","sourceRoot":"","sources":["../../../../src/commands/docker/restart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AAUtE,SAAS,uBAAuB,CAAC,OAA6B;IAC5D,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5F,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACvE,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5C,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;AACjE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAgC,EAAE;IACpE,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAErD,IAAI,QAAQ,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAEhD,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QACtB,QAAQ,GAAG,MAAM,8BAA8B,CAAC,WAAW,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5D,QAAQ,CAAC,sBAAsB,WAAW,aAAa,WAAW,EAAE,EAAE;QACpE,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface DockerRestoreOptions {
|
|
2
|
+
/** Explicit backup compose file (skips interactive list). */
|
|
3
|
+
backupCompose?: string;
|
|
4
|
+
/** Directory to scan for docker-compose_*.yaml (default: ./docker_image_backups). */
|
|
5
|
+
backupDir?: string;
|
|
6
|
+
/** Skip confirmation before down/pull/up. */
|
|
7
|
+
force?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Restores the stack from a backup compose file produced by docker backup.
|
|
11
|
+
* With no backup path, lists backups under the backup dir and prompts for one.
|
|
12
|
+
*/
|
|
13
|
+
export declare function dockerRestore(options?: DockerRestoreOptions): Promise<void>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { existsSync, readdirSync, statSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { Chalk } from 'chalk';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import { exitProcess } from '../../utils/processExit.js';
|
|
6
|
+
import { DOCKER_IMAGE_BACKUP_DIR } from './backup.js';
|
|
7
|
+
import { dockerUpdate } from './update.js';
|
|
8
|
+
const chalk = new Chalk();
|
|
9
|
+
const BACKUP_FILE_PREFIX = 'docker-compose_';
|
|
10
|
+
const BACKUP_FILE_SUFFIX = '.yaml';
|
|
11
|
+
function listBackupComposeFiles(backupDir) {
|
|
12
|
+
if (!existsSync(backupDir)) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
const entries = readdirSync(backupDir)
|
|
16
|
+
.filter((name) => name.startsWith(BACKUP_FILE_PREFIX) && name.endsWith(BACKUP_FILE_SUFFIX))
|
|
17
|
+
.map((name) => {
|
|
18
|
+
const fullPath = join(backupDir, name);
|
|
19
|
+
const mtimeMs = statSync(fullPath).mtimeMs;
|
|
20
|
+
const stampMatch = name.slice(BACKUP_FILE_PREFIX.length, -BACKUP_FILE_SUFFIX.length);
|
|
21
|
+
const date = new Date(mtimeMs);
|
|
22
|
+
const label = `${date.toLocaleString()} ${stampMatch}`;
|
|
23
|
+
return { path: fullPath, label, mtimeMs };
|
|
24
|
+
})
|
|
25
|
+
.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
26
|
+
return entries.map(({ path, label }) => ({ path, label }));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Restores the stack from a backup compose file produced by docker backup.
|
|
30
|
+
* With no backup path, lists backups under the backup dir and prompts for one.
|
|
31
|
+
*/
|
|
32
|
+
export async function dockerRestore(options = {}) {
|
|
33
|
+
const backupDir = options.backupDir ?? DOCKER_IMAGE_BACKUP_DIR;
|
|
34
|
+
let backupFile = options.backupCompose;
|
|
35
|
+
if (!backupFile) {
|
|
36
|
+
const choices = listBackupComposeFiles(backupDir);
|
|
37
|
+
if (choices.length === 0) {
|
|
38
|
+
console.error(chalk.red(`No backup compose files found in ${backupDir} (expected ${BACKUP_FILE_PREFIX}*${BACKUP_FILE_SUFFIX}). Run docker backup first.`));
|
|
39
|
+
exitProcess(1);
|
|
40
|
+
}
|
|
41
|
+
console.log(chalk.blue(`Backups in ${backupDir} (newest first):`));
|
|
42
|
+
const { selected } = await inquirer.prompt([
|
|
43
|
+
{
|
|
44
|
+
type: 'list',
|
|
45
|
+
name: 'selected',
|
|
46
|
+
message: 'Select backup to restore',
|
|
47
|
+
choices: choices.map((c) => ({ name: c.label, value: c.path })),
|
|
48
|
+
pageSize: Math.min(20, Math.max(10, choices.length))
|
|
49
|
+
}
|
|
50
|
+
]);
|
|
51
|
+
backupFile = selected;
|
|
52
|
+
}
|
|
53
|
+
if (!existsSync(backupFile)) {
|
|
54
|
+
console.error(chalk.red(`Error: Backup compose file not found at ${backupFile}`));
|
|
55
|
+
exitProcess(1);
|
|
56
|
+
}
|
|
57
|
+
await dockerUpdate({
|
|
58
|
+
backupFile,
|
|
59
|
+
force: options.force,
|
|
60
|
+
noBackup: true
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=restore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore.js","sourceRoot":"","sources":["../../../../src/commands/docker/restore.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
2
|
export { dbEnd, dbExport, dbImport, dbList, dbRestore } from './db/index.js';
|
|
3
|
-
export { dockerBackup, dockerList, dockerRestart, dockerUpdate } from './docker/index.js';
|
|
3
|
+
export { dockerBackup, dockerList, dockerLogs, dockerRestart, dockerRestore, dockerUpdate } from './docker/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Registers all foundation-utils CLI commands on the given Commander program.
|
|
6
6
|
* @param program Commander program instance.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { registerDbCommands } from './db/index.js';
|
|
2
2
|
import { registerDockerCommands } from './docker/index.js';
|
|
3
3
|
export { dbEnd, dbExport, dbImport, dbList, dbRestore } from './db/index.js';
|
|
4
|
-
export { dockerBackup, dockerList, dockerRestart, dockerUpdate } from './docker/index.js';
|
|
4
|
+
export { dockerBackup, dockerList, dockerLogs, dockerRestart, dockerRestore, dockerUpdate } from './docker/index.js';
|
|
5
5
|
/**
|
|
6
6
|
* Registers all foundation-utils CLI commands on the given Commander program.
|
|
7
7
|
* @param program Commander program instance.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE7E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE7E,OAAO,EACL,YAAY,EACZ,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { registerCommands, dbEnd, dbExport, dbImport, dbList, dbRestore, dockerBackup, dockerList, dockerRestart, dockerUpdate } from './commands/index.js';
|
|
1
|
+
export { registerCommands, dbEnd, dbExport, dbImport, dbList, dbRestore, dockerBackup, dockerList, dockerLogs, dockerRestart, dockerRestore, dockerUpdate } from './commands/index.js';
|
package/dist/src/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { registerCommands, dbEnd, dbExport, dbImport, dbList, dbRestore, dockerBackup, dockerList, dockerRestart, dockerUpdate } from './commands/index.js';
|
|
1
|
+
export { registerCommands, dbEnd, dbExport, dbImport, dbList, dbRestore, dockerBackup, dockerList, dockerLogs, dockerRestart, dockerRestore, dockerUpdate } from './commands/index.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,SAAS,EACT,YAAY,EACZ,UAAU,EACV,aAAa,EACb,YAAY,EACb,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,YAAY,EACb,MAAM,qBAAqB,CAAC"}
|