@gjermundgaraba/clankerbox-sdk 0.15.0 → 0.15.2
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/{client-VNMPU7ER.mjs → client-cFk3r2_1.mjs} +40 -5
- package/dist/index.d.mts +18 -1
- package/dist/index.mjs +9 -6
- package/dist/node.mjs +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
2
|
import * as Action from "@gjermundgaraba/effect-actions/Action";
|
|
3
3
|
import * as ActionHttp from "@gjermundgaraba/effect-actions/ActionHttp";
|
|
4
|
-
import { Context, Duration, Effect, Fiber, Match, Predicate, Result, Schema } from "effect";
|
|
4
|
+
import { Context, Duration, Effect, Fiber, Match, Predicate, Result, Schema, SchemaIssue } from "effect";
|
|
5
5
|
import { HttpClient, HttpClientRequest } from "effect/http";
|
|
6
6
|
//#region src/errors.ts
|
|
7
7
|
/**
|
|
@@ -129,7 +129,7 @@ const formatId = (host, name) => {
|
|
|
129
129
|
};
|
|
130
130
|
//#endregion
|
|
131
131
|
//#region package.json
|
|
132
|
-
var version$1 = "0.15.
|
|
132
|
+
var version$1 = "0.15.2";
|
|
133
133
|
//#endregion
|
|
134
134
|
//#region src/resources.ts
|
|
135
135
|
/** The resources a host reports: machines, checkpoints and the host itself. */
|
|
@@ -426,6 +426,41 @@ const Http = ActionHttp.make([
|
|
|
426
426
|
})
|
|
427
427
|
], { prefix: "/api" });
|
|
428
428
|
//#endregion
|
|
429
|
+
//#region src/text.ts
|
|
430
|
+
/** How sizes, decode failures and file failures read in a message or a table cell. */
|
|
431
|
+
const mibPerGib = 1024;
|
|
432
|
+
/**
|
|
433
|
+
* A RAM size, exactly, as a size flag takes one: GiB when it is whole or half GiB, `32G` or
|
|
434
|
+
* `1.5G`, and MiB when it isn't, `512M` or `1500M`.
|
|
435
|
+
*/
|
|
436
|
+
const formatMib = (mib) => mib >= mibPerGib && mib % (mibPerGib / 2) === 0 ? `${mib / mibPerGib}G` : `${mib}M`;
|
|
437
|
+
/**
|
|
438
|
+
* Where a decode failed, as a JSON path: `hosts[0].id`. `names` gives a top-level field the
|
|
439
|
+
* name its caller knows it by.
|
|
440
|
+
*/
|
|
441
|
+
const jsonPath = (path, names) => path.map((key, index) => {
|
|
442
|
+
if (Number.isInteger(key)) return `[${String(key)}]`;
|
|
443
|
+
return index === 0 ? names?.get(key) ?? String(key) : `.${String(key)}`;
|
|
444
|
+
}).join("");
|
|
445
|
+
const flatten = SchemaIssue.makeFormatterStandardSchemaV1({ leafHook: (issue) => Match.value(issue).pipe(Match.tag("MissingKey", () => "missing"), Match.tag("UnexpectedKey", () => "not a known field"), Match.orElse(SchemaIssue.defaultLeafHook)) });
|
|
446
|
+
/**
|
|
447
|
+
* Everything a decode refused, on one line, each under its JSON path: `cpu: missing; ram: not a
|
|
448
|
+
* known field`. `names` renames top-level fields, as when a flag set each: `--cpu: missing`.
|
|
449
|
+
*/
|
|
450
|
+
const describeIssues = (error, names) => flatten(error.issue).issues.map(({ path = [], message }) => {
|
|
451
|
+
const keys = path.map((segment) => Predicate.isPropertyKey(segment) ? segment : segment.key);
|
|
452
|
+
return keys.length === 0 ? message : `${jsonPath(keys, names)}: ${message}`;
|
|
453
|
+
}).join("; ");
|
|
454
|
+
/**
|
|
455
|
+
* Why a file couldn't be read, without the platform call that met it. Node describes a failure
|
|
456
|
+
* only in its cause, so what has no wording here reads as the system's own.
|
|
457
|
+
*/
|
|
458
|
+
const describeFileError = ({ reason }) => {
|
|
459
|
+
if (Predicate.isTagged(reason, "NotFound")) return "no such file or directory";
|
|
460
|
+
if (Predicate.isTagged(reason, "PermissionDenied")) return "permission denied";
|
|
461
|
+
return reason.description ?? (reason.cause instanceof Error ? reason.cause.message : reason._tag);
|
|
462
|
+
};
|
|
463
|
+
//#endregion
|
|
429
464
|
//#region src/client.ts
|
|
430
465
|
/**
|
|
431
466
|
* The client library: a host list in placement order, routing by ID, list fan-out and
|
|
@@ -497,7 +532,7 @@ const decodeHosts = Schema.decodeUnknownEffect(Schema.Array(HostEntry));
|
|
|
497
532
|
*/
|
|
498
533
|
const make = (hosts, options) => Effect.gen(function* () {
|
|
499
534
|
if (hosts.length === 0) return yield* new Invalid({ message: "the host list is empty: a client needs a host" });
|
|
500
|
-
yield* decodeHosts(hosts).pipe(Effect.mapError((error) => new Invalid({ message: `host list: ${error
|
|
535
|
+
yield* decodeHosts(hosts, { errors: "all" }).pipe(Effect.mapError((error) => new Invalid({ message: `host list: ${describeIssues(error)}` })));
|
|
501
536
|
const twice = hosts.find(({ id }, index) => hosts.findIndex((other) => other.id === id) < index);
|
|
502
537
|
if (twice !== void 0) return yield* new Invalid({ message: `host ${twice.id} appears twice in the host list` });
|
|
503
538
|
const routed = yield* Effect.forEach(hosts, (entry) => Effect.map(makeHostApi(entry), (api) => ({
|
|
@@ -575,7 +610,7 @@ const make = (hosts, options) => Effect.gen(function* () {
|
|
|
575
610
|
const result = yield* Fiber.join(fiber);
|
|
576
611
|
if (Result.isFailure(result)) {
|
|
577
612
|
noReply ||= Predicate.isTagged(result.failure, "Unavailable");
|
|
578
|
-
misses.push(`${host} failed: ${result.failure.
|
|
613
|
+
misses.push(`${host} failed: ${result.failure.message}`);
|
|
579
614
|
} else if (result.success.bases.includes(base)) return host;
|
|
580
615
|
else {
|
|
581
616
|
const { bases } = result.success;
|
|
@@ -622,4 +657,4 @@ const make = (hosts, options) => Effect.gen(function* () {
|
|
|
622
657
|
};
|
|
623
658
|
});
|
|
624
659
|
//#endregion
|
|
625
|
-
export {
|
|
660
|
+
export { parseName as A, Unavailable as B, release as C, Name as D, Id as E, HostErrorTag as F, Internal as I, Invalid as L, Conflict as M, ConflictKind as N, formatId as O, ErrorTag as P, NotFound as R, SshLogin as S, HostId as T, hostErrors as V, MachineSpec as _, describeIssues as a, Setup as b, readTimeout as c, ActionRecord as d, Checkpoint as f, Machine as g, Limit as h, describeFileError as i, Capacity as j, parseId as k, versionHeader as l, Host as m, client_exports as n, formatMib as o, CreateRequest as p, make as r, Http as s, Client as t, ActionName as u, Profile as v, version as w, SshEndpoint as x, Runtime as y, Precondition as z };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { A as Precondition, C as ConflictKind, D as Internal, E as HostErrorTag, M as hostErrors, O as Invalid, S as Conflict, T as HostError, _ as SshLogin, a as ActionName, b as Capacity, c as CreateRequest, d as Machine, f as MachineSpec, g as SshEndpoint, h as Setup, i as client_d_exports, j as Unavailable, k as NotFound, l as Host, m as Runtime, o as ActionRecord, p as Profile, s as Checkpoint, u as Limit, v as release, w as ErrorTag, x as ClankerboxError, y as version } from "./client-SX6jTU1R.mjs";
|
|
2
2
|
import * as Action from "@gjermundgaraba/effect-actions/Action";
|
|
3
3
|
import * as ActionHttp from "@gjermundgaraba/effect-actions/ActionHttp";
|
|
4
|
-
import { Duration, Effect, FileSystem, Path, Schema } from "effect";
|
|
4
|
+
import { Duration, Effect, FileSystem, Path, PlatformError, Schema } from "effect";
|
|
5
5
|
import { ChildProcessSpawner } from "effect/process";
|
|
6
6
|
//#region src/api.d.ts
|
|
7
7
|
/**
|
|
@@ -330,4 +330,21 @@ export declare const packRecipe: (directory: string) => Effect.Effect<string, In
|
|
|
330
330
|
/** Reads a setup: a script file's text, or a recipe directory packed into one script. */
|
|
331
331
|
export declare const readSetup: (path: string) => Effect.Effect<string, Invalid, FileSystem.FileSystem | ChildProcessSpawner.ChildProcessSpawner>;
|
|
332
332
|
//#endregion
|
|
333
|
+
//#region src/text.d.ts
|
|
334
|
+
/**
|
|
335
|
+
* A RAM size, exactly, as a size flag takes one: GiB when it is whole or half GiB, `32G` or
|
|
336
|
+
* `1.5G`, and MiB when it isn't, `512M` or `1500M`.
|
|
337
|
+
*/
|
|
338
|
+
export declare const formatMib: (mib: number) => string;
|
|
339
|
+
/**
|
|
340
|
+
* Everything a decode refused, on one line, each under its JSON path: `cpu: missing; ram: not a
|
|
341
|
+
* known field`. `names` renames top-level fields, as when a flag set each: `--cpu: missing`.
|
|
342
|
+
*/
|
|
343
|
+
export declare const describeIssues: (error: Schema.SchemaError, names?: ReadonlyMap<PropertyKey, string>) => string;
|
|
344
|
+
/**
|
|
345
|
+
* Why a file couldn't be read, without the platform call that met it. Node describes a failure
|
|
346
|
+
* only in its cause, so what has no wording here reads as the system's own.
|
|
347
|
+
*/
|
|
348
|
+
export declare const describeFileError: ({ reason }: PlatformError.PlatformError) => string;
|
|
349
|
+
//#endregion
|
|
333
350
|
export { ActionName, ActionRecord, Capacity, Checkpoint, ClankerboxError, client_d_exports as Client, Conflict, ConflictKind, CreateRequest, ErrorTag, Host, HostError, HostErrorTag, Internal, Invalid, Limit, Machine, MachineSpec, NotFound, Precondition, Profile, Runtime, Setup, SshEndpoint, SshLogin, Unavailable, hostErrors, release, version };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as parseName, B as Unavailable, C as release, D as Name, E as Id, F as HostErrorTag, I as Internal, L as Invalid, M as Conflict, N as ConflictKind, O as formatId, P as ErrorTag, R as NotFound, S as SshLogin, T as HostId, V as hostErrors, _ as MachineSpec, a as describeIssues, b as Setup, c as readTimeout, d as ActionRecord, f as Checkpoint, g as Machine, h as Limit, i as describeFileError, j as Capacity, k as parseId, l as versionHeader, m as Host, n as client_exports, o as formatMib, p as CreateRequest, s as Http, u as ActionName, v as Profile, w as version, x as SshEndpoint, y as Runtime, z as Precondition } from "./client-cFk3r2_1.mjs";
|
|
2
2
|
import { Effect, FileSystem, Path, Predicate, Schema, Stream } from "effect";
|
|
3
3
|
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
4
4
|
//#region src/profile.ts
|
|
@@ -13,8 +13,11 @@ const decodeProfile = Schema.decodeUnknownEffect(Schema.fromJsonString(Profile))
|
|
|
13
13
|
const loadProfile = (file) => Effect.gen(function* () {
|
|
14
14
|
const fs = yield* FileSystem.FileSystem;
|
|
15
15
|
const path = yield* Path.Path;
|
|
16
|
-
const text = yield* fs.readFileString(file).pipe(Effect.mapError((error) => new Invalid({ message: `couldn't read profile ${file}: ${error
|
|
17
|
-
const profile = yield* decodeProfile(text, {
|
|
16
|
+
const text = yield* fs.readFileString(file).pipe(Effect.mapError((error) => new Invalid({ message: `couldn't read profile ${file}: ${describeFileError(error)}` })));
|
|
17
|
+
const profile = yield* decodeProfile(text, {
|
|
18
|
+
onExcessProperty: "error",
|
|
19
|
+
errors: "all"
|
|
20
|
+
}).pipe(Effect.mapError((error) => new Invalid({ message: `profile ${file}: ${describeIssues(error)}` })));
|
|
18
21
|
const label = path.basename(file, ".json");
|
|
19
22
|
return profile.setup === void 0 ? {
|
|
20
23
|
...profile,
|
|
@@ -95,12 +98,12 @@ const packRecipe = (directory) => Effect.gen(function* () {
|
|
|
95
98
|
], { concurrency: "unbounded" });
|
|
96
99
|
if (code !== 0) return yield* new Invalid({ message: `tar couldn't pack recipe ${directory} (exit ${code}): ${errors.trim()}` });
|
|
97
100
|
return selfExtracting(Buffer.from(archive.buffer, archive.byteOffset, archive.byteLength).toString("base64"));
|
|
98
|
-
}).pipe(Effect.scoped, Effect.catchTag("PlatformError", (error) => Effect.fail(new Invalid({ message: `couldn't pack recipe ${directory}: ${error
|
|
101
|
+
}).pipe(Effect.scoped, Effect.catchTag("PlatformError", (error) => Effect.fail(new Invalid({ message: `couldn't pack recipe ${directory}: ${describeFileError(error)}` }))));
|
|
99
102
|
/** Reads a setup: a script file's text, or a recipe directory packed into one script. */
|
|
100
103
|
const readSetup = (path) => Effect.gen(function* () {
|
|
101
104
|
const fs = yield* FileSystem.FileSystem;
|
|
102
105
|
if ((yield* fs.stat(path)).type === "Directory") return yield* packRecipe(path);
|
|
103
106
|
return yield* fs.readFileString(path);
|
|
104
|
-
}).pipe(Effect.catchTag("PlatformError", (error) => Effect.fail(new Invalid({ message: `couldn't read setup ${path}: ${error
|
|
107
|
+
}).pipe(Effect.catchTag("PlatformError", (error) => Effect.fail(new Invalid({ message: `couldn't read setup ${path}: ${describeFileError(error)}` }))));
|
|
105
108
|
//#endregion
|
|
106
|
-
export { ActionName, ActionRecord, Capacity, Checkpoint, client_exports as Client, Conflict, ConflictKind, CreateRequest, ErrorTag, Host, HostErrorTag, HostId, Http, Id, Internal, Invalid, Limit, Machine, MachineSpec, Name, NotFound, Precondition, Profile, Runtime, Setup, SshEndpoint, SshLogin, Unavailable, formatId, hostErrors, loadProfile, packRecipe, parseId, parseName, readSetup, readTimeout, release, version, versionHeader };
|
|
109
|
+
export { ActionName, ActionRecord, Capacity, Checkpoint, client_exports as Client, Conflict, ConflictKind, CreateRequest, ErrorTag, Host, HostErrorTag, HostId, Http, Id, Internal, Invalid, Limit, Machine, MachineSpec, Name, NotFound, Precondition, Profile, Runtime, Setup, SshEndpoint, SshLogin, Unavailable, describeFileError, describeIssues, formatId, formatMib, hostErrors, loadProfile, packRecipe, parseId, parseName, readSetup, readTimeout, release, version, versionHeader };
|
package/dist/node.mjs
CHANGED