the-moby-effect
Version:
Moby/Docker API client built using effect-ts
788 lines • 28.8 kB
JavaScript
import * as Context from "effect/Context";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Schema from "effect/Schema";
import * as Stream from "effect/Stream";
import * as String from "effect/String";
import * as HttpClient from "effect/unstable/http/HttpClient";
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";
import * as Url from "effect/unstable/http/Url";
import * as HttpApi from "effect/unstable/httpapi/HttpApi";
import * as HttpApiClient from "effect/unstable/httpapi/HttpApiClient";
import * as HttpApiEndpoint from "effect/unstable/httpapi/HttpApiEndpoint";
import * as HttpApiError from "effect/unstable/httpapi/HttpApiError";
import * as HttpApiGroup from "effect/unstable/httpapi/HttpApiGroup";
import * as HttpApiSchema from "effect/unstable/httpapi/HttpApiSchema";
import * as Socket from "effect/unstable/socket/Socket";
import { MobyConnectionOptions } from "../../MobyConnection.js";
import { makeAgnosticHttpClientLayer } from "../../MobyPlatforms.js";
import { responseToStreamingSocketOrFailUnsafe } from "../demux/hijack.js";
import { makeRawSocket } from "../demux/raw.js";
import { ArchiveChange, ContainerConfig, ContainerCreateRequest, ContainerHealth, ContainerHostConfig, ContainerInspectResponse, ContainerState, ContainerStatsResponse, ContainerSummary, ContainerTopResponse, ContainerWaitResponse } from "../generated/index.js";
import { replacer as quoteWireNumbers } from "../platforms/agnostic.js";
import { ContainerIdentifier } from "../schemas/id.js";
import { DockerError } from "./circular.js";
import { BadRequest, Conflict, Forbidden, InternalServerError, NotAcceptable, NotFound } from "./errors.js";
import { BooleanFilter, StringFilter } from "./filters.js";
/** @since 1.0.0 */
export const ListFilters = /*#__PURE__*/Schema.fromJsonString(/*#__PURE__*/Schema.Struct({
ancestor: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.String)),
before: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.String)),
expose: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.String)),
exited: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.NumberFromString)),
health: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(ContainerHealth.fields["Status"])),
identifier: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(ContainerIdentifier)),
// isolation: Schema.optional(Schema.Array(ContainerHostConfig.fields["Isolation"])),
"is-task": /*#__PURE__*/Schema.optional(/*#__PURE__*/BooleanFilter("is-task")),
label: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.String)),
name: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.String)),
network: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.String)),
publish: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.String)),
since: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.String)),
status: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(ContainerState.fields["Status"])),
volume: /*#__PURE__*/Schema.optional(StringFilter)
}));
/** @since 1.0.0 */
export const PruneFilters = /*#__PURE__*/Schema.fromJsonString(/*#__PURE__*/Schema.Struct({
until: /*#__PURE__*/Schema.optional(StringFilter),
label: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Array(Schema.String))
}));
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerList */
const listContainersEndpoint = /*#__PURE__*/HttpApiEndpoint.get("list", "/json", {
query: {
all: /*#__PURE__*/Schema.optional(Schema.Boolean),
limit: /*#__PURE__*/Schema.optional(Schema.Number),
size: /*#__PURE__*/Schema.optional(Schema.Boolean),
filters: /*#__PURE__*/Schema.optional(ListFilters)
},
success: /*#__PURE__*/Schema.Array(ContainerSummary),
// 200 OK
error: [BadRequest,
// 400 Bad parameter
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerCreate */
const createContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("create", "/create", {
query: {
platform: /*#__PURE__*/Schema.optional(Schema.String),
name: /*#__PURE__*/Schema.String.pipe(/*#__PURE__*/Schema.check(/*#__PURE__*/Schema.isPattern(/^[a-zA-Z0-9][a-zA-Z0-9_.-]+/)), Schema.optional)
},
payload: ContainerCreateRequest,
success: /*#__PURE__*/Schema.Struct({
Id: ContainerIdentifier,
Warnings: Schema.NullOr(Schema.Array(Schema.String))
}).pipe(/*#__PURE__*/HttpApiSchema.status(201)),
// 201 Created
error: [BadRequest,
// 400 Bad parameter
Forbidden,
// 403 Forbidden
NotFound,
// 404 Not Found
NotAcceptable,
// 406 Not Acceptable
Conflict,
// 409 Name conflicts
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerInspect */
const inspectContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.get("inspect", "/:identifier/json", {
params: {
identifier: ContainerIdentifier
},
query: {
size: /*#__PURE__*/Schema.optional(Schema.Boolean)
},
success: ContainerInspectResponse,
// 200 OK
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerTop */
const topContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.get("top", "/:identifier/top", {
params: {
identifier: ContainerIdentifier
},
query: {
ps_args: /*#__PURE__*/Schema.optional(Schema.String)
},
success: ContainerTopResponse,
// 200 OK
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerLogs */
const logsContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.get("logs", "/:identifier/logs", {
params: {
identifier: ContainerIdentifier
},
query: {
follow: /*#__PURE__*/Schema.optional(Schema.Boolean),
stdout: /*#__PURE__*/Schema.optional(Schema.Boolean),
stderr: /*#__PURE__*/Schema.optional(Schema.Boolean),
since: /*#__PURE__*/Schema.optional(Schema.Number),
until: /*#__PURE__*/Schema.optional(Schema.Number),
timestamps: /*#__PURE__*/Schema.optional(Schema.Boolean),
tail: /*#__PURE__*/Schema.optional(Schema.String)
},
success: /*#__PURE__*/HttpApiSchema.StreamUint8Array(),
// 200 OK (streaming response)
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerChanges */
const changesContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.get("changes", "/:identifier/changes", {
params: {
identifier: ContainerIdentifier
},
success: /*#__PURE__*/Schema.NullOr(/*#__PURE__*/Schema.Array(ArchiveChange)),
// 200 OK
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerExport */
const exportContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.get("export", "/:identifier/export", {
params: {
identifier: ContainerIdentifier
},
success: /*#__PURE__*/HttpApiSchema.StreamUint8Array(),
// 200 OK (streaming response)
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerStats */
const statsContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.get("stats", "/:identifier/stats", {
params: {
identifier: ContainerIdentifier
},
query: {
stream: /*#__PURE__*/Schema.optional(Schema.Boolean),
"one-shot": /*#__PURE__*/Schema.optional(Schema.Boolean)
},
success: /*#__PURE__*/HttpApiSchema.StreamUint8Array(),
// 200 OK (streaming response)
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerResize */
const resizeContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("resize", "/:identifier/resize", {
params: {
identifier: ContainerIdentifier
},
query: {
h: /*#__PURE__*/Schema.optional(Schema.Number),
w: /*#__PURE__*/Schema.optional(Schema.Number)
},
success: /*#__PURE__*/HttpApiSchema.Empty(200),
// 200 OK
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerStart */
const startContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("start", "/:identifier/start", {
params: {
identifier: ContainerIdentifier
},
query: {
detachKeys: /*#__PURE__*/Schema.optional(Schema.String)
},
success: [/*#__PURE__*/HttpApiSchema.Empty(204),
/*#__PURE__*/
// 204 No Content
HttpApiSchema.Empty(304) // 304 Container already started
],
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerStop */
const stopContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("stop", "/:identifier/stop", {
params: {
identifier: ContainerIdentifier
},
query: {
signal: /*#__PURE__*/Schema.optional(Schema.String),
t: /*#__PURE__*/Schema.optional(Schema.Number)
},
success: [/*#__PURE__*/HttpApiSchema.Empty(204),
/*#__PURE__*/
// 204 No Content
HttpApiSchema.Empty(304) // 304 Container already stopped
],
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerRestart */
const restartContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("restart", "/:identifier/restart", {
params: {
identifier: ContainerIdentifier
},
query: {
signal: /*#__PURE__*/Schema.optional(Schema.String),
t: /*#__PURE__*/Schema.optional(Schema.Number)
},
success: /*#__PURE__*/HttpApiSchema.Empty(204),
// 204 No Content
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerKill */
const killContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("kill", "/:identifier/kill", {
params: {
identifier: ContainerIdentifier
},
query: {
signal: /*#__PURE__*/Schema.optional(Schema.String)
},
success: /*#__PURE__*/HttpApiSchema.Empty(204),
// 204 No Content
error: [NotFound,
// 404 Not Found
Conflict,
// 409 Container is not running
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerUpdate */
const updateContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("update", "/:identifier/update", {
params: {
identifier: ContainerIdentifier
},
payload: ContainerConfig,
success: /*#__PURE__*/Schema.Struct({
Warnings: /*#__PURE__*/Schema.NullOr(/*#__PURE__*/Schema.Array(Schema.String))
}),
// 200 OK
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerRename */
const renameContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("rename", "/:identifier/rename", {
params: {
identifier: ContainerIdentifier
},
query: {
name: Schema.String
},
success: /*#__PURE__*/HttpApiSchema.Empty(204),
// 204 No Content
error: [NotFound,
// 404 Not Found
Conflict,
// 409 Name already in use
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerPause */
const pauseContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("pause", "/:identifier/pause", {
params: {
identifier: ContainerIdentifier
},
success: /*#__PURE__*/HttpApiSchema.Empty(204),
// 204 No Content
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerUnpause */
const unpauseContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("unpause", "/:identifier/unpause", {
params: {
identifier: ContainerIdentifier
},
success: /*#__PURE__*/HttpApiSchema.Empty(204),
// 204 No Content
error: [NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerAttach */
const attachContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("attach", "/:identifier/attach", {
params: {
identifier: ContainerIdentifier
},
query: {
detachKeys: /*#__PURE__*/Schema.optional(Schema.String),
logs: /*#__PURE__*/Schema.optional(Schema.Boolean),
stream: /*#__PURE__*/Schema.optional(Schema.Boolean),
stdin: /*#__PURE__*/Schema.optional(Schema.Boolean),
stdout: /*#__PURE__*/Schema.optional(Schema.Boolean),
stderr: /*#__PURE__*/Schema.optional(Schema.Boolean)
},
headers: {
Upgrade: /*#__PURE__*/Schema.Literal("tcp"),
Connection: /*#__PURE__*/Schema.Literal("Upgrade")
},
success: [/*#__PURE__*/HttpApiSchema.Empty(101),
/*#__PURE__*/
// 101 Switching Protocols
HttpApiSchema.Empty(200) // 200 OK
],
error: [BadRequest,
// 400 Bad parameter
NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerAttachWebsocket */
const attachWebsocketContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.get("attachWebsocket", "/:identifier/attach/ws", {
params: {
identifier: ContainerIdentifier
},
query: {
detachKeys: /*#__PURE__*/Schema.optional(Schema.String),
logs: /*#__PURE__*/Schema.optional(Schema.Boolean),
stream: /*#__PURE__*/Schema.optional(Schema.Boolean),
stdin: /*#__PURE__*/Schema.optional(Schema.Boolean),
stdout: /*#__PURE__*/Schema.optional(Schema.Boolean),
stderr: /*#__PURE__*/Schema.optional(Schema.Boolean)
},
success: [/*#__PURE__*/HttpApiSchema.Empty(101),
/*#__PURE__*/
// 101 Switching Protocols
HttpApiSchema.Empty(200) // 200 OK
],
error: [BadRequest,
// 400 Bad parameter
NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerWait */
const waitContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.post("wait", "/:identifier/wait", {
params: {
identifier: ContainerIdentifier
},
query: {
condition: /*#__PURE__*/Schema.optional(Schema.String)
},
success: ContainerWaitResponse,
// 200 OK
error: [BadRequest,
// 400 Bad parameter
NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerDelete */
const deleteContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.delete("delete", "/:identifier", {
params: {
identifier: ContainerIdentifier
},
query: {
v: /*#__PURE__*/Schema.optional(Schema.Boolean),
force: /*#__PURE__*/Schema.optional(Schema.Boolean),
link: /*#__PURE__*/Schema.optional(Schema.Boolean)
},
success: /*#__PURE__*/HttpApiSchema.Empty(204),
// 204 No Content
error: [BadRequest,
// 400 Bad parameter
NotFound,
// 404 Not Found
Conflict,
// 409 Conflict
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerArchive */
const archiveContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.get("archive", "/:identifier/archive", {
params: {
identifier: ContainerIdentifier
},
query: {
path: Schema.String
},
success: /*#__PURE__*/HttpApiSchema.StreamUint8Array(),
// 200 OK (streaming response)
error: [BadRequest,
// 400 Bad parameter
NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerArchiveInfo */
const archiveInfoContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.head("archiveInfo", "/:identifier/archive", {
params: {
identifier: ContainerIdentifier
},
query: {
path: Schema.String
},
success: /*#__PURE__*/HttpApiSchema.Empty(200),
// 200 OK
error: [BadRequest,
// 400 Bad parameter
NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/PutContainerArchive */
const putArchiveContainerEndpoint = /*#__PURE__*/HttpApiEndpoint.put("putArchive", "/:identifier/archive", {
params: {
identifier: ContainerIdentifier
},
payload: /*#__PURE__*/HttpApiSchema.StreamUint8Array(),
query: {
path: Schema.String,
noOverwriteDirNonDir: /*#__PURE__*/Schema.optional(Schema.String),
copyUIDGidentifier: /*#__PURE__*/Schema.optional(Schema.String)
},
success: /*#__PURE__*/HttpApiSchema.Empty(200),
// 200 OK
error: [BadRequest,
// 400 Bad parameter
Forbidden,
// 403 Forbidden
NotFound,
// 404 Not Found
InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container/operation/ContainerPrune */
const pruneContainersEndpoint = /*#__PURE__*/HttpApiEndpoint.post("prune", "/prune", {
query: {
filters: /*#__PURE__*/Schema.optional(PruneFilters)
},
success: /*#__PURE__*/Schema.Struct({
ContainersDeleted: /*#__PURE__*/Schema.NullOr(/*#__PURE__*/Schema.Array(ContainerIdentifier)),
SpaceReclaimed: /*#__PURE__*/Schema.BigIntFromString.check(/*#__PURE__*/Schema.isBetweenBigInt({
minimum: 0n,
maximum: 2n ** 64n - 1n
}))
}),
// 200 OK
error: [InternalServerError]
});
/** @see https://docs.docker.com/reference/api/engine/latest/#tag/Container */
const ContainersGroup = /*#__PURE__*/HttpApiGroup.make("containers").add(listContainersEndpoint, createContainerEndpoint, inspectContainerEndpoint, topContainerEndpoint, logsContainerEndpoint, changesContainerEndpoint, exportContainerEndpoint, statsContainerEndpoint, resizeContainerEndpoint, startContainerEndpoint, stopContainerEndpoint, restartContainerEndpoint, killContainerEndpoint, updateContainerEndpoint, renameContainerEndpoint, pauseContainerEndpoint, unpauseContainerEndpoint, attachContainerEndpoint, attachWebsocketContainerEndpoint, waitContainerEndpoint, deleteContainerEndpoint, archiveContainerEndpoint, archiveInfoContainerEndpoint, putArchiveContainerEndpoint, pruneContainersEndpoint).prefix("/containers");
/**
* @since 1.0.0
* @category HttpApi
* @see https://docs.docker.com/reference/api/engine/latest/#tag/Container
*/
export const ContainersApi = /*#__PURE__*/HttpApi.make("ContainersApi").add(ContainersGroup);
/**
* @since 1.0.0
* @category Services
* @see https://docs.docker.com/reference/api/engine/latest/#tag/Container
*/
export class Containers extends /*#__PURE__*/Context.Service()("@the-moby-effect/endpoints/Containers", {
make: /*#__PURE__*/Effect.gen(function* () {
const httpClient = yield* HttpClient.HttpClient;
const ContainersError = DockerError.WrapForModule("containers");
const websocketConstructor = yield* Socket.WebSocketConstructor;
const client = yield* HttpApiClient.group(ContainersApi, {
httpClient,
group: "containers"
});
const list_ = options => client.list({
query: {
all: options?.all,
limit: options?.limit,
size: options?.size,
filters: options?.filters
}
}).pipe(Effect.mapError(ContainersError("list")));
const create_ = options => Effect.gen(function* () {
const hostConfig = options.HostConfig ? yield* ContainerHostConfig.makeEffect(options.HostConfig) : undefined;
const payload = yield* ContainerCreateRequest.makeEffect({
...options,
HostConfig: hostConfig
});
return yield* client.create({
query: {
name: options.Name,
platform: options.Platform
},
payload
});
}).pipe(Effect.mapError(ContainersError("create")));
const inspect_ = (identifier, options) => client.inspect({
params: {
identifier
},
query: {
...options
}
}).pipe(Effect.mapError(ContainersError("inspect")));
const top_ = (identifier, options) => client.top({
params: {
identifier
},
query: {
...options
}
}).pipe(Effect.mapError(ContainersError("top")));
const logs_ = (identifier, options) => client.logs({
params: {
identifier
},
query: {
...options
}
}).pipe(Stream.unwrap, Stream.decodeText(), Stream.splitLines, Stream.mapError(ContainersError("logs")));
const changes_ = identifier => client.changes({
params: {
identifier
}
}).pipe(Effect.mapError(ContainersError("changes")));
const export_ = identifier => client.export({
params: {
identifier
}
}).pipe(Stream.unwrap, Stream.mapError(ContainersError("export")));
const stats_ = (identifier, options) => client.stats({
params: {
identifier
},
query: {
...options
}
}).pipe(Stream.unwrap, Stream.decodeText(), Stream.splitLines, Stream.map(quoteWireNumbers), Stream.mapEffect(line => Schema.decodeEffect(Schema.fromJsonString(ContainerStatsResponse))(line)), Stream.mapError(ContainersError("stats")));
const resize_ = (identifier, options) => client.resize({
params: {
identifier
},
query: {
...options
}
}).pipe(Effect.mapError(ContainersError("resize")));
const start_ = (identifier, options) => client.start({
params: {
identifier
},
query: {
...options
}
}).pipe(Effect.mapError(ContainersError("start")));
const stop_ = (identifier, options) => client.stop({
params: {
identifier
},
query: {
...options
}
}).pipe(Effect.mapError(ContainersError("stop")));
const restart_ = (identifier, options) => client.restart({
params: {
identifier
},
query: {
...options
}
}).pipe(Effect.mapError(ContainersError("restart")));
const kill_ = (identifier, options) => client.kill({
params: {
identifier
},
query: {
...options
}
}).pipe(Effect.mapError(ContainersError("kill")));
const update_ = (identifier, config) => ContainerConfig.makeEffect(config).pipe(Effect.flatMap(payload => client.update({
params: {
identifier
},
payload
})), Effect.mapError(ContainersError("update")));
const rename_ = (identifier, name) => client.rename({
params: {
identifier
},
query: {
name
}
}).pipe(Effect.mapError(ContainersError("rename")));
const pause_ = identifier => client.pause({
params: {
identifier
}
}).pipe(Effect.mapError(ContainersError("pause")));
const unpause_ = identifier => client.unpause({
params: {
identifier
}
}).pipe(Effect.mapError(ContainersError("unpause")));
const attach_ = (identifier, options) => client.attach({
params: {
identifier
},
query: {
...options
},
headers: {
Connection: "Upgrade",
Upgrade: "tcp"
},
// FIXME: Broken on undici
responseMode: "response-only"
}).pipe(Effect.flatMap(responseToStreamingSocketOrFailUnsafe), Effect.mapError(ContainersError("attach")));
const attachWebsocket_ = (identifier, options) => Effect.gen(function* () {
const baseUrl = "ws://0.0.0.0";
const stripBaseUrl = String.replace(baseUrl, String.empty);
const emptyResponse = new Response(undefined, {
status: 200
});
const noopHttpClient = HttpClient.make(request => Effect.succeed(HttpClientResponse.fromWeb(request, emptyResponse)));
const client = yield* HttpApiClient.endpoint(ContainersApi, {
endpoint: "attachWebsocket",
httpClient: noopHttpClient,
group: "containers",
baseUrl
});
const response = yield* client({
responseMode: "response-only",
params: {
identifier
},
query: {
...options
}
});
const {
hash,
url,
urlParams
} = response.request;
const wsUrl = yield* Url.make(url, urlParams, hash.valueOrUndefined).pipe(Effect.fromResult, Effect.mapError(_cause => new HttpApiError.BadRequest()), Effect.map(url => url.toString()), Effect.map(stripBaseUrl));
const websocket = websocketConstructor(wsUrl);
yield* Effect.callback(resume => {
if (websocket.readyState === 1) {
resume(Effect.void);
return;
}
const onOpen = () => {
cleanup();
resume(Effect.void);
};
const onFailure = cause => {
cleanup();
resume(Effect.fail(new Socket.SocketError({
reason: new Socket.SocketOpenError({
kind: "Unknown",
cause
})
})));
};
const cleanup = () => {
websocket.removeEventListener("open", onOpen);
websocket.removeEventListener("error", onFailure);
websocket.removeEventListener("close", onFailure);
};
websocket.addEventListener("open", onOpen, {
once: true
});
websocket.addEventListener("error", onFailure, {
once: true
});
websocket.addEventListener("close", onFailure, {
once: true
});
return Effect.sync(cleanup);
});
const socket = yield* Socket.fromWebSocket(Effect.acquireRelease(Effect.succeed(websocket), ws => Effect.sync(() => ws.close())), {
closeCodeIsError: code => code !== 1000
});
return makeRawSocket(socket);
}).pipe(Effect.mapError(ContainersError("attachWebsocket")));
const wait_ = (identifier, options) => client.wait({
params: {
identifier
},
query: {
...options
}
}).pipe(Effect.mapError(ContainersError("wait")));
const delete_ = (identifier, options) => client.delete({
params: {
identifier
},
query: {
...options
}
}).pipe(Effect.mapError(ContainersError("delete")));
const archive_ = (identifier, options) => client.archive({
params: {
identifier
},
query: {
...options
}
}).pipe(Stream.unwrap, Stream.mapError(ContainersError("archive")));
const archiveInfo_ = (identifier, options) => client.archiveInfo({
params: {
identifier
},
query: {
...options
},
responseMode: "response-only"
}).pipe(Effect.flatMap(HttpClientResponse.schemaHeaders(Schema.Struct({
"x-docker-container-path-stat": Schema.StringFromBase64.pipe(Schema.decodeTo(Schema.fromJsonString(Schema.Unknown)), Schema.optional)
}))), Effect.map(({
"x-docker-container-path-stat": pathStat
}) => pathStat), Effect.mapError(ContainersError("archiveInfo")));
const putArchive_ = (identifier, stream, options) => Effect.contextWith(context => client.putArchive({
params: {
identifier
},
query: {
...options
},
payload: Stream.provideContext(stream, context)
})).pipe(Effect.mapError(ContainersError("putArchive")));
const prune_ = filters => client.prune({
query: {
filters
}
}).pipe(Effect.mapError(ContainersError("prune")));
return {
list: list_,
create: create_,
inspect: inspect_,
top: top_,
logs: logs_,
changes: changes_,
export: export_,
stats: stats_,
resize: resize_,
start: start_,
stop: stop_,
restart: restart_,
kill: kill_,
update: update_,
rename: rename_,
pause: pause_,
unpause: unpause_,
attach: attach_,
attachWebsocket: attachWebsocket_,
wait: wait_,
delete: delete_,
archive: archive_,
archiveInfo: archiveInfo_,
putArchive: putArchive_,
prune: prune_
};
})
}) {}
/**
* @since 1.0.0
* @category Layers
* @see https://docs.docker.com/reference/api/engine/latest/#tag/Container
*/
export const ContainersLayer = /*#__PURE__*/Layer.effect(Containers, Containers.make);
/**
* @since 1.0.0
* @category Layers
* @see https://docs.docker.com/reference/api/engine/latest/#tag/Container
*/
export const ContainersLayerLocalSocket = /*#__PURE__*/ContainersLayer.pipe(/*#__PURE__*/Layer.provide(/*#__PURE__*/makeAgnosticHttpClientLayer(/*#__PURE__*/MobyConnectionOptions.socket({
socketPath: "/var/run/docker.sock"
}))));
//# sourceMappingURL=containers.js.map