n8n-nodes-docker-api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +278 -0
  3. package/dist/credentials/DockerApi.credentials.d.ts +7 -0
  4. package/dist/credentials/DockerApi.credentials.js +125 -0
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.js +5 -0
  7. package/dist/nodes/Docker/Docker/docker.svg +25 -0
  8. package/dist/nodes/Docker/Docker.node.d.ts +5 -0
  9. package/dist/nodes/Docker/Docker.node.js +73 -0
  10. package/dist/nodes/Docker/actions/container/getLogs.operation.d.ts +3 -0
  11. package/dist/nodes/Docker/actions/container/getLogs.operation.js +82 -0
  12. package/dist/nodes/Docker/actions/container/list.operation.d.ts +3 -0
  13. package/dist/nodes/Docker/actions/container/list.operation.js +40 -0
  14. package/dist/nodes/Docker/actions/container/start.operation.d.ts +3 -0
  15. package/dist/nodes/Docker/actions/container/start.operation.js +21 -0
  16. package/dist/nodes/Docker/actions/container/stop.operation.d.ts +3 -0
  17. package/dist/nodes/Docker/actions/container/stop.operation.js +38 -0
  18. package/dist/nodes/Docker/actions/index.d.ts +3 -0
  19. package/dist/nodes/Docker/actions/index.js +25 -0
  20. package/dist/nodes/Docker/descriptions/container/getLogs.description.d.ts +2 -0
  21. package/dist/nodes/Docker/descriptions/container/getLogs.description.js +64 -0
  22. package/dist/nodes/Docker/descriptions/container/list.description.d.ts +2 -0
  23. package/dist/nodes/Docker/descriptions/container/list.description.js +66 -0
  24. package/dist/nodes/Docker/descriptions/container/start.description.d.ts +2 -0
  25. package/dist/nodes/Docker/descriptions/container/start.description.js +20 -0
  26. package/dist/nodes/Docker/descriptions/container/stop.description.d.ts +2 -0
  27. package/dist/nodes/Docker/descriptions/container/stop.description.js +46 -0
  28. package/dist/nodes/Docker/descriptions/index.d.ts +3 -0
  29. package/dist/nodes/Docker/descriptions/index.js +53 -0
  30. package/dist/nodes/Docker/helpers/accessGuard.d.ts +2 -0
  31. package/dist/nodes/Docker/helpers/accessGuard.js +13 -0
  32. package/dist/nodes/Docker/helpers/errorHandler.d.ts +1 -0
  33. package/dist/nodes/Docker/helpers/errorHandler.js +36 -0
  34. package/dist/nodes/Docker/helpers/normalizeContainer.d.ts +16 -0
  35. package/dist/nodes/Docker/helpers/normalizeContainer.js +71 -0
  36. package/dist/nodes/Docker/helpers/resolveContainer.d.ts +11 -0
  37. package/dist/nodes/Docker/helpers/resolveContainer.js +32 -0
  38. package/dist/utils/dockerClient.d.ts +3 -0
  39. package/dist/utils/dockerClient.js +31 -0
  40. package/package.json +69 -0
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startContainer = startContainer;
4
+ const errorHandler_1 = require("../../helpers/errorHandler");
5
+ const normalizeContainer_1 = require("../../helpers/normalizeContainer");
6
+ const resolveContainer_1 = require("../../helpers/resolveContainer");
7
+ async function startContainer(docker, itemIndex) {
8
+ try {
9
+ const containerId = this.getNodeParameter('containerId', itemIndex);
10
+ // Resolve name to ID first
11
+ const resolved = await (0, resolveContainer_1.resolveContainer)(docker, containerId);
12
+ const container = docker.getContainer(resolved.id);
13
+ await container.start();
14
+ // Get updated info using the same container instance
15
+ const containerInfo = await container.inspect();
16
+ return (0, normalizeContainer_1.normalizeContainerInfo)(containerInfo);
17
+ }
18
+ catch (error) {
19
+ throw new Error((0, errorHandler_1.translateDockerError)(error));
20
+ }
21
+ }
@@ -0,0 +1,3 @@
1
+ import Docker from 'dockerode';
2
+ import { IExecuteFunctions } from 'n8n-workflow';
3
+ export declare function stopContainer(this: IExecuteFunctions, docker: Docker, itemIndex: number): Promise<any>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stopContainer = stopContainer;
4
+ const errorHandler_1 = require("../../helpers/errorHandler");
5
+ const normalizeContainer_1 = require("../../helpers/normalizeContainer");
6
+ const resolveContainer_1 = require("../../helpers/resolveContainer");
7
+ async function stopContainer(docker, itemIndex) {
8
+ try {
9
+ const containerId = this.getNodeParameter('containerId', itemIndex);
10
+ const timeout = this.getNodeParameter('timeout', itemIndex, 10);
11
+ const dryRun = this.getNodeParameter('dryRun', itemIndex, false);
12
+ // Resolve name to ID first
13
+ const resolved = await (0, resolveContainer_1.resolveContainer)(docker, containerId);
14
+ const container = docker.getContainer(resolved.id);
15
+ // Handle dry run
16
+ if (dryRun) {
17
+ return {
18
+ dryRun: true,
19
+ action: 'stop',
20
+ target: {
21
+ id: resolved.id,
22
+ shortId: resolved.id.substring(0, 12),
23
+ name: resolved.name,
24
+ },
25
+ executed: false,
26
+ message: `Dry run: container '${resolved.name}' (${resolved.id.substring(0, 12)}) would have been stopped.`,
27
+ };
28
+ }
29
+ // Actually stop the container
30
+ await container.stop({ t: timeout });
31
+ // Get updated info using the same container instance
32
+ const containerInfo = await container.inspect();
33
+ return (0, normalizeContainer_1.normalizeContainerInfo)(containerInfo);
34
+ }
35
+ catch (error) {
36
+ throw new Error((0, errorHandler_1.translateDockerError)(error));
37
+ }
38
+ }
@@ -0,0 +1,3 @@
1
+ import Docker from 'dockerode';
2
+ import { IExecuteFunctions } from 'n8n-workflow';
3
+ export declare function executeContainerOperation(this: IExecuteFunctions, docker: Docker, operation: string, itemIndex: number): Promise<any[]>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeContainerOperation = executeContainerOperation;
4
+ const list_operation_1 = require("./container/list.operation");
5
+ const getLogs_operation_1 = require("./container/getLogs.operation");
6
+ const start_operation_1 = require("./container/start.operation");
7
+ const stop_operation_1 = require("./container/stop.operation");
8
+ async function executeContainerOperation(docker, operation, itemIndex) {
9
+ switch (operation) {
10
+ case 'list':
11
+ const listResult = await list_operation_1.listContainers.call(this, docker, itemIndex);
12
+ return listResult.map((item) => ({ json: item }));
13
+ case 'getLogs':
14
+ const logsResult = await getLogs_operation_1.getContainerLogs.call(this, docker, itemIndex);
15
+ return [{ json: logsResult }];
16
+ case 'start':
17
+ const startResult = await start_operation_1.startContainer.call(this, docker, itemIndex);
18
+ return [{ json: startResult }];
19
+ case 'stop':
20
+ const stopResult = await stop_operation_1.stopContainer.call(this, docker, itemIndex);
21
+ return [{ json: stopResult }];
22
+ default:
23
+ throw new Error(`Unknown operation: ${operation}`);
24
+ }
25
+ }
@@ -0,0 +1,2 @@
1
+ import { INodeProperties } from 'n8n-workflow';
2
+ export declare const getLogsContainerFields: INodeProperties[];
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLogsContainerFields = void 0;
4
+ exports.getLogsContainerFields = [
5
+ {
6
+ displayName: 'Container ID or Name',
7
+ name: 'containerId',
8
+ type: 'string',
9
+ required: true,
10
+ displayOptions: {
11
+ show: {
12
+ resource: ['container'],
13
+ operation: ['getLogs'],
14
+ },
15
+ },
16
+ default: '',
17
+ description: 'The ID or name of the container to retrieve logs from',
18
+ placeholder: 'my-container or abc123def456',
19
+ },
20
+ {
21
+ displayName: 'Tail (Lines)',
22
+ name: 'tail',
23
+ type: 'number',
24
+ displayOptions: {
25
+ show: {
26
+ resource: ['container'],
27
+ operation: ['getLogs'],
28
+ },
29
+ },
30
+ default: 100,
31
+ description: 'Number of lines from the end of the log to return. Use 0 for all lines.',
32
+ },
33
+ {
34
+ displayName: 'Include Timestamps',
35
+ name: 'timestamps',
36
+ type: 'boolean',
37
+ displayOptions: {
38
+ show: {
39
+ resource: ['container'],
40
+ operation: ['getLogs'],
41
+ },
42
+ },
43
+ default: false,
44
+ description: 'Whether to prepend timestamps to each log line',
45
+ },
46
+ {
47
+ displayName: 'Stream',
48
+ name: 'stream',
49
+ type: 'options',
50
+ displayOptions: {
51
+ show: {
52
+ resource: ['container'],
53
+ operation: ['getLogs'],
54
+ },
55
+ },
56
+ options: [
57
+ { name: 'Both (stdout + stderr)', value: 'both' },
58
+ { name: 'stdout Only', value: 'stdout' },
59
+ { name: 'stderr Only', value: 'stderr' },
60
+ ],
61
+ default: 'both',
62
+ description: 'Which output stream(s) to include in the logs',
63
+ },
64
+ ];
@@ -0,0 +1,2 @@
1
+ import { INodeProperties } from 'n8n-workflow';
2
+ export declare const listContainerFields: INodeProperties[];
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listContainerFields = void 0;
4
+ exports.listContainerFields = [
5
+ {
6
+ displayName: 'Show All Containers',
7
+ name: 'showAll',
8
+ type: 'boolean',
9
+ displayOptions: {
10
+ show: {
11
+ resource: ['container'],
12
+ operation: ['list'],
13
+ },
14
+ },
15
+ default: false,
16
+ description: 'Whether to show stopped and exited containers in addition to running ones',
17
+ },
18
+ {
19
+ displayName: 'Filters',
20
+ name: 'filters',
21
+ type: 'collection',
22
+ placeholder: 'Add Filter',
23
+ default: {},
24
+ displayOptions: {
25
+ show: {
26
+ resource: ['container'],
27
+ operation: ['list'],
28
+ },
29
+ },
30
+ options: [
31
+ {
32
+ displayName: 'Name',
33
+ name: 'name',
34
+ type: 'string',
35
+ default: '',
36
+ description: 'Filter containers by name (partial match supported)',
37
+ },
38
+ {
39
+ displayName: 'Status',
40
+ name: 'status',
41
+ type: 'options',
42
+ options: [
43
+ { name: 'All', value: '' },
44
+ { name: 'Running', value: 'running' },
45
+ { name: 'Exited', value: 'exited' },
46
+ { name: 'Paused', value: 'paused' },
47
+ ],
48
+ default: '',
49
+ description: 'Filter containers by status',
50
+ },
51
+ ],
52
+ },
53
+ {
54
+ displayName: 'Include Labels',
55
+ name: 'includeLabels',
56
+ type: 'boolean',
57
+ displayOptions: {
58
+ show: {
59
+ resource: ['container'],
60
+ operation: ['list'],
61
+ },
62
+ },
63
+ default: true,
64
+ description: 'Whether to include container labels in the output (can be verbose)',
65
+ },
66
+ ];
@@ -0,0 +1,2 @@
1
+ import { INodeProperties } from 'n8n-workflow';
2
+ export declare const startContainerFields: INodeProperties[];
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startContainerFields = void 0;
4
+ exports.startContainerFields = [
5
+ {
6
+ displayName: 'Container ID or Name',
7
+ name: 'containerId',
8
+ type: 'string',
9
+ required: true,
10
+ displayOptions: {
11
+ show: {
12
+ resource: ['container'],
13
+ operation: ['start'],
14
+ },
15
+ },
16
+ default: '',
17
+ description: 'The ID or name of the container to start',
18
+ placeholder: 'my-container or abc123def456',
19
+ },
20
+ ];
@@ -0,0 +1,2 @@
1
+ import { INodeProperties } from 'n8n-workflow';
2
+ export declare const stopContainerFields: INodeProperties[];
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stopContainerFields = void 0;
4
+ exports.stopContainerFields = [
5
+ {
6
+ displayName: 'Container ID or Name',
7
+ name: 'containerId',
8
+ type: 'string',
9
+ required: true,
10
+ displayOptions: {
11
+ show: {
12
+ resource: ['container'],
13
+ operation: ['stop'],
14
+ },
15
+ },
16
+ default: '',
17
+ description: 'The ID or name of the container to stop',
18
+ placeholder: 'my-container or abc123def456',
19
+ },
20
+ {
21
+ displayName: 'Timeout (Seconds)',
22
+ name: 'timeout',
23
+ type: 'number',
24
+ displayOptions: {
25
+ show: {
26
+ resource: ['container'],
27
+ operation: ['stop'],
28
+ },
29
+ },
30
+ default: 10,
31
+ description: 'Seconds to wait before force-killing the container. Default is 10.',
32
+ },
33
+ {
34
+ displayName: 'Dry Run',
35
+ name: 'dryRun',
36
+ type: 'boolean',
37
+ displayOptions: {
38
+ show: {
39
+ resource: ['container'],
40
+ operation: ['stop'],
41
+ },
42
+ },
43
+ default: false,
44
+ description: 'Whether to preview the action without executing it. No changes will be made.',
45
+ },
46
+ ];
@@ -0,0 +1,3 @@
1
+ import { INodeProperties } from 'n8n-workflow';
2
+ export declare const containerOperations: INodeProperties[];
3
+ export declare const containerFields: INodeProperties[];
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.containerFields = exports.containerOperations = void 0;
4
+ const list_description_1 = require("./container/list.description");
5
+ const getLogs_description_1 = require("./container/getLogs.description");
6
+ const start_description_1 = require("./container/start.description");
7
+ const stop_description_1 = require("./container/stop.description");
8
+ exports.containerOperations = [
9
+ {
10
+ displayName: 'Operation',
11
+ name: 'operation',
12
+ type: 'options',
13
+ noDataExpression: true,
14
+ displayOptions: {
15
+ show: {
16
+ resource: ['container'],
17
+ },
18
+ },
19
+ options: [
20
+ {
21
+ name: 'List Containers',
22
+ value: 'list',
23
+ description: 'List all containers',
24
+ action: 'List containers',
25
+ },
26
+ {
27
+ name: 'Get Container Logs',
28
+ value: 'getLogs',
29
+ description: 'Retrieve logs from a container',
30
+ action: 'Get container logs',
31
+ },
32
+ {
33
+ name: 'Start Container',
34
+ value: 'start',
35
+ description: 'Start a container',
36
+ action: 'Start container',
37
+ },
38
+ {
39
+ name: 'Stop Container',
40
+ value: 'stop',
41
+ description: 'Stop a container',
42
+ action: 'Stop container',
43
+ },
44
+ ],
45
+ default: 'list',
46
+ },
47
+ ];
48
+ exports.containerFields = [
49
+ ...list_description_1.listContainerFields,
50
+ ...getLogs_description_1.getLogsContainerFields,
51
+ ...start_description_1.startContainerFields,
52
+ ...stop_description_1.stopContainerFields,
53
+ ];
@@ -0,0 +1,2 @@
1
+ import { ICredentialDataDecryptedObject } from 'n8n-workflow';
2
+ export declare function enforceAccessMode(credentials: ICredentialDataDecryptedObject, operation: string): void;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.enforceAccessMode = enforceAccessMode;
4
+ // Operations that require full-control access
5
+ const WRITE_OPERATIONS = ['start', 'stop', 'remove', 'restart', 'run', 'pull', 'build', 'prune'];
6
+ function enforceAccessMode(credentials, operation) {
7
+ const accessMode = credentials.accessMode;
8
+ if (accessMode === 'readonly' && WRITE_OPERATIONS.includes(operation)) {
9
+ throw new Error(`Operation "${operation}" requires Full Control access. ` +
10
+ `This credential is configured as Read Only. ` +
11
+ `Update your Docker API credential to enable write operations.`);
12
+ }
13
+ }
@@ -0,0 +1 @@
1
+ export declare function translateDockerError(error: unknown): string;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.translateDockerError = translateDockerError;
4
+ function translateDockerError(error) {
5
+ var _a;
6
+ const msg = (_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : String(error);
7
+ if (msg.includes('ECONNREFUSED')) {
8
+ return 'Cannot connect to Docker daemon. Is Docker running? Check your connection settings.';
9
+ }
10
+ if (msg.includes('ENOENT') && msg.includes('docker.sock')) {
11
+ return 'Docker socket not found at the specified path. Verify the socket path in your credential.';
12
+ }
13
+ if (msg.toLowerCase().includes('permission denied')) {
14
+ return 'Permission denied accessing Docker socket. Ensure the n8n process has permission to access the socket.';
15
+ }
16
+ if (msg.includes('No such container') || msg.includes('not found')) {
17
+ return 'Container not found. Verify the container ID or name is correct and the container exists.';
18
+ }
19
+ if (msg.includes('is not running')) {
20
+ return 'Container is not running. Start the container before performing this operation.';
21
+ }
22
+ if (msg.includes('already started') || msg.includes('already running')) {
23
+ return 'Container is already running.';
24
+ }
25
+ if (msg.includes('404')) {
26
+ return 'Resource not found. The container or image may have been removed.';
27
+ }
28
+ if (msg.includes('409')) {
29
+ return 'Conflict: The container may already be in the requested state.';
30
+ }
31
+ if (msg.includes('timeout') || msg.includes('ETIMEDOUT')) {
32
+ return 'Connection timed out. Check network connectivity to the Docker host.';
33
+ }
34
+ // Fallback: return original message without prefix for cleaner output
35
+ return msg;
36
+ }
@@ -0,0 +1,16 @@
1
+ import { ContainerInfo, ContainerInspectInfo } from 'dockerode';
2
+ export interface NormalizedContainer {
3
+ id: string;
4
+ shortId: string;
5
+ name: string;
6
+ image: string;
7
+ status: 'running' | 'stopped' | 'exited' | 'paused' | 'restarting' | 'dead' | 'created' | 'unknown';
8
+ createdAt: string;
9
+ ports: Array<{
10
+ containerPort: number;
11
+ hostPort?: number;
12
+ protocol: string;
13
+ }>;
14
+ labels?: Record<string, string>;
15
+ }
16
+ export declare function normalizeContainerInfo(raw: ContainerInfo | ContainerInspectInfo, includeLabels?: boolean): NormalizedContainer;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeContainerInfo = normalizeContainerInfo;
4
+ function normalizeContainerInfo(raw, includeLabels = true) {
5
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
6
+ // Handle both ContainerInfo (from listContainers) and ContainerInspectInfo (from inspect)
7
+ const isInspectInfo = 'Name' in raw;
8
+ const name = isInspectInfo
9
+ ? raw.Name.replace(/^\//, '')
10
+ : (_c = (_b = (_a = raw.Names) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.replace(/^\//, '')) !== null && _c !== void 0 ? _c : 'unknown';
11
+ const dockerState = isInspectInfo
12
+ ? (_e = (_d = raw.State) === null || _d === void 0 ? void 0 : _d.Status) !== null && _e !== void 0 ? _e : 'unknown'
13
+ : (_f = raw.State) !== null && _f !== void 0 ? _f : 'unknown';
14
+ const status = mapStatus(dockerState);
15
+ // Handle ports - only available in ContainerInfo
16
+ const portsInfo = raw.Ports;
17
+ const seenPorts = new Set();
18
+ const uniquePorts = [];
19
+ if (portsInfo) {
20
+ for (const port of portsInfo) {
21
+ const key = `${port.PrivatePort}-${(_g = port.PublicPort) !== null && _g !== void 0 ? _g : 'none'}-${port.Type}`;
22
+ if (!seenPorts.has(key)) {
23
+ seenPorts.add(key);
24
+ uniquePorts.push({
25
+ containerPort: port.PrivatePort,
26
+ hostPort: port.PublicPort,
27
+ protocol: port.Type,
28
+ });
29
+ }
30
+ }
31
+ }
32
+ // Handle image
33
+ const image = isInspectInfo
34
+ ? (_j = (_h = raw.Config) === null || _h === void 0 ? void 0 : _h.Image) !== null && _j !== void 0 ? _j : 'unknown'
35
+ : (_k = raw.Image) !== null && _k !== void 0 ? _k : 'unknown';
36
+ // Handle created timestamp
37
+ const created = isInspectInfo
38
+ ? (_l = raw.Created) !== null && _l !== void 0 ? _l : new Date().toISOString()
39
+ : new Date(((_m = raw.Created) !== null && _m !== void 0 ? _m : 0) * 1000).toISOString();
40
+ // Handle labels - only include if requested
41
+ const labelsData = isInspectInfo
42
+ ? (_p = (_o = raw.Config) === null || _o === void 0 ? void 0 : _o.Labels) !== null && _p !== void 0 ? _p : {}
43
+ : (_q = raw.Labels) !== null && _q !== void 0 ? _q : {};
44
+ const result = {
45
+ id: raw.Id,
46
+ shortId: raw.Id.substring(0, 12),
47
+ name,
48
+ image,
49
+ status,
50
+ createdAt: created,
51
+ ports: uniquePorts,
52
+ };
53
+ // Only add labels field if includeLabels is true
54
+ if (includeLabels) {
55
+ result.labels = labelsData;
56
+ }
57
+ return result;
58
+ }
59
+ function mapStatus(dockerState) {
60
+ var _a;
61
+ const map = {
62
+ running: 'running',
63
+ exited: 'exited',
64
+ stopped: 'stopped',
65
+ paused: 'paused',
66
+ restarting: 'restarting',
67
+ dead: 'dead',
68
+ created: 'created',
69
+ };
70
+ return (_a = map[dockerState === null || dockerState === void 0 ? void 0 : dockerState.toLowerCase()]) !== null && _a !== void 0 ? _a : 'unknown';
71
+ }
@@ -0,0 +1,11 @@
1
+ import Docker from 'dockerode';
2
+ /**
3
+ * Resolves a container ID or name to a full container info object.
4
+ * Docker API requires exact ID or name (with leading /).
5
+ * This function handles user-friendly names by finding the matching container.
6
+ */
7
+ export declare function resolveContainer(docker: Docker, containerIdOrName: string): Promise<{
8
+ id: string;
9
+ name: string;
10
+ info: Docker.ContainerInfo;
11
+ }>;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveContainer = resolveContainer;
4
+ /**
5
+ * Resolves a container ID or name to a full container info object.
6
+ * Docker API requires exact ID or name (with leading /).
7
+ * This function handles user-friendly names by finding the matching container.
8
+ */
9
+ async function resolveContainer(docker, containerIdOrName) {
10
+ var _a, _b, _c;
11
+ const allContainers = await docker.listContainers({ all: true });
12
+ // Try exact match first (ID or name with /)
13
+ let containerInfo = allContainers.find((c) => {
14
+ var _a;
15
+ return c.Id === containerIdOrName ||
16
+ c.Id.startsWith(containerIdOrName) ||
17
+ ((_a = c.Names) === null || _a === void 0 ? void 0 : _a.some((n) => n === containerIdOrName || n === `/${containerIdOrName}`));
18
+ });
19
+ // If not found, try name without leading /
20
+ if (!containerInfo) {
21
+ containerInfo = allContainers.find((c) => { var _a; return (_a = c.Names) === null || _a === void 0 ? void 0 : _a.some((n) => n.replace(/^\//, '') === containerIdOrName); });
22
+ }
23
+ if (!containerInfo) {
24
+ throw new Error(`Container '${containerIdOrName}' not found. Verify the container ID or name is correct and the container exists.`);
25
+ }
26
+ const name = (_c = (_b = (_a = containerInfo.Names) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.replace(/^\//, '')) !== null && _c !== void 0 ? _c : 'unknown';
27
+ return {
28
+ id: containerInfo.Id,
29
+ name,
30
+ info: containerInfo,
31
+ };
32
+ }
@@ -0,0 +1,3 @@
1
+ import Docker from 'dockerode';
2
+ import { ICredentialDataDecryptedObject } from 'n8n-workflow';
3
+ export declare function createDockerClient(credentials: ICredentialDataDecryptedObject): Docker;
@@ -0,0 +1,31 @@
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.createDockerClient = createDockerClient;
7
+ const dockerode_1 = __importDefault(require("dockerode"));
8
+ function createDockerClient(credentials) {
9
+ const { authMode, socketPath, host, port, tlsPort, ca, cert, clientKey } = credentials;
10
+ if (authMode === 'socket') {
11
+ return new dockerode_1.default({ socketPath: socketPath });
12
+ }
13
+ if (authMode === 'tcp') {
14
+ return new dockerode_1.default({
15
+ host: host,
16
+ port: port,
17
+ protocol: 'http',
18
+ });
19
+ }
20
+ if (authMode === 'tls') {
21
+ return new dockerode_1.default({
22
+ host: host,
23
+ port: tlsPort,
24
+ ca: ca,
25
+ cert: cert,
26
+ key: clientKey,
27
+ protocol: 'https',
28
+ });
29
+ }
30
+ throw new Error(`Unknown authMode: ${authMode}`);
31
+ }