@cloud-cli/dx 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,22 @@
1
+ ## DX
2
+
3
+ Run Docker containers
4
+
5
+ ## Install
6
+
7
+ ```
8
+ npm i @cloud-cli/dx
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ cy dx.list
15
+ cy dx.status
16
+ cy dx.add --name node-app --image node --version latest --command 'node --version' --volumes 'volume:/container/path' --ports '1234:80'
17
+ cy dx.start --name node-app --env 'FOO=bar' --ports '1234:80'
18
+ cy dx.status --name node-app
19
+ cy dx.logs --name node-app
20
+ cy dx.stop --name node-app
21
+ cy dx.remove --name node-app
22
+ ```
@@ -0,0 +1,16 @@
1
+ export declare function getRunningContainers(): Promise<string[]>;
2
+ interface GetLogsOptions {
3
+ name: string;
4
+ lines?: string;
5
+ }
6
+ export declare function getLogs({ name, lines }: GetLogsOptions): Promise<string>;
7
+ interface RunOptions {
8
+ name: string;
9
+ env?: string[];
10
+ }
11
+ export declare function runContainer(options: RunOptions): Promise<boolean>;
12
+ export interface StopOptions {
13
+ name: string;
14
+ }
15
+ export declare function stopContainer(options: StopOptions): Promise<boolean>;
16
+ export {};
@@ -0,0 +1,50 @@
1
+ import { exec } from '@cloud-cli/exec';
2
+ import { findContainer } from './store.js';
3
+ export async function getRunningContainers() {
4
+ const ps = await exec('docker', ['ps', '--format', '{{.Names}}']);
5
+ if (!ps.ok) {
6
+ throw new Error('Failed to list containers: ' + ps.stderr);
7
+ }
8
+ return getListFromString(ps.stdout);
9
+ }
10
+ export async function getLogs({ name, lines }) {
11
+ if (!name) {
12
+ throw new Error('Name not specified');
13
+ }
14
+ const args = ['logs', name];
15
+ if (lines) {
16
+ args.push('-n', String(Number(lines)));
17
+ }
18
+ const sh = await exec('docker', args);
19
+ if (sh.ok) {
20
+ return sh.stdout;
21
+ }
22
+ return '';
23
+ }
24
+ const defaultRunOptions = { env: [] };
25
+ export async function runContainer(options) {
26
+ options = { ...defaultRunOptions, ...options };
27
+ const { name } = options;
28
+ if (!name) {
29
+ throw new Error('Name is required');
30
+ }
31
+ const container = await findContainer(name);
32
+ const env = options.env.flatMap((e) => ['-e', e]);
33
+ const volumes = container.volumes
34
+ .split(',')
35
+ .filter(Boolean)
36
+ .map((v) => `-v${v}`);
37
+ const ports = container.ports
38
+ .split(',')
39
+ .filter(Boolean)
40
+ .map((p) => `-p${p}`);
41
+ await exec('docker', ['run', '--rm', '--detach', '--name', name, ...volumes, ...ports, ...env, container.image]);
42
+ return true;
43
+ }
44
+ export async function stopContainer(options) {
45
+ await exec('docker', ['stop', '-t', '5', options.name]);
46
+ return true;
47
+ }
48
+ function getListFromString(string) {
49
+ return string.trim().split('\n').filter(Boolean);
50
+ }
@@ -0,0 +1,3 @@
1
+ export declare function pull(options: {
2
+ image: string;
3
+ }): Promise<boolean>;
package/dist/images.js ADDED
@@ -0,0 +1,11 @@
1
+ import { exec } from '@cloud-cli/exec';
2
+ export async function pull(options) {
3
+ return (await exec('docker', ['pull', options.image])).ok;
4
+ }
5
+ /*
6
+ async getImages(): Promise<string[]> {
7
+ const list = await this.shellExec('docker', ['image', 'ls', '--format', '{{.Repository}}']);
8
+
9
+ return list.filter((s: string) => s !== '<none>');
10
+ }
11
+ */
@@ -0,0 +1,19 @@
1
+ import { init } from '@cloud-cli/cli';
2
+ import { getRunningContainers, getLogs, runContainer, stopContainer } from './containers.js';
3
+ import { addContainer, removeContainer, listContainers, updateContainer } from './store.js';
4
+ import { pull } from './images.js';
5
+ declare function reload(): Promise<void>;
6
+ declare const _default: {
7
+ pull: typeof pull;
8
+ add: typeof addContainer;
9
+ remove: typeof removeContainer;
10
+ list: typeof listContainers;
11
+ update: typeof updateContainer;
12
+ run: typeof runContainer;
13
+ stop: typeof stopContainer;
14
+ ps: typeof getRunningContainers;
15
+ logs: typeof getLogs;
16
+ reload: typeof reload;
17
+ [init]: typeof reload;
18
+ };
19
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ import { init } from '@cloud-cli/cli';
2
+ import { Resource } from '@cloud-cli/store';
3
+ import { Container } from './store.js';
4
+ import { getRunningContainers, getLogs, runContainer, stopContainer } from './containers.js';
5
+ import { addContainer, removeContainer, listContainers, updateContainer } from './store.js';
6
+ import { pull } from './images.js';
7
+ async function reload() {
8
+ await Resource.create(Container);
9
+ }
10
+ export default {
11
+ pull,
12
+ add: addContainer,
13
+ remove: removeContainer,
14
+ list: listContainers,
15
+ update: updateContainer,
16
+ run: runContainer,
17
+ stop: stopContainer,
18
+ ps: getRunningContainers,
19
+ logs: getLogs,
20
+ reload,
21
+ [init]: reload
22
+ };
@@ -0,0 +1,26 @@
1
+ import { Resource } from '@cloud-cli/store';
2
+ export declare class Container extends Resource {
3
+ id: number;
4
+ name: string;
5
+ image: string;
6
+ ports: string;
7
+ volumes: string;
8
+ }
9
+ interface ContainerName {
10
+ name: string;
11
+ }
12
+ interface AddContainerOptions extends ContainerName {
13
+ image: string;
14
+ volumes?: string;
15
+ ports?: string;
16
+ }
17
+ export declare function addContainer(options: AddContainerOptions): Promise<Container>;
18
+ export declare function removeContainer(options: ContainerName): Promise<boolean>;
19
+ interface UpdateOptions extends ContainerName {
20
+ ports?: string;
21
+ volumes?: string;
22
+ }
23
+ export declare function updateContainer(options: UpdateOptions): Promise<Container>;
24
+ export declare function listContainers(): Promise<Container[]>;
25
+ export declare function findContainer(name: string): Promise<Container | null>;
26
+ export {};
package/dist/store.js ADDED
@@ -0,0 +1,79 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Model, Resource, Primary, NotNull, Property, Query } from '@cloud-cli/store';
8
+ let Container = class Container extends Resource {
9
+ };
10
+ __decorate([
11
+ Primary(),
12
+ NotNull(),
13
+ Property(Number)
14
+ ], Container.prototype, "id", void 0);
15
+ __decorate([
16
+ NotNull(),
17
+ Property(String)
18
+ ], Container.prototype, "name", void 0);
19
+ __decorate([
20
+ NotNull(),
21
+ Property(String)
22
+ ], Container.prototype, "image", void 0);
23
+ __decorate([
24
+ NotNull(),
25
+ Property(String)
26
+ ], Container.prototype, "ports", void 0);
27
+ __decorate([
28
+ NotNull(),
29
+ Property(String)
30
+ ], Container.prototype, "volumes", void 0);
31
+ Container = __decorate([
32
+ Model('container')
33
+ ], Container);
34
+ export { Container };
35
+ export async function addContainer(options) {
36
+ const { name, image } = options;
37
+ const volumes = (options.volumes ? sanitiseVolumes(options.volumes) : '');
38
+ const ports = (options.ports ? sanitisePorts(options.ports) : '');
39
+ const container = new Container({ name, image, volumes, ports });
40
+ const id = await container.save();
41
+ container.id = id;
42
+ return container;
43
+ }
44
+ export async function removeContainer(options) {
45
+ const found = await findContainer(options.name);
46
+ if (found) {
47
+ await found.remove();
48
+ return true;
49
+ }
50
+ throw new Error('Container not found: ' + options.name);
51
+ }
52
+ const optionSplitter = /,\s*/;
53
+ export async function updateContainer(options) {
54
+ let { ports, volumes, name } = options;
55
+ const container = await findContainer(name);
56
+ if (ports) {
57
+ container.ports = sanitisePorts(ports);
58
+ }
59
+ if (volumes) {
60
+ container.volumes = sanitiseVolumes(volumes);
61
+ }
62
+ await container.save();
63
+ return container;
64
+ }
65
+ export async function listContainers() {
66
+ return Resource.find(Container, new Query());
67
+ }
68
+ export async function findContainer(name) {
69
+ const found = await Resource.find(Container, new Query().where('name').is(name));
70
+ return found[0] || null;
71
+ }
72
+ const portTester = /^\d+:\d+$/;
73
+ function sanitisePorts(ports) {
74
+ return ports.split(optionSplitter).map(s => s.trim()).filter(s => portTester.test(s)).join(',');
75
+ }
76
+ const volumeTester = /^\S+:\S+$/;
77
+ function sanitiseVolumes(volumes) {
78
+ return volumes.split(optionSplitter).map(s => s.trim()).filter(s => volumeTester.test(s)).join(',');
79
+ }
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@cloud-cli/dx",
3
+ "version": "1.0.0",
4
+ "description": "Docker container management",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "type": "module",
8
+ "prettier": "@cloud-cli/prettier-config",
9
+ "scripts": {
10
+ "test": "jest",
11
+ "tdd": "jest --watch",
12
+ "build": "rm -rf ./dist/* && tsc"
13
+ },
14
+ "keywords": [
15
+ "cloudy"
16
+ ],
17
+ "license": "MIT",
18
+ "author": "Darlan Alves <me@darlanalv.es>",
19
+ "devDependencies": {
20
+ "@cloud-cli/jest-config": "^1.0.0",
21
+ "@cloud-cli/prettier-config": "^1.0.0",
22
+ "@cloud-cli/typescript-config": "^1.0.1",
23
+ "typescript": "^4.4.2"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/cloud-cli/dx.git"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "dependencies": {
33
+ "@cloud-cli/cli": "^1.4.4",
34
+ "@cloud-cli/exec": "^1.0.4",
35
+ "@cloud-cli/store": "^1.5.1"
36
+ }
37
+ }