@zgeoff/imp-client 0.8.0 → 0.10.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.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.10.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) {
@@ -754,6 +808,7 @@ function createImpClient(options) {
754
808
  images: rpc.images,
755
809
  exec: rpc.exec,
756
810
  sessions: rpc.sessions,
811
+ services: rpc.services,
757
812
  secrets: rpc.secrets,
758
813
  grants: rpc.grants,
759
814
  audit: rpc.audit,
@@ -775,7 +830,8 @@ function createImpClient(options) {
775
830
  openConsole: (name, consoleOptions) => openConsole(execDeps, name, consoleOptions),
776
831
  openAttach: (name, session, attachOptions) => openAttach(execDeps, name, session, attachOptions),
777
832
  requireAwake: (name, awakeOptions) => requireAwake(rpc, name, awakeOptions),
778
- checkServer: () => checkServer(rpc)
833
+ checkServer: () => checkServer(rpc),
834
+ buildImage: (name, context, buildOptions) => buildImage(execDeps, name, context, buildOptions)
779
835
  };
780
836
  }
781
837
  //#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.10.0",
4
4
  "description": "Typed client for impd, the imp host daemon: imps, checkpoints, images and exec",
5
5
  "license": "MIT",
6
6
  "repository": {