@clickraft/cli 0.2.0 → 0.3.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/CHANGELOG.md +2 -2
- package/README.md +3 -0
- package/dist/cli.js +315 -11
- package/dist/cli.js.map +1 -1
- package/dist/index.js +315 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
## [0.
|
|
1
|
+
## [0.3.0](https://github.com/clickraft/cli/compare/v0.2.0...v0.3.0) (2026-05-24)
|
|
2
2
|
|
|
3
3
|
### Features
|
|
4
4
|
|
|
5
|
-
* **commands:** add
|
|
5
|
+
* **commands:** add template list, get, and find commands ([b2f5c5c](https://github.com/clickraft/cli/commit/b2f5c5c2e501f8ea5c6586476d121b97ce97f4ba))
|
|
6
6
|
|
|
7
7
|
# Changelog
|
|
8
8
|
|
package/README.md
CHANGED
|
@@ -19,6 +19,9 @@ clickraft login
|
|
|
19
19
|
clickraft generate create --prompt "a serene mountain landscape at dawn"
|
|
20
20
|
clickraft balance
|
|
21
21
|
clickraft brand-model list
|
|
22
|
+
clickraft template list
|
|
23
|
+
clickraft template get <template-id>
|
|
24
|
+
clickraft template find "coffee brand"
|
|
22
25
|
```
|
|
23
26
|
|
|
24
27
|
Full documentation: [docs.clickraft.ai/cli](https://docs.clickraft.ai/cli) _(coming soon)_
|
package/dist/cli.js
CHANGED
|
@@ -721,6 +721,10 @@ function buildUrl(baseUrl, path, query) {
|
|
|
721
721
|
if (query) {
|
|
722
722
|
for (const [key, value] of Object.entries(query)) {
|
|
723
723
|
if (value === void 0) continue;
|
|
724
|
+
if (Array.isArray(value)) {
|
|
725
|
+
for (const item of value) url.searchParams.append(key, item);
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
724
728
|
url.searchParams.append(key, String(value));
|
|
725
729
|
}
|
|
726
730
|
}
|
|
@@ -2305,21 +2309,112 @@ function inspectTelemetry(options = {}) {
|
|
|
2305
2309
|
};
|
|
2306
2310
|
}
|
|
2307
2311
|
|
|
2308
|
-
// src/commands/
|
|
2312
|
+
// src/commands/template/internal.ts
|
|
2313
|
+
async function buildTemplateClient(opts) {
|
|
2314
|
+
const cfg = await loadConfig({
|
|
2315
|
+
flagProfile: opts.profile,
|
|
2316
|
+
flagApiBaseUrl: opts.apiBaseUrl,
|
|
2317
|
+
flagToken: opts.token
|
|
2318
|
+
});
|
|
2319
|
+
return new ApiClient({
|
|
2320
|
+
apiBaseUrl: cfg.apiBaseUrl,
|
|
2321
|
+
accessToken: cfg.accessToken,
|
|
2322
|
+
signal: opts.signal,
|
|
2323
|
+
cloudflareAccess: cfg.cloudflareAccess
|
|
2324
|
+
});
|
|
2325
|
+
}
|
|
2326
|
+
|
|
2327
|
+
// src/schemas/templates.ts
|
|
2309
2328
|
import { z as z8 } from "zod";
|
|
2310
|
-
var
|
|
2329
|
+
var DeclaredParamSchema = z8.object({
|
|
2330
|
+
name: z8.string(),
|
|
2331
|
+
type: z8.string(),
|
|
2332
|
+
required: z8.boolean(),
|
|
2333
|
+
defaultValue: z8.string().nullable().optional(),
|
|
2334
|
+
enumValues: z8.array(z8.string()).nullable().optional(),
|
|
2335
|
+
description: z8.string().nullable().optional()
|
|
2336
|
+
}).strict();
|
|
2337
|
+
var TemplateSummarySchema = z8.object({
|
|
2311
2338
|
id: z8.string().uuid(),
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
lastUsedAt: z8.string().nullable(),
|
|
2319
|
-
expiresAt: z8.string(),
|
|
2339
|
+
source: z8.enum(["own", "system"]),
|
|
2340
|
+
name: z8.string(),
|
|
2341
|
+
description: z8.string().nullable(),
|
|
2342
|
+
category: z8.string().nullable(),
|
|
2343
|
+
thumbnailUrl: z8.string().nullable(),
|
|
2344
|
+
tags: z8.array(z8.string()),
|
|
2320
2345
|
createdAt: z8.string()
|
|
2321
2346
|
}).strict();
|
|
2322
|
-
var
|
|
2347
|
+
var TemplateDetailSchema = TemplateSummarySchema.extend({
|
|
2348
|
+
declaredParams: z8.array(DeclaredParamSchema),
|
|
2349
|
+
timesUsed: z8.number()
|
|
2350
|
+
}).strict();
|
|
2351
|
+
var TemplatesListResponseSchema = z8.object({
|
|
2352
|
+
templates: z8.array(TemplateSummarySchema),
|
|
2353
|
+
cursor: z8.string().nullable(),
|
|
2354
|
+
hasMore: z8.boolean()
|
|
2355
|
+
}).strict();
|
|
2356
|
+
|
|
2357
|
+
// src/commands/template/list.ts
|
|
2358
|
+
async function listTemplates(opts) {
|
|
2359
|
+
const client = opts.client ?? await buildTemplateClient(opts);
|
|
2360
|
+
const data = await client.request({
|
|
2361
|
+
method: "GET",
|
|
2362
|
+
path: "/templates",
|
|
2363
|
+
query: {
|
|
2364
|
+
q: opts.q,
|
|
2365
|
+
tags: opts.tags,
|
|
2366
|
+
scope: opts.scope,
|
|
2367
|
+
cursor: opts.cursor,
|
|
2368
|
+
limit: opts.limit
|
|
2369
|
+
},
|
|
2370
|
+
responseSchema: TemplatesListResponseSchema,
|
|
2371
|
+
signal: opts.signal
|
|
2372
|
+
});
|
|
2373
|
+
return data;
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
// src/commands/template/find.ts
|
|
2377
|
+
async function findTemplates(opts) {
|
|
2378
|
+
return listTemplates({
|
|
2379
|
+
q: opts.query,
|
|
2380
|
+
tags: opts.tags,
|
|
2381
|
+
scope: opts.scope,
|
|
2382
|
+
limit: opts.limit,
|
|
2383
|
+
cursor: opts.cursor,
|
|
2384
|
+
profile: opts.profile,
|
|
2385
|
+
apiBaseUrl: opts.apiBaseUrl,
|
|
2386
|
+
token: opts.token,
|
|
2387
|
+
signal: opts.signal,
|
|
2388
|
+
client: opts.client
|
|
2389
|
+
});
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
// src/commands/template/get.ts
|
|
2393
|
+
async function getTemplate(opts) {
|
|
2394
|
+
const client = opts.client ?? await buildTemplateClient(opts);
|
|
2395
|
+
return client.request({
|
|
2396
|
+
method: "GET",
|
|
2397
|
+
path: `/templates/${encodeURIComponent(opts.id)}`,
|
|
2398
|
+
responseSchema: TemplateDetailSchema,
|
|
2399
|
+
signal: opts.signal
|
|
2400
|
+
});
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
// src/commands/tokens/list.ts
|
|
2404
|
+
import { z as z9 } from "zod";
|
|
2405
|
+
var TokenRowSchema = z9.object({
|
|
2406
|
+
id: z9.string().uuid(),
|
|
2407
|
+
organizationId: z9.string().uuid(),
|
|
2408
|
+
userId: z9.string().uuid(),
|
|
2409
|
+
clientId: z9.string().nullable(),
|
|
2410
|
+
tokenPrefix: z9.string(),
|
|
2411
|
+
name: z9.string().nullable(),
|
|
2412
|
+
scopes: z9.array(z9.string()),
|
|
2413
|
+
lastUsedAt: z9.string().nullable(),
|
|
2414
|
+
expiresAt: z9.string(),
|
|
2415
|
+
createdAt: z9.string()
|
|
2416
|
+
}).strict();
|
|
2417
|
+
var TokensListResponseSchema = z9.array(TokenRowSchema);
|
|
2323
2418
|
async function listTokens(options) {
|
|
2324
2419
|
const config = await loadConfig({
|
|
2325
2420
|
flagProfile: options.profile,
|
|
@@ -2717,6 +2812,61 @@ function renderBrandModelsList(models, out) {
|
|
|
2717
2812
|
out.write(padRow(headers) + "\n");
|
|
2718
2813
|
for (const cells of data) out.write(padRow(cells) + "\n");
|
|
2719
2814
|
}
|
|
2815
|
+
function renderTemplatesList(result, out) {
|
|
2816
|
+
const { templates } = result;
|
|
2817
|
+
if (templates.length === 0) {
|
|
2818
|
+
out.write("No templates.\n");
|
|
2819
|
+
return;
|
|
2820
|
+
}
|
|
2821
|
+
const MAX_TAGS = 3;
|
|
2822
|
+
const headers = ["SOURCE", "NAME", "CATEGORY", "TAGS", "CREATED"];
|
|
2823
|
+
const data = templates.map((t) => {
|
|
2824
|
+
const shown = t.tags.slice(0, MAX_TAGS).join(", ");
|
|
2825
|
+
const extra = t.tags.length > MAX_TAGS ? ` +${t.tags.length - MAX_TAGS} more` : "";
|
|
2826
|
+
return [
|
|
2827
|
+
t.source,
|
|
2828
|
+
t.name,
|
|
2829
|
+
t.category ?? "\u2014",
|
|
2830
|
+
t.tags.length > 0 ? shown + extra : "\u2014",
|
|
2831
|
+
t.createdAt.slice(0, 10)
|
|
2832
|
+
];
|
|
2833
|
+
});
|
|
2834
|
+
const widths = headers.map(
|
|
2835
|
+
(header, i) => Math.max(header.length, ...data.map((cells) => cells[i].length))
|
|
2836
|
+
);
|
|
2837
|
+
const padRow = (cells) => cells.map((cell, i) => cell.padEnd(widths[i])).join(" ").trimEnd();
|
|
2838
|
+
out.write(padRow(headers) + "\n");
|
|
2839
|
+
for (const cells of data) out.write(padRow(cells) + "\n");
|
|
2840
|
+
if (result.hasMore) {
|
|
2841
|
+
out.write("\nMore results available. Use --cursor to fetch the next page.\n");
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
function renderTemplateDetail(detail, out) {
|
|
2845
|
+
const pad = 17;
|
|
2846
|
+
const lines = [
|
|
2847
|
+
detail.name,
|
|
2848
|
+
`${"ID:".padEnd(pad)}${detail.id}`,
|
|
2849
|
+
`${"Source:".padEnd(pad)}${detail.source}`,
|
|
2850
|
+
`${"Category:".padEnd(pad)}${detail.category ?? "\u2014"}`,
|
|
2851
|
+
`${"Tags:".padEnd(pad)}${detail.tags.length > 0 ? detail.tags.join(", ") : "\u2014"}`,
|
|
2852
|
+
`${"Created:".padEnd(pad)}${detail.createdAt.slice(0, 10)}`,
|
|
2853
|
+
`${"Times used:".padEnd(pad)}${detail.timesUsed}`
|
|
2854
|
+
];
|
|
2855
|
+
if (detail.description) {
|
|
2856
|
+
lines.push("", detail.description);
|
|
2857
|
+
}
|
|
2858
|
+
lines.push("", "Declared parameters:");
|
|
2859
|
+
if (detail.declaredParams.length === 0) {
|
|
2860
|
+
lines.push(" (none)");
|
|
2861
|
+
} else {
|
|
2862
|
+
for (const p of detail.declaredParams) {
|
|
2863
|
+
const req = p.required ? "required" : "optional";
|
|
2864
|
+
const desc = p.description ? `: ${p.description}` : "";
|
|
2865
|
+
lines.push(` - ${p.name} (${p.type}, ${req})${desc}`);
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
out.write(lines.join("\n") + "\n");
|
|
2869
|
+
}
|
|
2720
2870
|
function formatExpiresAt(iso) {
|
|
2721
2871
|
const ms = Date.parse(iso);
|
|
2722
2872
|
if (Number.isNaN(ms)) return iso;
|
|
@@ -2944,6 +3094,9 @@ function renderRootHelp(version) {
|
|
|
2944
3094
|
" balance Show credit balance and rate limits",
|
|
2945
3095
|
" brand-model list List available brand models",
|
|
2946
3096
|
" telemetry inspect Show current telemetry state and payload shape",
|
|
3097
|
+
" template list List available templates",
|
|
3098
|
+
" template get Fetch a template by ID",
|
|
3099
|
+
" template find Search templates by keyword",
|
|
2947
3100
|
" generate create Submit a generation job and wait for completion",
|
|
2948
3101
|
" generate wait Wait for an existing job to reach a terminal state",
|
|
2949
3102
|
" generate get Fetch the current state of a job",
|
|
@@ -3027,6 +3180,62 @@ function renderCommandHelp(command) {
|
|
|
3027
3180
|
" --json Emit JSON envelope instead of human output",
|
|
3028
3181
|
""
|
|
3029
3182
|
].join("\n");
|
|
3183
|
+
case "template":
|
|
3184
|
+
return [
|
|
3185
|
+
"Usage: clickraft template <subcommand> [options]",
|
|
3186
|
+
"",
|
|
3187
|
+
"Subcommands:",
|
|
3188
|
+
" list List available templates",
|
|
3189
|
+
" get Fetch a template by ID",
|
|
3190
|
+
" find Search templates by keyword",
|
|
3191
|
+
""
|
|
3192
|
+
].join("\n");
|
|
3193
|
+
case "template list":
|
|
3194
|
+
return [
|
|
3195
|
+
"Usage: clickraft template list [options]",
|
|
3196
|
+
"",
|
|
3197
|
+
"Options:",
|
|
3198
|
+
" --scope <scope> Filter by scope: own, system, or all (default: all)",
|
|
3199
|
+
" --q <query> Free-text search query",
|
|
3200
|
+
" --tags <tag> Filter by tag (repeatable)",
|
|
3201
|
+
" --cursor <token> Pagination cursor from a previous response",
|
|
3202
|
+
" --limit <n> Max results per page (1-50, default: 20)",
|
|
3203
|
+
" --profile <name>",
|
|
3204
|
+
" --api-base-url <url>",
|
|
3205
|
+
" --token <token>",
|
|
3206
|
+
" --json",
|
|
3207
|
+
""
|
|
3208
|
+
].join("\n");
|
|
3209
|
+
case "template get":
|
|
3210
|
+
return [
|
|
3211
|
+
"Usage: clickraft template get <id> [options]",
|
|
3212
|
+
"",
|
|
3213
|
+
"Fetches a single template by its ID, including declared parameters.",
|
|
3214
|
+
"",
|
|
3215
|
+
"Options:",
|
|
3216
|
+
" --profile <name>",
|
|
3217
|
+
" --api-base-url <url>",
|
|
3218
|
+
" --token <token>",
|
|
3219
|
+
" --json",
|
|
3220
|
+
""
|
|
3221
|
+
].join("\n");
|
|
3222
|
+
case "template find":
|
|
3223
|
+
return [
|
|
3224
|
+
"Usage: clickraft template find <query> [options]",
|
|
3225
|
+
"",
|
|
3226
|
+
"Searches templates by keyword. Shorthand for `template list --q <query>`.",
|
|
3227
|
+
"",
|
|
3228
|
+
"Options:",
|
|
3229
|
+
" --tags <tag> Filter by tag (repeatable)",
|
|
3230
|
+
" --scope <scope> Filter by scope: own, system, or all (default: all)",
|
|
3231
|
+
" --limit <n> Max results per page (1-50, default: 20)",
|
|
3232
|
+
" --cursor <token> Pagination cursor from a previous response",
|
|
3233
|
+
" --profile <name>",
|
|
3234
|
+
" --api-base-url <url>",
|
|
3235
|
+
" --token <token>",
|
|
3236
|
+
" --json",
|
|
3237
|
+
""
|
|
3238
|
+
].join("\n");
|
|
3030
3239
|
case "generate":
|
|
3031
3240
|
return [
|
|
3032
3241
|
"Usage: clickraft generate <subcommand> [options]",
|
|
@@ -3148,6 +3357,14 @@ function matchNewCommand(argv) {
|
|
|
3148
3357
|
if (sub === void 0 || sub.startsWith("-")) return { kind: "sub-help", verb: "jobs" };
|
|
3149
3358
|
return { kind: "unknown-sub", verb: "jobs", sub };
|
|
3150
3359
|
}
|
|
3360
|
+
if (verb === "template") {
|
|
3361
|
+
const sub = argv[1];
|
|
3362
|
+
if (sub === "list") return { kind: "cmd", path: "template.list", verbTokenCount: 2 };
|
|
3363
|
+
if (sub === "get") return { kind: "cmd", path: "template.get", verbTokenCount: 2 };
|
|
3364
|
+
if (sub === "find") return { kind: "cmd", path: "template.find", verbTokenCount: 2 };
|
|
3365
|
+
if (sub === void 0 || sub.startsWith("-")) return { kind: "sub-help", verb: "template" };
|
|
3366
|
+
return { kind: "unknown-sub", verb: "template", sub };
|
|
3367
|
+
}
|
|
3151
3368
|
return null;
|
|
3152
3369
|
}
|
|
3153
3370
|
async function runNewCommand(newCmd, options, stdout, stderr) {
|
|
@@ -3198,6 +3415,12 @@ async function runNewCommand(newCmd, options, stdout, stderr) {
|
|
|
3198
3415
|
return await runJobsWait(argvAfterVerb, ctx, rc);
|
|
3199
3416
|
case "upload":
|
|
3200
3417
|
return await runUploadCmd(argvAfterVerb, ctx, rc);
|
|
3418
|
+
case "template.list":
|
|
3419
|
+
return await runTemplateList(argvAfterVerb, ctx, rc);
|
|
3420
|
+
case "template.get":
|
|
3421
|
+
return await runTemplateGet(argvAfterVerb, ctx, rc);
|
|
3422
|
+
case "template.find":
|
|
3423
|
+
return await runTemplateFind(argvAfterVerb, ctx, rc);
|
|
3201
3424
|
}
|
|
3202
3425
|
} catch (err) {
|
|
3203
3426
|
if (isAbortedError(err, options.signal)) {
|
|
@@ -3392,6 +3615,87 @@ function exitCodeForResult(result) {
|
|
|
3392
3615
|
}
|
|
3393
3616
|
return 0;
|
|
3394
3617
|
}
|
|
3618
|
+
async function runTemplateList(argv, ctx, rc) {
|
|
3619
|
+
const parsed = parseArgs(argv, {
|
|
3620
|
+
string: [...COMMON_RICH_STRING_FLAGS, "scope", "q", "cursor", "limit"],
|
|
3621
|
+
boolean: [...COMMON_RICH_BOOL_FLAGS],
|
|
3622
|
+
array: ["tags"]
|
|
3623
|
+
});
|
|
3624
|
+
const result = await listTemplates({
|
|
3625
|
+
q: parsed.string.q,
|
|
3626
|
+
tags: parsed.array.tags,
|
|
3627
|
+
scope: parsed.string.scope,
|
|
3628
|
+
cursor: parsed.string.cursor,
|
|
3629
|
+
limit: optionalInt(parsed.string.limit, "limit"),
|
|
3630
|
+
profile: parsed.string.profile,
|
|
3631
|
+
apiBaseUrl: parsed.string["api-base-url"],
|
|
3632
|
+
token: parsed.string.token,
|
|
3633
|
+
signal: rc.signal
|
|
3634
|
+
});
|
|
3635
|
+
ctx.nextCursor = result.cursor ?? void 0;
|
|
3636
|
+
emitTemplateList(result, ctx, rc);
|
|
3637
|
+
return 0;
|
|
3638
|
+
}
|
|
3639
|
+
async function runTemplateGet(argv, ctx, rc) {
|
|
3640
|
+
const parsed = parseArgs(argv, {
|
|
3641
|
+
string: [...COMMON_RICH_STRING_FLAGS],
|
|
3642
|
+
boolean: [...COMMON_RICH_BOOL_FLAGS]
|
|
3643
|
+
});
|
|
3644
|
+
const id = parsed.positional[0];
|
|
3645
|
+
if (!id) throw new ArgError("Missing required <id> argument.");
|
|
3646
|
+
const detail = await getTemplate({
|
|
3647
|
+
id,
|
|
3648
|
+
profile: parsed.string.profile,
|
|
3649
|
+
apiBaseUrl: parsed.string["api-base-url"],
|
|
3650
|
+
token: parsed.string.token,
|
|
3651
|
+
signal: rc.signal
|
|
3652
|
+
});
|
|
3653
|
+
emitTemplateDetail(detail, ctx, rc);
|
|
3654
|
+
return 0;
|
|
3655
|
+
}
|
|
3656
|
+
async function runTemplateFind(argv, ctx, rc) {
|
|
3657
|
+
const parsed = parseArgs(argv, {
|
|
3658
|
+
string: [...COMMON_RICH_STRING_FLAGS, "scope", "cursor", "limit"],
|
|
3659
|
+
boolean: [...COMMON_RICH_BOOL_FLAGS],
|
|
3660
|
+
array: ["tags"]
|
|
3661
|
+
});
|
|
3662
|
+
const query = parsed.positional[0];
|
|
3663
|
+
if (!query) throw new ArgError("Missing required <query> argument.");
|
|
3664
|
+
const result = await findTemplates({
|
|
3665
|
+
query,
|
|
3666
|
+
tags: parsed.array.tags,
|
|
3667
|
+
scope: parsed.string.scope,
|
|
3668
|
+
cursor: parsed.string.cursor,
|
|
3669
|
+
limit: optionalInt(parsed.string.limit, "limit"),
|
|
3670
|
+
profile: parsed.string.profile,
|
|
3671
|
+
apiBaseUrl: parsed.string["api-base-url"],
|
|
3672
|
+
token: parsed.string.token,
|
|
3673
|
+
signal: rc.signal
|
|
3674
|
+
});
|
|
3675
|
+
ctx.nextCursor = result.cursor ?? void 0;
|
|
3676
|
+
emitTemplateList(result, ctx, rc);
|
|
3677
|
+
return 0;
|
|
3678
|
+
}
|
|
3679
|
+
function emitTemplateList(result, ctx, rc) {
|
|
3680
|
+
if (rc.signal?.aborted) {
|
|
3681
|
+
throw new AuthError("AUTH_FLOW_CANCELLED", "Cancelled.");
|
|
3682
|
+
}
|
|
3683
|
+
if (rc.jsonMode) {
|
|
3684
|
+
rc.stdout.write(JSON.stringify(wrapSuccess(result, ctx)) + "\n");
|
|
3685
|
+
return;
|
|
3686
|
+
}
|
|
3687
|
+
renderTemplatesList(result, rc.stdout);
|
|
3688
|
+
}
|
|
3689
|
+
function emitTemplateDetail(detail, ctx, rc) {
|
|
3690
|
+
if (rc.signal?.aborted) {
|
|
3691
|
+
throw new AuthError("AUTH_FLOW_CANCELLED", "Cancelled.");
|
|
3692
|
+
}
|
|
3693
|
+
if (rc.jsonMode) {
|
|
3694
|
+
rc.stdout.write(JSON.stringify(wrapSuccess(detail, ctx)) + "\n");
|
|
3695
|
+
return;
|
|
3696
|
+
}
|
|
3697
|
+
renderTemplateDetail(detail, rc.stdout);
|
|
3698
|
+
}
|
|
3395
3699
|
|
|
3396
3700
|
// src/index.ts
|
|
3397
3701
|
var __filename2 = fileURLToPath(import.meta.url);
|