@zgeoff/imp-client 0.8.0 → 0.9.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/dist/index.d.ts CHANGED
@@ -5662,6 +5662,14 @@ interface ServerCheck {
5662
5662
  readonly compatible: boolean;
5663
5663
  }
5664
5664
  //#endregion
5665
+ //#region src/build-image.d.ts
5666
+ type BuildContext = Blob | Uint8Array<ArrayBuffer> | ReadableStream<Uint8Array>;
5667
+ interface BuildImageOptions {
5668
+ readonly dockerfile?: string;
5669
+ readonly size?: number;
5670
+ readonly signal?: AbortSignal;
5671
+ }
5672
+ //#endregion
5665
5673
  //#region src/exec/open-exec-session.d.ts
5666
5674
  interface ExecStart {
5667
5675
  readonly name: string;
@@ -5796,6 +5804,7 @@ interface ImpClientOptions {
5796
5804
  interface ImpClient extends RpcClient {
5797
5805
  readonly requireAwake: (name: string, options?: RequireAwakeOptions) => Promise<Imp>;
5798
5806
  readonly checkServer: () => Promise<ServerCheck>;
5807
+ readonly buildImage: (name: string, context: BuildContext, options?: BuildImageOptions) => Promise<Image>;
5799
5808
  readonly openExec: (name: string, argv: readonly string[], options?: ExecOptions) => Promise<ExecHandle>;
5800
5809
  readonly run: (name: string, argv: readonly string[], options?: RunOptions) => Promise<RunResult>;
5801
5810
  readonly openConsole: (name: string, options?: ConsoleOptions) => Promise<ExecHandle>;
@@ -5865,4 +5874,4 @@ export declare class ExecError extends Error {
5865
5874
  }>);
5866
5875
  }
5867
5876
  //#endregion
5868
- export { type ApiCall, type AttachOptions, type Checkpoint, type ConsoleOptions, type DetachReason, type ExecClientErrorCode, type ExecExit, type ExecHandle, type ExecOptions, type ExecOutcome, type ExecSession, type ExecSessionOptions, type ExecSocket, type ExecStarted, type Identity, type Image, type Imp, type ImpClient, type ImpClientOptions, type ImpEvent, type ImpState, ORPCError, type RequireAwakeOptions, type ReverseForward, type ReverseForwardEnd, type ReverseForwardOptions, type ReverseGuest, type ReverseListening, type ReverseRelay, type ReverseRelayHandlers, type RunOptions, type RunResult, type Scope, type ServerCheck, type Session, type SshKey, type SystemInfo, type Token, isDefinedError, safe };
5877
+ export { type ApiCall, type AttachOptions, type BuildContext, type BuildImageOptions, type Checkpoint, type ConsoleOptions, type DetachReason, type ExecClientErrorCode, type ExecExit, type ExecHandle, type ExecOptions, type ExecOutcome, type ExecSession, type ExecSessionOptions, type ExecSocket, type ExecStarted, type Identity, type Image, type Imp, type ImpClient, type ImpClientOptions, type ImpEvent, type ImpState, ORPCError, type RequireAwakeOptions, type ReverseForward, type ReverseForwardEnd, type ReverseForwardOptions, type ReverseGuest, type ReverseListening, type ReverseRelay, type ReverseRelayHandlers, type RunOptions, type RunResult, type Scope, type ServerCheck, type Session, type SshKey, type SystemInfo, type Token, isDefinedError, safe };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { RPCLink } from "@orpc/client/fetch";
3
3
  import * as z from "zod";
4
4
  //#endregion
5
5
  //#region src/check-server.ts
6
- const CLIENT_VERSION = "0.8.0";
6
+ const CLIENT_VERSION = "0.9.0";
7
7
  async function checkServer(rpc) {
8
8
  const info = await rpc.system.info();
9
9
  return {
@@ -29,6 +29,29 @@ function parseVersion(version) {
29
29
  //#region ../api/src/name-schema.ts
30
30
  const NameSchema = z.string().regex(/^[a-z][a-z0-9-]{0,30}$/, "must be a lowercase letter followed by up to 30 lowercase letters, digits or hyphens");
31
31
  //#endregion
32
+ //#region ../api/src/image-schema.ts
33
+ const ImageSchema = z.object({
34
+ id: z.string(),
35
+ name: NameSchema,
36
+ ref: z.string(),
37
+ digest: z.string(),
38
+ createdAt: z.date(),
39
+ sizeBytes: z.int().nonnegative()
40
+ });
41
+ //#endregion
42
+ //#region ../api/src/image-build-protocol.ts
43
+ const IMAGE_BUILD_PATH = "/images/build";
44
+ const DockerfilePathSchema = z.string().min(1).refine((path) => !path.startsWith("/") && !path.split(/[/\\]/u).includes(".."), { message: "the Dockerfile path must be relative and stay inside the build context" });
45
+ z.object({
46
+ name: NameSchema,
47
+ dockerfile: DockerfilePathSchema.optional()
48
+ });
49
+ const ImageBuildResultSchema = ImageSchema.extend({ createdAt: z.coerce.date() });
50
+ const ImageBuildErrorSchema = z.object({
51
+ code: z.string(),
52
+ message: z.string()
53
+ });
54
+ //#endregion
32
55
  //#region ../api/src/session-schema.ts
33
56
  const SessionNameSchema = z.string().regex(/^[a-z0-9][a-z0-9-]{0,31}$/, "must be a lowercase letter or digit followed by up to 31 lowercase letters, digits or hyphens");
34
57
  const SessionExitSchema = z.object({
@@ -222,6 +245,44 @@ const CONSOLE_SHELL = [
222
245
  "exec \"$shell\" -l"
223
246
  ].join("\n");
224
247
  //#endregion
248
+ //#region src/resolve-impd-url.ts
249
+ function resolveImpdUrl(base, path) {
250
+ const url = new URL(base);
251
+ url.pathname = `${url.pathname.replace(/\/+$/, "")}${path}`;
252
+ return url;
253
+ }
254
+ //#endregion
255
+ //#region src/build-image.ts
256
+ async function buildImage(deps, name, context, options = {}) {
257
+ const url = resolveImpdUrl(deps.baseUrl, IMAGE_BUILD_PATH);
258
+ url.searchParams.set("name", name);
259
+ if (options.dockerfile !== void 0) url.searchParams.set("dockerfile", options.dockerfile);
260
+ const headers = { "content-type": "application/x-tar" };
261
+ if (deps.token !== null) headers["authorization"] = `Bearer ${deps.token}`;
262
+ if (options.size !== void 0) headers["content-length"] = String(options.size);
263
+ const init = {
264
+ method: "POST",
265
+ headers,
266
+ body: context,
267
+ duplex: "half",
268
+ ...options.signal !== void 0 && { signal: options.signal }
269
+ };
270
+ const request = new Request(url.href, init);
271
+ const response = await (deps.fetch ?? fetch)(request);
272
+ const body = await response.json().catch(() => null);
273
+ if (response.ok) return ImageBuildResultSchema.parse(body);
274
+ const failure = ImageBuildErrorSchema.safeParse(body);
275
+ if (failure.success) throw new ORPCError$1(failure.data.code, {
276
+ status: response.status,
277
+ message: failure.data.message
278
+ });
279
+ const code = response.status === 401 ? "UNAUTHORIZED" : "INTERNAL_SERVER_ERROR";
280
+ throw new ORPCError$1(code, {
281
+ status: response.status,
282
+ message: `impd answered ${String(response.status)} to the image build`
283
+ });
284
+ }
285
+ //#endregion
225
286
  //#region src/exec/exec-error.ts
226
287
  var ExecError = class extends Error {
227
288
  code;
@@ -244,13 +305,6 @@ function toExecError(outcome) {
244
305
  return new ExecError("LOCAL_ERROR", "an output handler threw", { cause: outcome.error });
245
306
  }
246
307
  //#endregion
247
- //#region src/resolve-impd-url.ts
248
- function resolveImpdUrl(base, path) {
249
- const url = new URL(base);
250
- url.pathname = `${url.pathname.replace(/\/+$/, "")}${path}`;
251
- return url;
252
- }
253
- //#endregion
254
308
  //#region src/exec/check-impd-access.ts
255
309
  const CHECK_TIMEOUT_MS = 5e3;
256
310
  async function checkImpdAccess(baseUrl, token, customFetch = fetch) {
@@ -775,7 +829,8 @@ function createImpClient(options) {
775
829
  openConsole: (name, consoleOptions) => openConsole(execDeps, name, consoleOptions),
776
830
  openAttach: (name, session, attachOptions) => openAttach(execDeps, name, session, attachOptions),
777
831
  requireAwake: (name, awakeOptions) => requireAwake(rpc, name, awakeOptions),
778
- checkServer: () => checkServer(rpc)
832
+ checkServer: () => checkServer(rpc),
833
+ buildImage: (name, context, buildOptions) => buildImage(execDeps, name, context, buildOptions)
779
834
  };
780
835
  }
781
836
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zgeoff/imp-client",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Typed client for impd, the imp host daemon: imps, checkpoints, images and exec",
5
5
  "license": "MIT",
6
6
  "repository": {