@settlemint/dalp-cli 3.1.32-main.42202049300 → 3.1.32-main.42209626311

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.
@@ -0,0 +1,363 @@
1
+ import { z } from "incur";
2
+ import type { SurfaceOperation, SurfaceParam } from "./openapi-surface-types.ts";
3
+
4
+ export type ZodTypeAny = z.ZodType;
5
+
6
+ const cliValueSchema = z.union([z.json(), z.date(), z.bigint(), z.undefined()]);
7
+ const looseBagSchema = z.record(z.string(), cliValueSchema);
8
+
9
+ export type LooseBag = z.output<typeof looseBagSchema>;
10
+
11
+ export const parseLooseBag = (value: unknown): LooseBag => looseBagSchema.parse(value);
12
+
13
+ function zodDefType(schema: ZodTypeAny): string | undefined {
14
+ const def = Reflect.get(schema, "def") as { type?: string } | undefined;
15
+ return def?.type ?? Reflect.get(schema, "type");
16
+ }
17
+
18
+ function zodInner(schema: ZodTypeAny): ZodTypeAny | undefined {
19
+ const def = Reflect.get(schema, "def") as { innerType?: ZodTypeAny; schema?: ZodTypeAny } | undefined;
20
+ return def?.innerType ?? def?.schema;
21
+ }
22
+
23
+ function unwrapZod(schema: ZodTypeAny): ZodTypeAny {
24
+ let current = schema;
25
+ for (let depth = 0; depth < 8; depth += 1) {
26
+ const type = zodDefType(current);
27
+ if (type === "optional" || type === "nullable" || type === "default" || type === "readonly") {
28
+ const inner = zodInner(current);
29
+ if (inner === undefined) {
30
+ return current;
31
+ }
32
+ current = inner;
33
+ continue;
34
+ }
35
+ break;
36
+ }
37
+ return current;
38
+ }
39
+
40
+ export type ZodShape = Record<string, ZodTypeAny>;
41
+
42
+ export function objectShape(schema: ZodTypeAny | undefined): ZodShape | undefined {
43
+ if (schema === undefined) {
44
+ return undefined;
45
+ }
46
+ const core = unwrapZod(schema);
47
+ if (zodDefType(core) !== "object") {
48
+ return undefined;
49
+ }
50
+ const def = Reflect.get(core, "def") as {
51
+ shape?: ZodShape | (() => ZodShape);
52
+ };
53
+ const shape = typeof def.shape === "function" ? def.shape() : def.shape;
54
+ if (shape === undefined) {
55
+ return Reflect.get(core, "shape") as ZodShape | undefined;
56
+ }
57
+ return shape;
58
+ }
59
+
60
+ function needsJsonStringInput(schema: ZodTypeAny): boolean {
61
+ const type = zodDefType(unwrapZod(schema));
62
+ return type === "object" || type === "array" || type === "union" || type === "intersection";
63
+ }
64
+
65
+ export function asCliField(schema: ZodTypeAny, description?: string): ZodTypeAny {
66
+ const core = unwrapZod(schema);
67
+ let field: ZodTypeAny;
68
+
69
+ if (needsJsonStringInput(schema)) {
70
+ field = z.preprocess((value: unknown) => {
71
+ if (typeof value !== "string") {
72
+ return value;
73
+ }
74
+ const trimmed = value.trim();
75
+ if (trimmed === "") {
76
+ return value;
77
+ }
78
+ try {
79
+ const parsed: unknown = JSON.parse(trimmed);
80
+ return parsed;
81
+ } catch {
82
+ return value;
83
+ }
84
+ }, schema);
85
+ } else if (zodDefType(core) === "number") {
86
+ field = z.preprocess((value: unknown) => {
87
+ if (typeof value === "string" && value.trim() !== "" && !Number.isNaN(Number(value))) {
88
+ return Number(value);
89
+ }
90
+ return value;
91
+ }, schema);
92
+ } else if (zodDefType(core) === "boolean") {
93
+ field = z.preprocess((value: unknown) => {
94
+ if (value === "true" || value === true) {
95
+ return true;
96
+ }
97
+ if (value === "false" || value === false) {
98
+ return false;
99
+ }
100
+ return value;
101
+ }, schema);
102
+ } else {
103
+ field = schema;
104
+ }
105
+
106
+ if (description !== undefined && description.trim() !== "") {
107
+ return field.describe(description);
108
+ }
109
+ return field;
110
+ }
111
+
112
+ function asCliJsonOption(schema: ZodTypeAny, description: string): ZodTypeAny {
113
+ return z
114
+ .preprocess((value: unknown) => {
115
+ if (value === undefined || value === null || value === "") {
116
+ return value;
117
+ }
118
+ if (typeof value === "string") {
119
+ try {
120
+ const parsed: unknown = JSON.parse(value);
121
+ return parsed;
122
+ } catch {
123
+ return value;
124
+ }
125
+ }
126
+ return value;
127
+ }, schema.optional())
128
+ .describe(description);
129
+ }
130
+
131
+ function openApiFieldDescription(
132
+ surface: SurfaceOperation | undefined,
133
+ location: "path" | "query" | "body",
134
+ name: string
135
+ ): string | undefined {
136
+ if (surface === undefined) {
137
+ return undefined;
138
+ }
139
+ if (location === "path") {
140
+ const param = surface.pathParams.find((entry) => entry.name === name);
141
+ return formatSurfaceDescribe(param?.description, param?.examples, param?.pattern);
142
+ }
143
+ if (location === "query") {
144
+ const param = surface.queryParams.find((entry) => entry.name === name);
145
+ if (param === undefined) {
146
+ return undefined;
147
+ }
148
+ return formatSurfaceDescribe(param.description, param.examples, param.pattern);
149
+ }
150
+ const field = surface.bodyFields.find((entry) => entry.name === name);
151
+ return formatSurfaceDescribe(field?.description, field?.examples, field?.pattern);
152
+ }
153
+
154
+ function formatSurfaceDescribe(
155
+ description: string | null | undefined,
156
+ examples: ReadonlyArray<string> | undefined,
157
+ pattern: string | null | undefined
158
+ ): string | undefined {
159
+ const parts: Array<string> = [];
160
+ if (description !== undefined && description !== null && description.trim() !== "") {
161
+ parts.push(description);
162
+ }
163
+ if (pattern !== undefined && pattern !== null && pattern !== "") {
164
+ parts.push(`Pattern: ${pattern}`);
165
+ }
166
+ if (examples !== undefined && examples.length > 0) {
167
+ parts.push(`Example: ${examples[0]}`);
168
+ }
169
+ return parts.length > 0 ? parts.join(" ") : undefined;
170
+ }
171
+
172
+ export function buildArgsFromSdkPath(
173
+ pathSchema: ZodTypeAny | undefined,
174
+ surface: SurfaceOperation | undefined,
175
+ makeOptional: boolean
176
+ ): z.ZodObject<ZodShape> | undefined {
177
+ const shape = objectShape(pathSchema);
178
+ if (shape === undefined || Object.keys(shape).length === 0) {
179
+ return undefined;
180
+ }
181
+ const out: ZodShape = {};
182
+ for (const [name, fieldSchema] of Object.entries(shape)) {
183
+ const described = asCliField(fieldSchema, openApiFieldDescription(surface, "path", name));
184
+ out[name] = makeOptional ? described.optional() : described;
185
+ }
186
+ return z.object(out);
187
+ }
188
+
189
+ export function buildOptionsFromSdk(
190
+ querySchema: ZodTypeAny | undefined,
191
+ bodySchema: ZodTypeAny | undefined,
192
+ surface: SurfaceOperation | undefined,
193
+ extras?: ZodShape
194
+ ): z.ZodObject<ZodShape> | undefined {
195
+ const out: ZodShape = extras === undefined ? {} : { ...extras };
196
+
197
+ const queryShape = objectShape(querySchema);
198
+ if (queryShape !== undefined) {
199
+ for (const [name, fieldSchema] of Object.entries(queryShape)) {
200
+ out[name] = asCliField(fieldSchema, openApiFieldDescription(surface, "query", name));
201
+ }
202
+ }
203
+ if (querySchema !== undefined) {
204
+ out.query = asCliJsonOption(
205
+ querySchema,
206
+ surface?.queryParams.map((param) => param.description).find((text) => text !== null && text !== "") ??
207
+ "Full query object as JSON (SDK query schema)"
208
+ );
209
+ }
210
+
211
+ if (bodySchema !== undefined) {
212
+ out.body = asCliJsonOption(bodySchema, surface?.requestBodyDescription ?? "JSON request body (SDK body schema)");
213
+ const bodyShape = objectShape(bodySchema);
214
+ if (bodyShape !== undefined) {
215
+ for (const [name, fieldSchema] of Object.entries(bodyShape)) {
216
+ if (needsJsonStringInput(fieldSchema)) {
217
+ continue;
218
+ }
219
+ if (out[name] !== undefined) {
220
+ continue;
221
+ }
222
+ out[name] = asCliField(fieldSchema, openApiFieldDescription(surface, "body", name)).optional();
223
+ }
224
+ }
225
+ }
226
+
227
+ for (const param of surface?.headerParams ?? []) {
228
+ const headerOption = param.name
229
+ .replaceAll(/([a-z0-9])([A-Z])/gu, "$1-$2")
230
+ .replaceAll("_", "-")
231
+ .replaceAll(/-+/gu, "-")
232
+ .toLowerCase();
233
+ if (out[headerOption] !== undefined) {
234
+ continue;
235
+ }
236
+ out[headerOption] = z
237
+ .string()
238
+ .optional()
239
+ .describe(formatSurfaceDescribe(param.description, param.examples, param.pattern) ?? param.name);
240
+ }
241
+
242
+ if (Object.keys(out).length === 0) {
243
+ return undefined;
244
+ }
245
+ return z.object(out);
246
+ }
247
+
248
+ export function collectQueryBag(options: LooseBag, querySchema: ZodTypeAny | undefined): unknown {
249
+ if (options.query !== undefined) {
250
+ return options.query;
251
+ }
252
+ const shape = objectShape(querySchema);
253
+ if (shape === undefined) {
254
+ return undefined;
255
+ }
256
+ const query: LooseBag = {};
257
+ for (const name of Object.keys(shape)) {
258
+ if (options[name] !== undefined) {
259
+ query[name] = options[name];
260
+ }
261
+ }
262
+ return Object.keys(query).length > 0 ? query : undefined;
263
+ }
264
+
265
+ export function collectBodyBag(options: LooseBag, bodySchema: ZodTypeAny | undefined): unknown {
266
+ if (options.body !== undefined) {
267
+ return options.body;
268
+ }
269
+ const shape = objectShape(bodySchema);
270
+ if (shape === undefined) {
271
+ return undefined;
272
+ }
273
+ const body: LooseBag = {};
274
+ for (const [name, fieldSchema] of Object.entries(shape)) {
275
+ if (needsJsonStringInput(fieldSchema)) {
276
+ continue;
277
+ }
278
+ if (options[name] !== undefined) {
279
+ body[name] = options[name];
280
+ }
281
+ }
282
+ if (Object.keys(body).length === 0) {
283
+ return undefined;
284
+ }
285
+ if (bodySchema === undefined) {
286
+ return body;
287
+ }
288
+ const parsed = bodySchema.safeParse(body);
289
+ if (!parsed.success) {
290
+ return body;
291
+ }
292
+ return parsed.data;
293
+ }
294
+
295
+ export function collectPathBag(args: LooseBag): LooseBag | undefined {
296
+ const path: LooseBag = {};
297
+ for (const [key, value] of Object.entries(args)) {
298
+ if (value !== undefined && value !== "") {
299
+ path[key] = value;
300
+ }
301
+ }
302
+ return Object.keys(path).length > 0 ? path : undefined;
303
+ }
304
+
305
+ export function parseWithSdkSchema<T>(schema: ZodTypeAny, value: unknown, label: string): T {
306
+ const parsed = schema.safeParse(value);
307
+ if (!parsed.success) {
308
+ throw new Error(`${label}: ${parsed.error.message}`);
309
+ }
310
+ return parsed.data as T;
311
+ }
312
+
313
+ function zodForSurfaceParam(param: SurfaceParam): ZodTypeAny {
314
+ let schema: ZodTypeAny;
315
+ if (param.enum !== null && param.enum.length > 0) {
316
+ schema = z.enum(param.enum as [string, ...Array<string>]);
317
+ } else if (param.fields.length > 0) {
318
+ schema = z.object(Object.fromEntries(param.fields.map((field) => [field.name, zodForSurfaceParam(field)])));
319
+ } else {
320
+ switch (param.type ?? "string") {
321
+ case "integer":
322
+ case "number": {
323
+ schema = z.number();
324
+ break;
325
+ }
326
+ case "boolean": {
327
+ schema = z.boolean();
328
+ break;
329
+ }
330
+ case "array": {
331
+ schema = z.array(z.json());
332
+ break;
333
+ }
334
+ case "object": {
335
+ schema = z.record(z.string(), z.json());
336
+ break;
337
+ }
338
+ default: {
339
+ schema = param.pattern === null ? z.string() : z.string().regex(new RegExp(param.pattern, "u"));
340
+ }
341
+ }
342
+ }
343
+ const described = asCliField(schema, param.description ?? undefined);
344
+ return param.required ? described : described.optional();
345
+ }
346
+
347
+ export function zodFromSurfaceParams(params: ReadonlyArray<SurfaceParam>): z.ZodObject<ZodShape> | undefined {
348
+ if (params.length === 0) {
349
+ return undefined;
350
+ }
351
+ return z.object(Object.fromEntries(params.map((param) => [param.name, zodForSurfaceParam(param)])));
352
+ }
353
+
354
+ export function zodForRequestBody(surface: SurfaceOperation | undefined): z.ZodType | undefined {
355
+ if (surface === undefined || !surface.hasRequestBody) {
356
+ return undefined;
357
+ }
358
+ if (surface.bodyIsComplex) {
359
+ const partial = zodFromSurfaceParams(surface.bodyFields);
360
+ return partial === undefined ? z.record(z.string(), z.json()) : partial.catchall(z.json());
361
+ }
362
+ return zodFromSurfaceParams(surface.bodyFields) ?? z.record(z.string(), z.json());
363
+ }
@@ -0,0 +1,23 @@
1
+ import { createInterface } from "node:readline";
2
+ import { Writable } from "node:stream";
3
+
4
+ const muted = new Writable({
5
+ write(_chunk, _encoding, done) {
6
+ done();
7
+ },
8
+ });
9
+
10
+ export const promptSecret = (question: string): Promise<string> =>
11
+ new Promise((resolve, reject) => {
12
+ process.stdout.write(question);
13
+ const reader = createInterface({ input: process.stdin, output: muted, terminal: true });
14
+ reader.once("line", (answer) => {
15
+ reader.close();
16
+ process.stdout.write("\n");
17
+ resolve(answer.trim());
18
+ });
19
+ reader.once("SIGINT", () => {
20
+ reader.close();
21
+ reject(new Error("Cancelled"));
22
+ });
23
+ });
@@ -0,0 +1,19 @@
1
+ import type { DalpClient } from "@settlemint/dalp-sdk";
2
+ import { z } from "incur";
3
+ import type { StoredCredentials } from "./credential-store.ts";
4
+ import packageJson from "../../package.json" with { type: "json" };
5
+
6
+ export const CLI_VERSION = packageJson.version;
7
+ export const CLI_USER_AGENT = `DALP CLI v${CLI_VERSION}`;
8
+
9
+ function middlewareInjectedVar<T>() {
10
+ return z.custom<T>().optional();
11
+ }
12
+
13
+ export const cliVars = z.object({
14
+ apiUrl: middlewareInjectedVar<string>(),
15
+ credentials: middlewareInjectedVar<StoredCredentials>(),
16
+ client: middlewareInjectedVar<DalpClient>(),
17
+ });
18
+
19
+ export type CliVars = z.infer<typeof cliVars>;