hostctl 0.1.55 → 0.1.58
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/bin/hostctl.js +436 -62
- package/dist/bin/hostctl.js.map +1 -1
- package/dist/index.d.ts +28 -2
- package/dist/index.js +436 -62
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/hostctl.js
CHANGED
|
@@ -2929,9 +2929,13 @@ function task(runFn4, options) {
|
|
|
2929
2929
|
options?.outputSchema
|
|
2930
2930
|
);
|
|
2931
2931
|
const taskFnObject = function(params) {
|
|
2932
|
-
|
|
2933
|
-
|
|
2932
|
+
const normalizedParams = params ?? {};
|
|
2933
|
+
const taskPartialFn = function(parentInvocation) {
|
|
2934
|
+
return parentInvocation.invokeChildTask(taskFnObject, normalizedParams);
|
|
2934
2935
|
};
|
|
2936
|
+
taskPartialFn.taskFn = taskFnObject;
|
|
2937
|
+
taskPartialFn.params = normalizedParams;
|
|
2938
|
+
return taskPartialFn;
|
|
2935
2939
|
};
|
|
2936
2940
|
Object.assign(taskFnObject, { task: taskInstance });
|
|
2937
2941
|
return taskFnObject;
|
|
@@ -3897,6 +3901,9 @@ import AdmZip from "adm-zip";
|
|
|
3897
3901
|
|
|
3898
3902
|
// src/hash.ts
|
|
3899
3903
|
import { createHash } from "crypto";
|
|
3904
|
+
function sha256(str) {
|
|
3905
|
+
return createHash("sha256").update(str).digest("hex");
|
|
3906
|
+
}
|
|
3900
3907
|
|
|
3901
3908
|
// src/param-map.ts
|
|
3902
3909
|
import { match as match2 } from "ts-pattern";
|
|
@@ -3981,7 +3988,7 @@ var ParamMap = class _ParamMap {
|
|
|
3981
3988
|
import * as z from "zod";
|
|
3982
3989
|
|
|
3983
3990
|
// src/version.ts
|
|
3984
|
-
var version = "0.1.
|
|
3991
|
+
var version = "0.1.58";
|
|
3985
3992
|
|
|
3986
3993
|
// src/app.ts
|
|
3987
3994
|
import { retryUntilDefined } from "ts-retry";
|
|
@@ -6731,58 +6738,64 @@ async function detectRockyLinux(exec) {
|
|
|
6731
6738
|
}
|
|
6732
6739
|
var os_default = task(
|
|
6733
6740
|
async function run27(context) {
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
variant
|
|
6741
|
+
return await context.memoize(
|
|
6742
|
+
"core.host.os:v1",
|
|
6743
|
+
async () => {
|
|
6744
|
+
try {
|
|
6745
|
+
const { exec } = context;
|
|
6746
|
+
const {
|
|
6747
|
+
success: ostypeSuccess,
|
|
6748
|
+
stdout: ostypeOutput,
|
|
6749
|
+
stderr: ostypeStderr
|
|
6750
|
+
} = await exec(["bash", "-c", "echo $OSTYPE"]);
|
|
6751
|
+
if (!ostypeSuccess) {
|
|
6752
|
+
throw new Error(`Failed to get OSTYPE: ${ostypeStderr}`);
|
|
6753
|
+
}
|
|
6754
|
+
const family = await match5(ostypeOutput.trim().toLowerCase()).with(P3.string.startsWith("solaris"), () => "solaris").with(P3.string.startsWith("darwin"), () => "darwin").with(P3.string.startsWith("linux"), () => "linux").with(P3.string.startsWith("bsd"), () => "bsd").with(P3.string.startsWith("freebsd"), () => "bsd").with(P3.string.startsWith("msys"), () => "windows").with(P3.string.startsWith("cygwin"), () => "windows").with(P3.string.startsWith("mingw"), () => "windows").otherwise(async () => {
|
|
6755
|
+
const { stdout: unameOutput } = await exec(["uname"]);
|
|
6756
|
+
const unameFamily = match5(unameOutput.trim().toLowerCase()).with(P3.string.startsWith("sunos"), () => "solaris").with(P3.string.startsWith("darwin"), () => "darwin").with(P3.string.startsWith("linux"), () => "linux").with(P3.string.startsWith("freebsd"), () => "bsd").with(P3.string.startsWith("openbsd"), () => "bsd").with(P3.string.startsWith("netbsd"), () => "bsd").otherwise(() => "unknown");
|
|
6757
|
+
return unameFamily;
|
|
6758
|
+
});
|
|
6759
|
+
const [osIdLike, osId, osVersion] = await match5(family).with("bsd", async () => {
|
|
6760
|
+
const { stdout: unameROutput } = await exec(["uname", "-r"]);
|
|
6761
|
+
return [family, family, unameROutput.trim()];
|
|
6762
|
+
}).with("darwin", async () => {
|
|
6763
|
+
const { stdout: swVersOutput } = await exec(["sw_vers", "-productVersion"]);
|
|
6764
|
+
return [family, family, swVersOutput.trim()];
|
|
6765
|
+
}).with("linux", async () => {
|
|
6766
|
+
const { idLike, id, version: version2 } = await getOsReleaseInfo(exec);
|
|
6767
|
+
return [idLike, id, version2];
|
|
6768
|
+
}).with("solaris", async () => {
|
|
6769
|
+
const { stdout: unameROutput } = await exec(["uname", "-r"]);
|
|
6770
|
+
return ["solaris", "solaris", unameROutput.trim()];
|
|
6771
|
+
}).with("windows", () => ["windows", "windows", "unknown"]).otherwise(() => ["unknown", "unknown", "unknown"]);
|
|
6772
|
+
let variant = osId.toLowerCase();
|
|
6773
|
+
if (family === "linux" && !variant.includes("rocky") && (osIdLike.toLowerCase().includes("rocky") || osId.toLowerCase().includes("rhel"))) {
|
|
6774
|
+
const isRocky = await detectRockyLinux(exec);
|
|
6775
|
+
if (isRocky) {
|
|
6776
|
+
variant = "rocky";
|
|
6777
|
+
}
|
|
6778
|
+
}
|
|
6779
|
+
return {
|
|
6780
|
+
success: true,
|
|
6781
|
+
family,
|
|
6782
|
+
os: osIdLike.toLowerCase(),
|
|
6783
|
+
variant,
|
|
6784
|
+
version: osVersion
|
|
6785
|
+
};
|
|
6786
|
+
} catch (error) {
|
|
6787
|
+
return {
|
|
6788
|
+
success: false,
|
|
6789
|
+
error: error.message,
|
|
6790
|
+
family: "unknown",
|
|
6791
|
+
os: "unknown",
|
|
6792
|
+
variant: "unknown",
|
|
6793
|
+
version: "unknown"
|
|
6794
|
+
};
|
|
6767
6795
|
}
|
|
6768
|
-
}
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
family,
|
|
6772
|
-
os: osIdLike.toLowerCase(),
|
|
6773
|
-
variant,
|
|
6774
|
-
version: osVersion
|
|
6775
|
-
};
|
|
6776
|
-
} catch (error) {
|
|
6777
|
-
return {
|
|
6778
|
-
success: false,
|
|
6779
|
-
error: error.message,
|
|
6780
|
-
family: "unknown",
|
|
6781
|
-
os: "unknown",
|
|
6782
|
-
variant: "unknown",
|
|
6783
|
-
version: "unknown"
|
|
6784
|
-
};
|
|
6785
|
-
}
|
|
6796
|
+
},
|
|
6797
|
+
{ scope: "host" }
|
|
6798
|
+
);
|
|
6786
6799
|
},
|
|
6787
6800
|
{
|
|
6788
6801
|
name: "os",
|
|
@@ -31791,6 +31804,154 @@ function registrySize(registry2) {
|
|
|
31791
31804
|
return registry2.tasks().length;
|
|
31792
31805
|
}
|
|
31793
31806
|
|
|
31807
|
+
// src/task-cache.ts
|
|
31808
|
+
var DEFAULT_CACHE_MODE = "use";
|
|
31809
|
+
var LOCAL_HOST_SCOPE_KEY = "host:local";
|
|
31810
|
+
function normalizeValue(value) {
|
|
31811
|
+
if (value === void 0) {
|
|
31812
|
+
return void 0;
|
|
31813
|
+
}
|
|
31814
|
+
if (value === null) {
|
|
31815
|
+
return null;
|
|
31816
|
+
}
|
|
31817
|
+
if (typeof value === "bigint") {
|
|
31818
|
+
return value.toString();
|
|
31819
|
+
}
|
|
31820
|
+
if (value instanceof Date) {
|
|
31821
|
+
return value.toISOString();
|
|
31822
|
+
}
|
|
31823
|
+
if (Array.isArray(value)) {
|
|
31824
|
+
return value.map((item) => {
|
|
31825
|
+
const normalized = normalizeValue(item);
|
|
31826
|
+
return normalized === void 0 ? null : normalized;
|
|
31827
|
+
});
|
|
31828
|
+
}
|
|
31829
|
+
if (typeof value === "object") {
|
|
31830
|
+
const obj = value;
|
|
31831
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
31832
|
+
const result = {};
|
|
31833
|
+
for (const key of sortedKeys) {
|
|
31834
|
+
const normalized = normalizeValue(obj[key]);
|
|
31835
|
+
if (normalized !== void 0) {
|
|
31836
|
+
result[key] = normalized;
|
|
31837
|
+
}
|
|
31838
|
+
}
|
|
31839
|
+
return result;
|
|
31840
|
+
}
|
|
31841
|
+
return value;
|
|
31842
|
+
}
|
|
31843
|
+
function stableJson(value) {
|
|
31844
|
+
const normalized = normalizeValue(value);
|
|
31845
|
+
return JSON.stringify(normalized ?? null);
|
|
31846
|
+
}
|
|
31847
|
+
function normalizeCacheConfig(cache) {
|
|
31848
|
+
if (!cache) {
|
|
31849
|
+
return { enabled: false, mode: DEFAULT_CACHE_MODE };
|
|
31850
|
+
}
|
|
31851
|
+
if (cache === true) {
|
|
31852
|
+
return { enabled: true, mode: DEFAULT_CACHE_MODE };
|
|
31853
|
+
}
|
|
31854
|
+
if (typeof cache === "string") {
|
|
31855
|
+
return { enabled: true, scope: cache, mode: DEFAULT_CACHE_MODE };
|
|
31856
|
+
}
|
|
31857
|
+
return {
|
|
31858
|
+
enabled: true,
|
|
31859
|
+
scope: cache.scope,
|
|
31860
|
+
key: cache.key,
|
|
31861
|
+
ttlMs: cache.ttlMs,
|
|
31862
|
+
mode: cache.mode ?? DEFAULT_CACHE_MODE
|
|
31863
|
+
};
|
|
31864
|
+
}
|
|
31865
|
+
function buildTaskCacheKey(taskIdentity, params) {
|
|
31866
|
+
const taskName = taskIdentity?.task?.name;
|
|
31867
|
+
const modulePath = taskIdentity?.task?.taskModuleAbsolutePath;
|
|
31868
|
+
const identity2 = taskName ?? (modulePath ? Path.new(modulePath).absolute().toString() : "unknown-task");
|
|
31869
|
+
const paramsHash = sha256(stableJson(params ?? {}));
|
|
31870
|
+
return `${identity2}:${paramsHash}`;
|
|
31871
|
+
}
|
|
31872
|
+
function buildHostScopeKey(host, configRef) {
|
|
31873
|
+
if (!host) {
|
|
31874
|
+
return LOCAL_HOST_SCOPE_KEY;
|
|
31875
|
+
}
|
|
31876
|
+
const identity2 = {
|
|
31877
|
+
alias: host.alias ?? "",
|
|
31878
|
+
hostname: host.hostname ?? "",
|
|
31879
|
+
user: host.user ?? "",
|
|
31880
|
+
port: host.port ?? 22,
|
|
31881
|
+
config: configRef ?? ""
|
|
31882
|
+
};
|
|
31883
|
+
return `host:${sha256(stableJson(identity2))}`;
|
|
31884
|
+
}
|
|
31885
|
+
function buildInvocationScopeKey(rootInvocationId) {
|
|
31886
|
+
return `invocation:${rootInvocationId}`;
|
|
31887
|
+
}
|
|
31888
|
+
var TaskCacheStore = class {
|
|
31889
|
+
entries = /* @__PURE__ */ new Map();
|
|
31890
|
+
runId;
|
|
31891
|
+
constructor(runId) {
|
|
31892
|
+
this.runId = runId ?? crypto.randomUUID();
|
|
31893
|
+
}
|
|
31894
|
+
globalScopeKey() {
|
|
31895
|
+
return `global:${this.runId}`;
|
|
31896
|
+
}
|
|
31897
|
+
get(scopeKey, cacheKey2) {
|
|
31898
|
+
const scope = this.entries.get(scopeKey);
|
|
31899
|
+
if (!scope) {
|
|
31900
|
+
return void 0;
|
|
31901
|
+
}
|
|
31902
|
+
const entry = scope.get(cacheKey2);
|
|
31903
|
+
if (!entry) {
|
|
31904
|
+
return void 0;
|
|
31905
|
+
}
|
|
31906
|
+
if (entry.expiresAt > 0 && Date.now() > entry.expiresAt) {
|
|
31907
|
+
scope.delete(cacheKey2);
|
|
31908
|
+
if (scope.size === 0) {
|
|
31909
|
+
this.entries.delete(scopeKey);
|
|
31910
|
+
}
|
|
31911
|
+
return void 0;
|
|
31912
|
+
}
|
|
31913
|
+
return entry;
|
|
31914
|
+
}
|
|
31915
|
+
set(scopeKey, cacheKey2, value, ttlMs) {
|
|
31916
|
+
const scope = this.entries.get(scopeKey) ?? /* @__PURE__ */ new Map();
|
|
31917
|
+
const expiresAt = ttlMs && ttlMs > 0 ? Date.now() + ttlMs : 0;
|
|
31918
|
+
const entry = { value, expiresAt };
|
|
31919
|
+
scope.set(cacheKey2, entry);
|
|
31920
|
+
this.entries.set(scopeKey, scope);
|
|
31921
|
+
return entry;
|
|
31922
|
+
}
|
|
31923
|
+
delete(scopeKey, cacheKey2) {
|
|
31924
|
+
const scope = this.entries.get(scopeKey);
|
|
31925
|
+
if (!scope) {
|
|
31926
|
+
return;
|
|
31927
|
+
}
|
|
31928
|
+
scope.delete(cacheKey2);
|
|
31929
|
+
if (scope.size === 0) {
|
|
31930
|
+
this.entries.delete(scopeKey);
|
|
31931
|
+
}
|
|
31932
|
+
}
|
|
31933
|
+
async resolve(scopeKey, cacheKey2, compute, options = {}) {
|
|
31934
|
+
const mode = options.mode ?? DEFAULT_CACHE_MODE;
|
|
31935
|
+
if (mode === "bypass") {
|
|
31936
|
+
return await compute();
|
|
31937
|
+
}
|
|
31938
|
+
if (mode === "use") {
|
|
31939
|
+
const cached = this.get(scopeKey, cacheKey2);
|
|
31940
|
+
if (cached) {
|
|
31941
|
+
return await cached.value;
|
|
31942
|
+
}
|
|
31943
|
+
}
|
|
31944
|
+
const promise = Promise.resolve().then(compute);
|
|
31945
|
+
this.set(scopeKey, cacheKey2, promise, options.ttlMs);
|
|
31946
|
+
try {
|
|
31947
|
+
return await promise;
|
|
31948
|
+
} catch (error) {
|
|
31949
|
+
this.delete(scopeKey, cacheKey2);
|
|
31950
|
+
throw error;
|
|
31951
|
+
}
|
|
31952
|
+
}
|
|
31953
|
+
};
|
|
31954
|
+
|
|
31794
31955
|
// src/app.ts
|
|
31795
31956
|
var TaskTree = class {
|
|
31796
31957
|
// private taskEventBus: Emittery<{ newTask: NewTaskEvent; taskComplete: TaskCompleteEvent }>;
|
|
@@ -31887,6 +32048,7 @@ var App3 = class _App {
|
|
|
31887
32048
|
outputStyle;
|
|
31888
32049
|
_tmpDir;
|
|
31889
32050
|
tmpFileRegistry;
|
|
32051
|
+
taskCache;
|
|
31890
32052
|
taskTree;
|
|
31891
32053
|
verbosity = Verbosity.ERROR;
|
|
31892
32054
|
passwordProvider;
|
|
@@ -31896,6 +32058,7 @@ var App3 = class _App {
|
|
|
31896
32058
|
this.taskTree = new TaskTree();
|
|
31897
32059
|
this.outputStyle = "plain";
|
|
31898
32060
|
this.tmpFileRegistry = new TmpFileRegistry(this.hostctlTmpDir());
|
|
32061
|
+
this.taskCache = new TaskCacheStore();
|
|
31899
32062
|
this.configRef = void 0;
|
|
31900
32063
|
this.hostSelector = void 0;
|
|
31901
32064
|
process3.on("exit", (code) => this.appExitCallback());
|
|
@@ -32211,6 +32374,27 @@ ${cmdRes.stderr.trim()}`));
|
|
|
32211
32374
|
}
|
|
32212
32375
|
taskContextForRunFn(invocation, params, hostForContext) {
|
|
32213
32376
|
const effectiveHost = hostForContext || invocation.host;
|
|
32377
|
+
const rootInvocationId = (() => {
|
|
32378
|
+
let current = invocation;
|
|
32379
|
+
while (current.parent) {
|
|
32380
|
+
current = current.parent;
|
|
32381
|
+
}
|
|
32382
|
+
return current.id;
|
|
32383
|
+
})();
|
|
32384
|
+
const defaultScope = () => effectiveHost ? "host" : "global";
|
|
32385
|
+
const scopeKeyFor = (scope) => {
|
|
32386
|
+
switch (scope) {
|
|
32387
|
+
case "global":
|
|
32388
|
+
return this.taskCache.globalScopeKey();
|
|
32389
|
+
case "host":
|
|
32390
|
+
return buildHostScopeKey(effectiveHost, this.configRef);
|
|
32391
|
+
case "invocation":
|
|
32392
|
+
return buildInvocationScopeKey(rootInvocationId);
|
|
32393
|
+
}
|
|
32394
|
+
};
|
|
32395
|
+
const isTaskFn = (candidate) => {
|
|
32396
|
+
return typeof candidate === "function" && !!candidate.task;
|
|
32397
|
+
};
|
|
32214
32398
|
return {
|
|
32215
32399
|
// Properties from TaskContext
|
|
32216
32400
|
params,
|
|
@@ -32240,8 +32424,58 @@ ${cmdRes.stderr.trim()}`));
|
|
|
32240
32424
|
ssh: async (tags, remoteTaskFn) => {
|
|
32241
32425
|
return await invocation.ssh(tags, remoteTaskFn);
|
|
32242
32426
|
},
|
|
32243
|
-
run: async (
|
|
32244
|
-
|
|
32427
|
+
run: async (...args) => {
|
|
32428
|
+
const [firstArg, secondArg, thirdArg] = args;
|
|
32429
|
+
let taskPartialFn;
|
|
32430
|
+
let taskIdentity;
|
|
32431
|
+
let paramsForKey;
|
|
32432
|
+
let options;
|
|
32433
|
+
if (isTaskFn(firstArg)) {
|
|
32434
|
+
taskIdentity = firstArg;
|
|
32435
|
+
paramsForKey = secondArg ?? {};
|
|
32436
|
+
options = thirdArg;
|
|
32437
|
+
taskPartialFn = taskIdentity(paramsForKey);
|
|
32438
|
+
} else {
|
|
32439
|
+
taskPartialFn = firstArg;
|
|
32440
|
+
options = secondArg;
|
|
32441
|
+
const meta = taskPartialFn;
|
|
32442
|
+
taskIdentity = meta.taskFn;
|
|
32443
|
+
paramsForKey = meta.params;
|
|
32444
|
+
}
|
|
32445
|
+
const cacheDecision = normalizeCacheConfig(options?.cache);
|
|
32446
|
+
if (!cacheDecision.enabled || cacheDecision.mode === "bypass") {
|
|
32447
|
+
return await invocation.run(taskPartialFn);
|
|
32448
|
+
}
|
|
32449
|
+
const scope = cacheDecision.scope ?? defaultScope();
|
|
32450
|
+
const cacheKey2 = cacheDecision.key ?? buildTaskCacheKey(taskIdentity, paramsForKey ?? {});
|
|
32451
|
+
const scopeKey = scopeKeyFor(scope);
|
|
32452
|
+
return await this.taskCache.resolve(scopeKey, cacheKey2, () => invocation.run(taskPartialFn), {
|
|
32453
|
+
ttlMs: cacheDecision.ttlMs,
|
|
32454
|
+
mode: cacheDecision.mode
|
|
32455
|
+
});
|
|
32456
|
+
},
|
|
32457
|
+
memoize: async (key, valueOrFactory, options) => {
|
|
32458
|
+
const cacheDecision = normalizeCacheConfig({
|
|
32459
|
+
scope: options?.scope,
|
|
32460
|
+
ttlMs: options?.ttlMs,
|
|
32461
|
+
mode: options?.mode,
|
|
32462
|
+
key
|
|
32463
|
+
});
|
|
32464
|
+
const scope = cacheDecision.scope ?? defaultScope();
|
|
32465
|
+
const scopeKey = scopeKeyFor(scope);
|
|
32466
|
+
const compute = async () => {
|
|
32467
|
+
if (typeof valueOrFactory === "function") {
|
|
32468
|
+
return await valueOrFactory();
|
|
32469
|
+
}
|
|
32470
|
+
return await valueOrFactory;
|
|
32471
|
+
};
|
|
32472
|
+
if (cacheDecision.mode === "bypass") {
|
|
32473
|
+
return await compute();
|
|
32474
|
+
}
|
|
32475
|
+
return await this.taskCache.resolve(scopeKey, key, compute, {
|
|
32476
|
+
ttlMs: cacheDecision.ttlMs,
|
|
32477
|
+
mode: cacheDecision.mode
|
|
32478
|
+
});
|
|
32245
32479
|
},
|
|
32246
32480
|
getPassword: async () => {
|
|
32247
32481
|
return await invocation.getPassword();
|
|
@@ -33906,8 +34140,8 @@ function renderTaskRows(rows, {
|
|
|
33906
34140
|
name: r.name,
|
|
33907
34141
|
description: r.description,
|
|
33908
34142
|
module: r.module,
|
|
33909
|
-
inputSchema:
|
|
33910
|
-
outputSchema:
|
|
34143
|
+
inputSchema: schemaToDescriptor(r.inputSchema),
|
|
34144
|
+
outputSchema: schemaToDescriptor(r.outputSchema),
|
|
33911
34145
|
schemaSource: r.schemaSource
|
|
33912
34146
|
}));
|
|
33913
34147
|
console.log(JSON.stringify(sanitized, null, 2));
|
|
@@ -33948,9 +34182,12 @@ function summarizeType(val) {
|
|
|
33948
34182
|
case "optional":
|
|
33949
34183
|
case "ZodNullable":
|
|
33950
34184
|
case "nullable":
|
|
34185
|
+
case "ZodDefault":
|
|
34186
|
+
case "default":
|
|
33951
34187
|
return summarizeType(def.innerType || def.type);
|
|
33952
34188
|
case "ZodEffects":
|
|
33953
|
-
|
|
34189
|
+
case "pipe":
|
|
34190
|
+
return summarizeType(def.schema || def.in);
|
|
33954
34191
|
case "ZodString":
|
|
33955
34192
|
case "string":
|
|
33956
34193
|
return { type: "string", desc };
|
|
@@ -33973,8 +34210,11 @@ function summarizeType(val) {
|
|
|
33973
34210
|
return types.length ? { type: types.join(" | "), desc } : {};
|
|
33974
34211
|
}
|
|
33975
34212
|
case "ZodLiteral":
|
|
33976
|
-
case "literal":
|
|
33977
|
-
|
|
34213
|
+
case "literal": {
|
|
34214
|
+
const values3 = Array.isArray(def?.values) ? def.values : def?.value !== void 0 ? [def.value] : [];
|
|
34215
|
+
const value = values3.length ? values3[0] : void 0;
|
|
34216
|
+
return { type: value !== void 0 ? JSON.stringify(value) : void 0, desc };
|
|
34217
|
+
}
|
|
33978
34218
|
case "ZodObject":
|
|
33979
34219
|
case "object":
|
|
33980
34220
|
return { type: "object", desc };
|
|
@@ -33982,6 +34222,140 @@ function summarizeType(val) {
|
|
|
33982
34222
|
return { type: String(tn).replace(/^Zod/, "").toLowerCase(), desc };
|
|
33983
34223
|
}
|
|
33984
34224
|
}
|
|
34225
|
+
function schemaToDescriptor(schema) {
|
|
34226
|
+
if (!schema) return null;
|
|
34227
|
+
const { schema: base, nullable } = unwrapSchema(schema);
|
|
34228
|
+
const def = base?._def ?? base?.def;
|
|
34229
|
+
const typeName = def?.typeName || def?.type;
|
|
34230
|
+
const description = def?.description || base?.description;
|
|
34231
|
+
let descriptor = {};
|
|
34232
|
+
switch (typeName) {
|
|
34233
|
+
case "ZodString":
|
|
34234
|
+
case "string":
|
|
34235
|
+
descriptor.type = "string";
|
|
34236
|
+
break;
|
|
34237
|
+
case "ZodNumber":
|
|
34238
|
+
case "number":
|
|
34239
|
+
descriptor.type = "number";
|
|
34240
|
+
break;
|
|
34241
|
+
case "ZodBoolean":
|
|
34242
|
+
case "boolean":
|
|
34243
|
+
descriptor.type = "boolean";
|
|
34244
|
+
break;
|
|
34245
|
+
case "ZodArray":
|
|
34246
|
+
case "array": {
|
|
34247
|
+
const inner = def?.element ?? def?.type;
|
|
34248
|
+
descriptor.type = "array";
|
|
34249
|
+
descriptor.items = schemaToDescriptor(inner);
|
|
34250
|
+
break;
|
|
34251
|
+
}
|
|
34252
|
+
case "ZodObject":
|
|
34253
|
+
case "object": {
|
|
34254
|
+
const shapeSource = def?.shape || def?.shape_;
|
|
34255
|
+
const shape = shapeSource && typeof shapeSource === "function" ? shapeSource.call(def) : shapeSource;
|
|
34256
|
+
const properties = {};
|
|
34257
|
+
const required = [];
|
|
34258
|
+
if (shape && typeof shape === "object") {
|
|
34259
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
34260
|
+
const { schema: fieldSchema, optional, nullable: fieldNullable } = unwrapSchema(value);
|
|
34261
|
+
const fieldDescriptor = schemaToDescriptor(fieldSchema) ?? {};
|
|
34262
|
+
if (fieldNullable) {
|
|
34263
|
+
fieldDescriptor.nullable = true;
|
|
34264
|
+
}
|
|
34265
|
+
properties[key] = fieldDescriptor;
|
|
34266
|
+
if (!optional) {
|
|
34267
|
+
required.push(key);
|
|
34268
|
+
}
|
|
34269
|
+
}
|
|
34270
|
+
}
|
|
34271
|
+
descriptor.type = "object";
|
|
34272
|
+
descriptor.properties = properties;
|
|
34273
|
+
descriptor.required = required.length ? required : void 0;
|
|
34274
|
+
break;
|
|
34275
|
+
}
|
|
34276
|
+
case "ZodUnion":
|
|
34277
|
+
case "union": {
|
|
34278
|
+
const options = def?.options ?? [];
|
|
34279
|
+
descriptor.anyOf = options.map((option) => schemaToDescriptor(option)).filter(Boolean);
|
|
34280
|
+
break;
|
|
34281
|
+
}
|
|
34282
|
+
case "ZodLiteral":
|
|
34283
|
+
case "literal": {
|
|
34284
|
+
const values3 = Array.isArray(def?.values) ? def.values : def?.value !== void 0 ? [def.value] : [];
|
|
34285
|
+
const sample = values3.length ? values3[0] : void 0;
|
|
34286
|
+
descriptor.type = sample === null ? "null" : typeof sample;
|
|
34287
|
+
descriptor.enum = values3;
|
|
34288
|
+
break;
|
|
34289
|
+
}
|
|
34290
|
+
case "ZodEnum":
|
|
34291
|
+
case "enum":
|
|
34292
|
+
const enumValues = Array.isArray(def?.values) ? def.values : Object.values(def?.entries ?? {});
|
|
34293
|
+
descriptor.enum = enumValues;
|
|
34294
|
+
if (enumValues.length) {
|
|
34295
|
+
const hasNumber = enumValues.some((value) => typeof value === "number");
|
|
34296
|
+
const hasString = enumValues.some((value) => typeof value === "string");
|
|
34297
|
+
descriptor.type = hasNumber && !hasString ? "number" : "string";
|
|
34298
|
+
} else {
|
|
34299
|
+
descriptor.type = "string";
|
|
34300
|
+
}
|
|
34301
|
+
break;
|
|
34302
|
+
case "ZodNativeEnum":
|
|
34303
|
+
case "nativeenum": {
|
|
34304
|
+
const values3 = Array.isArray(def?.values) ? def.values : Object.values(def?.entries ?? def?.values ?? {});
|
|
34305
|
+
descriptor.type = values3.every((value) => typeof value === "number") ? "number" : "string";
|
|
34306
|
+
descriptor.enum = values3;
|
|
34307
|
+
break;
|
|
34308
|
+
}
|
|
34309
|
+
default:
|
|
34310
|
+
descriptor.type = typeName ? String(typeName).replace(/^Zod/, "").toLowerCase() : "unknown";
|
|
34311
|
+
break;
|
|
34312
|
+
}
|
|
34313
|
+
if (description) {
|
|
34314
|
+
descriptor.description = description;
|
|
34315
|
+
}
|
|
34316
|
+
if (nullable) {
|
|
34317
|
+
descriptor.nullable = true;
|
|
34318
|
+
}
|
|
34319
|
+
return descriptor;
|
|
34320
|
+
}
|
|
34321
|
+
function unwrapSchema(schema) {
|
|
34322
|
+
let current = schema;
|
|
34323
|
+
let optional = false;
|
|
34324
|
+
let nullable = false;
|
|
34325
|
+
while (current) {
|
|
34326
|
+
const def = current?._def ?? current?.def;
|
|
34327
|
+
const typeName = def?.typeName || def?.type;
|
|
34328
|
+
if (typeName === "ZodOptional" || typeName === "optional") {
|
|
34329
|
+
optional = true;
|
|
34330
|
+
current = def?.innerType ?? def?.type;
|
|
34331
|
+
continue;
|
|
34332
|
+
}
|
|
34333
|
+
if (typeName === "ZodNullable" || typeName === "nullable") {
|
|
34334
|
+
nullable = true;
|
|
34335
|
+
current = def?.innerType ?? def?.type;
|
|
34336
|
+
continue;
|
|
34337
|
+
}
|
|
34338
|
+
if (typeName === "ZodDefault" || typeName === "default") {
|
|
34339
|
+
optional = true;
|
|
34340
|
+
current = def?.innerType ?? def?.type;
|
|
34341
|
+
continue;
|
|
34342
|
+
}
|
|
34343
|
+
if (typeName === "ZodEffects" || typeName === "effects") {
|
|
34344
|
+
current = def?.schema;
|
|
34345
|
+
continue;
|
|
34346
|
+
}
|
|
34347
|
+
if (typeName === "pipe") {
|
|
34348
|
+
current = def?.in ?? def?.schema;
|
|
34349
|
+
continue;
|
|
34350
|
+
}
|
|
34351
|
+
if (typeName === "transform") {
|
|
34352
|
+
current = def?.schema ?? def?.in;
|
|
34353
|
+
continue;
|
|
34354
|
+
}
|
|
34355
|
+
break;
|
|
34356
|
+
}
|
|
34357
|
+
return { schema: current, optional, nullable };
|
|
34358
|
+
}
|
|
33985
34359
|
function formatSchemaLines(schema) {
|
|
33986
34360
|
if (!schema) return ["none"];
|
|
33987
34361
|
const def = schema._def ?? schema.def;
|
|
@@ -33994,7 +34368,7 @@ function formatSchemaLines(schema) {
|
|
|
33994
34368
|
const tn = anyVal?._def?.typeName || anyVal?.def?.type;
|
|
33995
34369
|
const typeString = summary2.type || (tn ? String(tn).replace(/^Zod/, "").toLowerCase() : void 0);
|
|
33996
34370
|
const desc = summary2.desc;
|
|
33997
|
-
const optional =
|
|
34371
|
+
const optional = ["ZodOptional", "optional", "ZodNullable", "nullable", "ZodDefault", "default"].includes(tn);
|
|
33998
34372
|
const typePart = typeString ? `: ${typeString}` : "";
|
|
33999
34373
|
const descPart = desc ? ` - ${desc}` : "";
|
|
34000
34374
|
return `- ${key}${optional ? "?" : ""}${typePart}${descPart}`;
|