@deessejs/cli 1.1.0 → 1.1.1

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,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,624 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import pc2 from 'picocolors';
4
+ import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync } from 'fs';
5
+ import { join, resolve } from 'path';
6
+ import ora from 'ora';
7
+ import { TemplatesListResponseV1 } from '@workspace/contracts/v1';
8
+ import { homedir } from 'os';
9
+ import { spawn as spawn$1 } from 'child_process';
10
+
11
+ // src/constants.ts
12
+ var DEFAULT_API_URL = "https://app.deessejs.com/api/v1/templates";
13
+ var USER_AGENT = "deessejs-cli/0.1.0 (https://deessejs.com)";
14
+ var EXIT_ERROR = 1;
15
+
16
+ // src/errors.ts
17
+ var CliError = class extends Error {
18
+ code;
19
+ hint;
20
+ constructor(code, message, hint) {
21
+ super(message);
22
+ this.name = "CliError";
23
+ this.code = code;
24
+ this.hint = hint;
25
+ }
26
+ exitCode = () => EXIT_ERROR;
27
+ };
28
+ var notFound = (slug, available) => new CliError(
29
+ "not_found",
30
+ `template "${slug}" not found`,
31
+ `available templates: ${available.join(", ")}`
32
+ );
33
+ var networkError = (detail) => new CliError(
34
+ "network_error",
35
+ `could not reach the templates endpoint`,
36
+ detail
37
+ );
38
+ var gitNotInstalled = () => new CliError(
39
+ "git_not_installed",
40
+ "`git` is not installed or not on PATH",
41
+ "install git from https://git-scm.com and try again"
42
+ );
43
+ var targetExists = (dir) => new CliError(
44
+ "target_exists",
45
+ `target directory "${dir}" already exists`,
46
+ "remove the directory or pass --force to overwrite"
47
+ );
48
+ var installFailed = (pm, code) => new CliError(
49
+ "install_failed",
50
+ `${pm} install exited with code ${code ?? "unknown"}`,
51
+ "check the output above, then run the install command manually inside the cloned directory"
52
+ );
53
+ var parseError = (detail) => new CliError(
54
+ "parse_error",
55
+ "templates endpoint returned malformed data",
56
+ detail
57
+ );
58
+ var internal = (detail) => new CliError("internal", "unexpected internal error", detail);
59
+ var CACHE_DIR = join(homedir(), ".deessejs");
60
+ var ensureDir = () => {
61
+ if (!existsSync(CACHE_DIR)) {
62
+ mkdirSync(CACHE_DIR, { recursive: true });
63
+ }
64
+ };
65
+ var cachePath = (name) => join(CACHE_DIR, name);
66
+ var readDiskCache = (name) => {
67
+ const path = cachePath(name);
68
+ if (!existsSync(path)) return null;
69
+ try {
70
+ const raw = readFileSync(path, "utf8");
71
+ return JSON.parse(raw);
72
+ } catch {
73
+ return null;
74
+ }
75
+ };
76
+ var writeDiskCache = (name, body, etag) => {
77
+ ensureDir();
78
+ const entry = {
79
+ etag,
80
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
81
+ body
82
+ };
83
+ const target = cachePath(name);
84
+ const tmp = `${target}.tmp`;
85
+ writeFileSync(tmp, JSON.stringify(entry), "utf8");
86
+ try {
87
+ renameSync(tmp, target);
88
+ } catch {
89
+ writeFileSync(target, JSON.stringify(entry), "utf8");
90
+ }
91
+ };
92
+
93
+ // src/fetch-with-retry.ts
94
+ var BASE_DELAYS_MS = [250, 750, 2e3];
95
+ var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
96
+ var jitter = (base) => base + Math.floor(Math.random() * 100);
97
+ var fetchWithRetry = async (opts) => {
98
+ const maxAttempts = opts.maxAttempts ?? 3;
99
+ const headers = {
100
+ "user-agent": USER_AGENT,
101
+ accept: "application/json",
102
+ ...opts.headers ?? {}
103
+ };
104
+ let lastNetworkError;
105
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
106
+ let res;
107
+ try {
108
+ res = await fetch(opts.apiUrl, { headers });
109
+ } catch (e) {
110
+ lastNetworkError = e;
111
+ if (attempt < maxAttempts - 1) {
112
+ await sleep(jitter(BASE_DELAYS_MS[attempt] ?? 2e3));
113
+ continue;
114
+ }
115
+ throw e;
116
+ }
117
+ if (res.status === 429) {
118
+ const resetHeader = res.headers.get("X-RateLimit-Reset");
119
+ const resetSec = resetHeader ? Number(resetHeader.split(",")[0]) : NaN;
120
+ const waitMs = Number.isFinite(resetSec) && resetSec > 0 ? Math.min(resetSec * 1e3, 3e4) : jitter(BASE_DELAYS_MS[attempt] ?? 2e3);
121
+ if (attempt < maxAttempts - 1) {
122
+ await sleep(waitMs);
123
+ continue;
124
+ }
125
+ }
126
+ if (res.status >= 500 && attempt < maxAttempts - 1) {
127
+ await sleep(jitter(BASE_DELAYS_MS[attempt] ?? 2e3));
128
+ continue;
129
+ }
130
+ const bodyText = await res.text();
131
+ return {
132
+ status: res.status,
133
+ bodyText,
134
+ etag: res.headers.get("ETag")
135
+ };
136
+ }
137
+ throw lastNetworkError ?? new Error("fetchWithRetry: exhausted attempts");
138
+ };
139
+
140
+ // src/cli-self-version.ts
141
+ var CLI_PACKAGE_VERSION = "1.1.0";
142
+ var readPackageVersion = () => CLI_PACKAGE_VERSION;
143
+
144
+ // src/version-check.ts
145
+ var SEMVER_RE = /^\d+\.\d+\.\d+$/;
146
+ var parseSemver = (v) => {
147
+ if (!SEMVER_RE.test(v)) return null;
148
+ const [major, minor, patch] = v.split(".").map(Number);
149
+ return [major ?? 0, minor ?? 0, patch ?? 0];
150
+ };
151
+ var compareSemver = (a, b) => {
152
+ const pa = parseSemver(a);
153
+ const pb = parseSemver(b);
154
+ if (!pa || !pb) return 0;
155
+ if (pa[0] !== pb[0]) return pa[0] - pb[0];
156
+ if (pa[1] !== pb[1]) return pa[1] - pb[1];
157
+ return pa[2] - pb[2];
158
+ };
159
+ var maybeWarnAboutOutdatedCli = async (apiUrl) => {
160
+ let bodyText;
161
+ try {
162
+ const res = await fetchWithRetry({
163
+ apiUrl: apiUrl.replace(/\/templates$/, "/cli-version")
164
+ });
165
+ if (res.status !== 200) return;
166
+ bodyText = res.bodyText;
167
+ } catch {
168
+ return;
169
+ }
170
+ let parsed;
171
+ try {
172
+ parsed = JSON.parse(bodyText);
173
+ } catch {
174
+ return;
175
+ }
176
+ if (typeof parsed.version !== "string" || typeof parsed.minSupported !== "string") {
177
+ return;
178
+ }
179
+ const localVersion = readPackageVersion();
180
+ if (compareSemver(localVersion, parsed.minSupported) < 0) {
181
+ process.stderr.write(
182
+ `
183
+ \u26A0 deessejs-cli ${localVersion} is below the minimum supported version (${parsed.minSupported}).
184
+ Upgrade: pnpm dlx @deessejs/cli@latest
185
+
186
+ `
187
+ );
188
+ }
189
+ };
190
+
191
+ // src/api.ts
192
+ var TEMPLATES_CACHE_FILE = "templates.json";
193
+ var buildHeaders = (etag) => {
194
+ const headers = {
195
+ "user-agent": USER_AGENT,
196
+ accept: "application/json"
197
+ };
198
+ if (etag) headers["If-None-Match"] = etag;
199
+ return headers;
200
+ };
201
+ var fetchTemplates = async (apiUrl, options = {}) => {
202
+ if (!options.skipVersionCheck) {
203
+ await maybeWarnAboutOutdatedCli(apiUrl);
204
+ }
205
+ const cached = readDiskCache(TEMPLATES_CACHE_FILE);
206
+ if (options.offline) {
207
+ if (!cached) {
208
+ throw networkError(
209
+ "no cached registry available. Run without --offline first to populate the cache."
210
+ );
211
+ }
212
+ return cached.body.templates;
213
+ }
214
+ let res;
215
+ try {
216
+ res = await fetchWithRetry({
217
+ apiUrl,
218
+ headers: buildHeaders(cached?.etag ?? null)
219
+ });
220
+ } catch (e) {
221
+ if (cached) {
222
+ process.stderr.write(
223
+ "\u26A0 Using cached registry (offline \u2014 backend unreachable)\n"
224
+ );
225
+ return cached.body.templates;
226
+ }
227
+ throw networkError(
228
+ `fetch failed: ${e instanceof Error ? e.message : String(e)}`
229
+ );
230
+ }
231
+ if (res.status === 304 && cached) {
232
+ return cached.body.templates;
233
+ }
234
+ if (res.status < 200 || res.status >= 300) {
235
+ if (cached) {
236
+ process.stderr.write(
237
+ `\u26A0 Using cached registry (offline \u2014 server returned HTTP ${res.status})
238
+ `
239
+ );
240
+ return cached.body.templates;
241
+ }
242
+ throw networkError(`endpoint returned HTTP ${res.status}`);
243
+ }
244
+ let body;
245
+ try {
246
+ body = JSON.parse(res.bodyText);
247
+ } catch (e) {
248
+ throw parseError(
249
+ `endpoint returned non-JSON body: ${e instanceof Error ? e.message : String(e)}`
250
+ );
251
+ }
252
+ const result = TemplatesListResponseV1.safeParse(body);
253
+ if (!result.success) {
254
+ throw parseError(
255
+ `response shape mismatch: ${result.error.issues.map((i) => `${i.path.join(".")} (${i.code})`).join(", ")}`
256
+ );
257
+ }
258
+ writeDiskCache(TEMPLATES_CACHE_FILE, result.data, res.etag);
259
+ return result.data.templates;
260
+ };
261
+ var printJson = (value) => {
262
+ process.stdout.write(JSON.stringify(value, null, 2) + "\n");
263
+ };
264
+ var printError = (err) => {
265
+ process.stderr.write(
266
+ `${pc2.red("Error")}: ${err.message}
267
+ ` + (err.hint ? `${pc2.dim("Hint")}: ${err.hint}
268
+ ` : "") + `${pc2.dim("Code")}: ${err.code}
269
+ `
270
+ );
271
+ };
272
+ var printTemplatesTable = (templates) => {
273
+ if (templates.length === 0) {
274
+ process.stdout.write(pc2.dim("No templates available.\n"));
275
+ return;
276
+ }
277
+ const headers = ["slug", "name", "category", "license"];
278
+ const rows = templates.map((t) => [
279
+ t.slug,
280
+ t.name,
281
+ t.category,
282
+ t.license
283
+ ]);
284
+ printAlignedTable([headers, ...rows]);
285
+ };
286
+ var printTemplateInfo = (t) => {
287
+ const lines = [
288
+ ["slug", t.slug],
289
+ ["name", t.name],
290
+ ["description", t.description],
291
+ ["category", t.category],
292
+ ["license", t.license],
293
+ ["repo", `${t.owner}/${t.repo}`],
294
+ ["labels", t.labels.join(", ") || pc2.dim("(none)")]
295
+ ];
296
+ if (t.image) lines.push(["image", t.image]);
297
+ const labelWidth = Math.max(...lines.map(([l]) => l.length));
298
+ for (const [label, value] of lines) {
299
+ process.stdout.write(
300
+ `${pc2.dim(label.padEnd(labelWidth))} ${value}
301
+ `
302
+ );
303
+ }
304
+ };
305
+ var printAlignedTable = (rows) => {
306
+ const firstRow = rows[0];
307
+ if (!firstRow) return;
308
+ const widths = firstRow.map(
309
+ (_, col) => Math.max(...rows.map((row) => row[col]?.length ?? 0))
310
+ );
311
+ for (const row of rows) {
312
+ process.stdout.write(
313
+ row.map((cell, i) => cell.padEnd(widths[i] ?? 0)).join(" ") + "\n"
314
+ );
315
+ }
316
+ };
317
+ var spawn = (command, args, options = {}) => {
318
+ const { cwd, env, stdio = "inherit", reject = false } = options;
319
+ return new Promise((resolve2, rejectFn) => {
320
+ const child = spawn$1(command, args, {
321
+ cwd,
322
+ env: env ?? process.env,
323
+ stdio,
324
+ shell: false
325
+ });
326
+ child.on("error", (err) => rejectFn(err));
327
+ child.on("exit", (code) => {
328
+ const exit = code ?? 1;
329
+ if (reject && exit !== 0) {
330
+ rejectFn(new Error(`${command} exited with code ${exit}`));
331
+ } else {
332
+ resolve2(exit);
333
+ }
334
+ });
335
+ });
336
+ };
337
+
338
+ // src/utils/git.ts
339
+ var cloneRepo = async (url, dir, requestedRef) => {
340
+ const refs = requestedRef ? [requestedRef] : ["main", "master"];
341
+ const attempts = [];
342
+ for (const ref of refs) {
343
+ attempts.push(ref);
344
+ const code = await spawn(
345
+ "git",
346
+ ["clone", "--depth", "1", "--branch", ref, url, dir],
347
+ { stdio: "inherit", reject: false }
348
+ );
349
+ if (code === 0) {
350
+ return { ref, attempts };
351
+ }
352
+ }
353
+ const probe = await spawn("git", ["--version"], {
354
+ stdio: "ignore",
355
+ reject: false
356
+ });
357
+ if (probe !== 0) {
358
+ throw gitNotInstalled();
359
+ }
360
+ throw new Error(
361
+ `git clone failed for refs: ${refs.join(", ")}. Tried: ${attempts.join(", ")}.`
362
+ );
363
+ };
364
+ var detectPackageManager = (cwd) => {
365
+ const pkg = readPackageJson(cwd);
366
+ if (pkg?.packageManager) {
367
+ const pm = parsePackageManagerField(pkg.packageManager);
368
+ if (pm) return pm;
369
+ }
370
+ if (existsSync(join(cwd, "pnpm-lock.yaml"))) return { pm: "pnpm" };
371
+ if (existsSync(join(cwd, "bun.lockb"))) return { pm: "bun" };
372
+ if (existsSync(join(cwd, "yarn.lock"))) return { pm: "yarn" };
373
+ if (existsSync(join(cwd, "package-lock.json"))) return { pm: "npm" };
374
+ return null;
375
+ };
376
+ var getInstallCommand = (info) => {
377
+ switch (info.pm) {
378
+ case "pnpm":
379
+ return "pnpm install";
380
+ case "npm":
381
+ return "npm install";
382
+ case "yarn":
383
+ return "yarn install";
384
+ case "bun":
385
+ return "bun install";
386
+ }
387
+ };
388
+ var readPackageJson = (cwd) => {
389
+ const path = join(cwd, "package.json");
390
+ if (!existsSync(path)) return null;
391
+ try {
392
+ return JSON.parse(readFileSync(path, "utf8"));
393
+ } catch {
394
+ return null;
395
+ }
396
+ };
397
+ var parsePackageManagerField = (raw) => {
398
+ const name = raw.split("@")[0]?.trim().toLowerCase();
399
+ if (name === "pnpm" || name === "npm" || name === "yarn" || name === "bun") {
400
+ return { pm: name, raw };
401
+ }
402
+ return null;
403
+ };
404
+
405
+ // src/commands/init.ts
406
+ var initCommand = new Command("init").description("Clone a template repo + install dependencies").argument("<slug>", "template slug (use `deessejs list` to see options)").option("--pm <name>", "override detected package manager (pnpm|npm|yarn|bun)").option("--dir <path>", "target directory (default: ./<slug>)").option("--ref <branch>", "git ref to clone (default: tries main, falls back to master)").option("--no-install", "skip the install step").option("--force", "overwrite target directory if it exists").option("--json", "JSON output for scripting").action(
407
+ async (slug, opts) => {
408
+ const apiUrl = initCommand.parent?.getOptionValue("apiUrl");
409
+ const offline = initCommand.parent?.getOptionValue("offline");
410
+ try {
411
+ const templates = await fetchTemplates(
412
+ apiUrl ?? process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL,
413
+ { offline: Boolean(offline) }
414
+ );
415
+ const template = templates.find((t) => t.slug === slug);
416
+ if (!template) {
417
+ throw notFound(
418
+ slug,
419
+ templates.map((t) => t.slug)
420
+ );
421
+ }
422
+ const dir = resolve(process.cwd(), opts.dir ?? `./${slug}`);
423
+ if (existsSync(dir) && !opts.force) {
424
+ throw targetExists(dir);
425
+ }
426
+ const repoUrl = template.cloneUrl ?? `https://github.com/${template.owner}/${template.repo}`;
427
+ const cloneSpinner = ora(`Cloning ${pc2.cyan(template.owner + "/" + template.repo)}...`).start();
428
+ let cloneResult;
429
+ try {
430
+ cloneResult = await cloneRepo(repoUrl, dir, opts.ref);
431
+ cloneSpinner.succeed(`Cloned into ${pc2.cyan(dir)} (ref: ${cloneResult.ref})`);
432
+ } catch (err) {
433
+ cloneSpinner.fail("Clone failed");
434
+ throw err;
435
+ }
436
+ if (!opts.install) {
437
+ if (opts.json) {
438
+ printJson({
439
+ ok: true,
440
+ slug: template.slug,
441
+ dir,
442
+ ref: cloneResult.ref,
443
+ installed: false
444
+ });
445
+ } else {
446
+ console.log(pc2.dim(`
447
+ Next: cd ${dir} && <your package manager> install
448
+ `));
449
+ }
450
+ return;
451
+ }
452
+ const VALID_PMS = ["pnpm", "npm", "yarn", "bun"];
453
+ const pmInfo = opts.pm && VALID_PMS.includes(opts.pm) ? { pm: opts.pm } : detectPackageManager(dir);
454
+ if (!pmInfo) {
455
+ console.log(
456
+ pc2.yellow(
457
+ "\nNo package manager detected (no packageManager field, no lockfile)."
458
+ )
459
+ );
460
+ console.log(
461
+ pc2.dim("Skipping install. Run your install command manually inside the directory.\n")
462
+ );
463
+ } else {
464
+ const installSpinner = ora(
465
+ `Installing dependencies via ${pc2.cyan(pmInfo.pm)}...`
466
+ ).start();
467
+ const cmd = getInstallCommand(pmInfo);
468
+ const cmdParts = cmd.split(" ");
469
+ const bin = cmdParts[0] ?? "npm";
470
+ const args = cmdParts.slice(1);
471
+ const code = await spawn(bin, args, { cwd: dir, stdio: "inherit", reject: false });
472
+ if (code !== 0) {
473
+ installSpinner.fail(`${pmInfo.pm} install failed`);
474
+ throw installFailed(pmInfo.pm, code);
475
+ }
476
+ installSpinner.succeed("Dependencies installed");
477
+ }
478
+ if (opts.json) {
479
+ printJson({
480
+ ok: true,
481
+ slug: template.slug,
482
+ dir,
483
+ ref: cloneResult.ref,
484
+ installed: pmInfo !== null,
485
+ packageManager: pmInfo?.pm ?? null
486
+ });
487
+ } else {
488
+ console.log();
489
+ console.log(pc2.green("\u2713 Template ready"));
490
+ console.log(pc2.dim(` cd ${dir}`));
491
+ console.log(
492
+ pc2.dim(
493
+ pmInfo ? ` ${getInstallCommand(pmInfo).split(" ")[0]} dev` : ` install deps, then start`
494
+ )
495
+ );
496
+ console.log();
497
+ }
498
+ } catch (err) {
499
+ if (err instanceof Error && err.name === "CliError") {
500
+ if (opts.json) {
501
+ printJson({
502
+ ok: false,
503
+ code: err.code,
504
+ message: err.message,
505
+ hint: err.hint
506
+ });
507
+ } else {
508
+ printError(err);
509
+ }
510
+ process.exit(err.exitCode?.() ?? 1);
511
+ }
512
+ throw internal(err instanceof Error ? err.message : String(err));
513
+ }
514
+ }
515
+ );
516
+ var listCommand = new Command("list").description("List available templates").option("--category <name>", "filter to a single category").option("--json", "JSON output for scripting").action(
517
+ async (opts, command) => {
518
+ const apiUrl = command.parent?.getOptionValue("apiUrl");
519
+ const offline = command.parent?.getOptionValue("offline");
520
+ const spinner = opts.json ? null : ora(offline ? "Reading cached templates..." : "Fetching templates...").start();
521
+ try {
522
+ const all = await fetchTemplates(
523
+ apiUrl ?? process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL,
524
+ { offline: Boolean(offline) }
525
+ );
526
+ const filtered = opts.category ? all.filter((t) => t.category === opts.category) : all;
527
+ spinner?.stop();
528
+ if (opts.json) {
529
+ printJson({ templates: filtered });
530
+ } else {
531
+ if (opts.category) {
532
+ console.log(pc2.dim(`Category: ${opts.category}`));
533
+ }
534
+ printTemplatesTable(filtered);
535
+ console.log();
536
+ console.log(
537
+ pc2.dim(
538
+ `${filtered.length} template${filtered.length === 1 ? "" : "s"}.` + (opts.category ? "" : " Use --category <name> to filter, --json for scripting.")
539
+ )
540
+ );
541
+ }
542
+ } catch (err) {
543
+ spinner?.fail("Failed to fetch templates");
544
+ if (err instanceof Error && err.name === "CliError") {
545
+ if (opts.json) {
546
+ printJson({
547
+ ok: false,
548
+ code: err.code,
549
+ message: err.message,
550
+ hint: err.hint
551
+ });
552
+ } else {
553
+ printError(err);
554
+ }
555
+ process.exit(1);
556
+ }
557
+ throw internal(err instanceof Error ? err.message : String(err));
558
+ }
559
+ }
560
+ );
561
+ var infoCommand = new Command("info").description("Show details for one template").argument("<slug>", "template slug").option("--json", "JSON output for scripting").action(
562
+ async (slug, opts, command) => {
563
+ const apiUrl = command.parent?.getOptionValue("apiUrl");
564
+ const offline = command.parent?.getOptionValue("offline");
565
+ const spinner = opts.json ? null : ora(offline ? "Reading cached template..." : "Fetching template...").start();
566
+ try {
567
+ const all = await fetchTemplates(
568
+ apiUrl ?? process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL,
569
+ { offline: Boolean(offline) }
570
+ );
571
+ const template = all.find((t) => t.slug === slug);
572
+ spinner?.stop();
573
+ if (!template) {
574
+ throw notFound(slug, all.map((t) => t.slug));
575
+ }
576
+ if (opts.json) {
577
+ printJson({ template });
578
+ } else {
579
+ printTemplateInfo(template);
580
+ console.log();
581
+ console.log(
582
+ `Install: ${`deessejs init ${template.slug}`}`
583
+ );
584
+ }
585
+ } catch (err) {
586
+ spinner?.fail("Failed to fetch template");
587
+ if (err instanceof Error && err.name === "CliError") {
588
+ if (opts.json) {
589
+ printJson({
590
+ ok: false,
591
+ code: err.code,
592
+ message: err.message,
593
+ hint: err.hint
594
+ });
595
+ } else {
596
+ printError(err);
597
+ }
598
+ process.exit(1);
599
+ }
600
+ throw internal(err instanceof Error ? err.message : String(err));
601
+ }
602
+ }
603
+ );
604
+
605
+ // src/index.ts
606
+ var program = new Command();
607
+ program.name("deessejs").description("CLI for the DeesseJS template registry").version("0.1.0").option("--api-url <url>", "templates endpoint URL", process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL).option("--offline", "skip the network, serve the on-disk cache (~/.deessejs/templates.json)");
608
+ program.addCommand(listCommand);
609
+ program.addCommand(infoCommand);
610
+ program.addCommand(initCommand);
611
+ program.parseAsync(process.argv).catch((err) => {
612
+ process.stderr.write(
613
+ `${pc2.red("Internal error")}: ${err instanceof Error ? err.message : String(err)}
614
+ `
615
+ );
616
+ if (process.env.DEESSEJS_DEBUG) {
617
+ process.stderr.write(`
618
+ ${err instanceof Error && err.stack ? err.stack : ""}
619
+ `);
620
+ }
621
+ process.exit(1);
622
+ });
623
+ //# sourceMappingURL=index.js.map
624
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/cache.ts","../src/fetch-with-retry.ts","../src/cli-self-version.ts","../src/version-check.ts","../src/api.ts","../src/output.ts","../src/utils/spawn.ts","../src/utils/git.ts","../src/utils/detect-pm.ts","../src/commands/init.ts","../src/commands/list.ts","../src/commands/info.ts","../src/index.ts"],"names":["resolve","pc","nodeSpawn","existsSync","join","readFileSync","Command","ora"],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_API_URL = \"https://app.deessejs.com/api/v1/templates\"\n\nexport const USER_AGENT = \"deessejs-cli/0.1.0 (https://deessejs.com)\"\n\nexport const EXIT_SUCCESS = 0\nexport const EXIT_ERROR = 1\n","import { EXIT_ERROR } from \"./constants.js\"\n\nexport type CliErrorCode =\n | \"not_found\"\n | \"network_error\"\n | \"git_not_installed\"\n | \"target_exists\"\n | \"install_failed\"\n | \"parse_error\"\n | \"internal\"\n\nexport class CliError extends Error {\n public readonly code: CliErrorCode\n public readonly hint: string | undefined\n\n constructor(code: CliErrorCode, message: string, hint?: string) {\n super(message)\n this.name = \"CliError\"\n this.code = code\n this.hint = hint\n }\n\n public exitCode = (): number => EXIT_ERROR\n}\n\nexport const notFound = (slug: string, available: string[]): CliError =>\n new CliError(\n \"not_found\",\n `template \"${slug}\" not found`,\n `available templates: ${available.join(\", \")}`,\n )\n\nexport const networkError = (detail: string): CliError =>\n new CliError(\n \"network_error\",\n `could not reach the templates endpoint`,\n detail,\n )\n\nexport const gitNotInstalled = (): CliError =>\n new CliError(\n \"git_not_installed\",\n \"`git` is not installed or not on PATH\",\n \"install git from https://git-scm.com and try again\",\n )\n\nexport const targetExists = (dir: string): CliError =>\n new CliError(\n \"target_exists\",\n `target directory \"${dir}\" already exists`,\n \"remove the directory or pass --force to overwrite\",\n )\n\nexport const installFailed = (\n pm: string,\n code: number | null,\n): CliError =>\n new CliError(\n \"install_failed\",\n `${pm} install exited with code ${code ?? \"unknown\"}`,\n \"check the output above, then run the install command manually inside the cloned directory\",\n )\n\nexport const parseError = (detail: string): CliError =>\n new CliError(\n \"parse_error\",\n \"templates endpoint returned malformed data\",\n detail,\n )\n\nexport const internal = (detail: string): CliError =>\n new CliError(\"internal\", \"unexpected internal error\", detail)","import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\n\n/**\n * On-disk response cache for the CLI.\n *\n * Layout: one file per endpoint under ~/.deessejs/. Each file holds the\n * raw response body plus the ETag the server returned, so we can reissue\n * If-None-Match on the next call and serve the cached body on a 304.\n *\n * No TTL: the server is the source of truth for freshness. A cache entry\n * is \"valid\" if either (a) we can revalidate it against the server and\n * the server says 304, or (b) we're in --offline mode and any prior\n * response is better than nothing.\n *\n * Corruption policy: a malformed file is treated as cache-miss. We do\n * not auto-overwrite it — if the user manually edited a cache file, we\n * surface that as a warning and let them decide. The next successful\n * network call will overwrite the file normally.\n */\nexport type CacheEntry<T = unknown> = {\n etag: string | null\n fetchedAt: string\n body: T\n}\n\nexport const CACHE_DIR = join(homedir(), \".deessejs\")\n\nconst ensureDir = (): void => {\n if (!existsSync(CACHE_DIR)) {\n mkdirSync(CACHE_DIR, { recursive: true })\n }\n}\n\nconst cachePath = (name: string): string => join(CACHE_DIR, name)\n\nexport const readDiskCache = <T>(name: string): CacheEntry<T> | null => {\n const path = cachePath(name)\n if (!existsSync(path)) return null\n try {\n const raw = readFileSync(path, \"utf8\")\n return JSON.parse(raw) as CacheEntry<T>\n } catch {\n // Corrupt or unreadable. Caller logs a warning; we don't overwrite.\n return null\n }\n}\n\nexport const writeDiskCache = <T>(\n name: string,\n body: T,\n etag: string | null,\n): void => {\n ensureDir()\n const entry: CacheEntry<T> = {\n etag,\n fetchedAt: new Date().toISOString(),\n body,\n }\n // Write atomically via a temp file + rename to avoid torn writes\n // if the process is killed mid-write. tmp + rename is atomic on\n // POSIX; on Windows it's \"atomic if the destination exists\", which\n // is good enough for our use case.\n const target = cachePath(name)\n const tmp = `${target}.tmp`\n writeFileSync(tmp, JSON.stringify(entry), \"utf8\")\n // Best-effort rename. If it fails (rare on Windows), fall back to direct write.\n try {\n renameSync(tmp, target)\n } catch {\n writeFileSync(target, JSON.stringify(entry), \"utf8\")\n }\n}\n","import { USER_AGENT } from \"./constants.js\"\n\nexport type FetchRetryOptions = {\n apiUrl: string\n headers?: Record<string, string>\n /** Maximum number of attempts. Default 3. */\n maxAttempts?: number\n}\n\nexport type FetchRetryResult = {\n status: number\n bodyText: string\n etag: string | null\n}\n\nconst BASE_DELAYS_MS = [250, 750, 2000]\n\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms))\n\nconst jitter = (base: number): number =>\n base + Math.floor(Math.random() * 100)\n\n/**\n * Fetch with retry on transient failures.\n *\n * Retries on:\n * - network errors (the `fetch` itself throws)\n * - HTTP 5xx\n * - HTTP 429 (rate-limited): honors the X-RateLimit-Reset header\n * instead of the static backoff, so we don't sleep longer than needed.\n *\n * Aborts (returns the failing response) on:\n * - HTTP 4xx other than 429. A 404 on /templates will still be a 404\n * in 3 seconds; the user gets a faster error.\n *\n * Returns the final response (success or terminal failure) and a\n * `bodyText` ready to JSON.parse. The caller is responsible for parsing\n * — we don't presume the schema here.\n */\nexport const fetchWithRetry = async (\n opts: FetchRetryOptions,\n): Promise<FetchRetryResult> => {\n const maxAttempts = opts.maxAttempts ?? 3\n const headers: Record<string, string> = {\n \"user-agent\": USER_AGENT,\n accept: \"application/json\",\n ...(opts.headers ?? {}),\n }\n\n let lastNetworkError: unknown\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n let res: Response\n try {\n res = await fetch(opts.apiUrl, { headers })\n } catch (e) {\n lastNetworkError = e\n if (attempt < maxAttempts - 1) {\n await sleep(jitter(BASE_DELAYS_MS[attempt] ?? 2000))\n continue\n }\n throw e\n }\n\n if (res.status === 429) {\n // Honor X-RateLimit-Reset if the server provides it. Header is in\n // seconds; we read the first value if it's a comma list.\n const resetHeader = res.headers.get(\"X-RateLimit-Reset\")\n const resetSec = resetHeader ? Number(resetHeader.split(\",\")[0]) : NaN\n const waitMs = Number.isFinite(resetSec) && resetSec > 0\n ? Math.min(resetSec * 1000, 30_000) // cap at 30s\n : jitter(BASE_DELAYS_MS[attempt] ?? 2000)\n if (attempt < maxAttempts - 1) {\n await sleep(waitMs)\n continue\n }\n }\n\n if (res.status >= 500 && attempt < maxAttempts - 1) {\n await sleep(jitter(BASE_DELAYS_MS[attempt] ?? 2000))\n continue\n }\n\n const bodyText = await res.text()\n return {\n status: res.status,\n bodyText,\n etag: res.headers.get(\"ETag\"),\n }\n }\n\n // Unreachable in practice (the loop always either returns or throws).\n throw lastNetworkError ?? new Error(\"fetchWithRetry: exhausted attempts\")\n}\n","/**\n * The CLI's own version, read from the package metadata at build time.\n *\n * The CLI is bundled by tsup into a single `dist/index.js`, so a\n * runtime `import.meta.url` resolution back to package.json is\n * fragile (paths differ between `npx`, global install, and direct\n * invocation). We bake the version into the bundle as a constant.\n *\n * Update this when bumping apps/cli/package.json.\n */\nexport const CLI_PACKAGE_VERSION = \"1.1.0\"\n\nexport const readPackageVersion = (): string => CLI_PACKAGE_VERSION\n","import { readPackageVersion } from \"./cli-self-version.js\"\nimport { fetchWithRetry } from \"./fetch-with-retry.js\"\n\nexport type CliVersionResponse = {\n version: string\n minSupported: string\n}\n\nconst SEMVER_RE = /^\\d+\\.\\d+\\.\\d+$/\n\nconst parseSemver = (v: string): [number, number, number] | null => {\n if (!SEMVER_RE.test(v)) return null\n const [major, minor, patch] = v.split(\".\").map(Number)\n return [major ?? 0, minor ?? 0, patch ?? 0]\n}\n\nconst compareSemver = (a: string, b: string): number => {\n const pa = parseSemver(a)\n const pb = parseSemver(b)\n if (!pa || !pb) return 0 // unknown: don't warn\n if (pa[0] !== pb[0]) return pa[0] - pb[0]\n if (pa[1] !== pb[1]) return pa[1] - pb[1]\n return pa[2] - pb[2]\n}\n\n/**\n * Non-blocking version probe.\n *\n * Calls /api/v1/cli-version. If the local CLI version is strictly\n * below minSupported, prints a warning to stderr. The caller does NOT\n * abort — the user might have a workflow that depends on the old\n * version. The warning is loud (yellow, separate line) but not\n * authoritative.\n *\n * Failures (network, parse, server error) are swallowed silently: the\n * version check is best-effort, never the reason a command fails.\n */\nexport const maybeWarnAboutOutdatedCli = async (apiUrl: string): Promise<void> => {\n let bodyText: string\n try {\n const res = await fetchWithRetry({\n apiUrl: apiUrl.replace(/\\/templates$/, \"/cli-version\"),\n })\n if (res.status !== 200) return\n bodyText = res.bodyText\n } catch {\n return\n }\n\n let parsed: CliVersionResponse\n try {\n parsed = JSON.parse(bodyText) as CliVersionResponse\n } catch {\n return\n }\n if (\n typeof parsed.version !== \"string\" ||\n typeof parsed.minSupported !== \"string\"\n ) {\n return\n }\n\n const localVersion = readPackageVersion()\n if (compareSemver(localVersion, parsed.minSupported) < 0) {\n process.stderr.write(\n `\\n⚠ deessejs-cli ${localVersion} is below the minimum supported version (${parsed.minSupported}).\\n` +\n ` Upgrade: pnpm dlx @deessejs/cli@latest\\n\\n`,\n )\n }\n}\n","import { TemplatesListResponseV1 } from \"@workspace/contracts/v1\"\nimport { USER_AGENT } from \"./constants.js\"\nimport { networkError, parseError } from \"./errors.js\"\nimport { readDiskCache, writeDiskCache } from \"./cache.js\"\nimport { fetchWithRetry } from \"./fetch-with-retry.js\"\nimport { maybeWarnAboutOutdatedCli } from \"./version-check.js\"\n\nexport type Template = TemplatesListResponseV1[\"templates\"][number]\n\nexport type FetchOptions = {\n /** Skip network entirely, serve cache only. Errors if no cache exists. */\n offline?: boolean\n /** Skip the version probe. Used by tests and by the version probe itself. */\n skipVersionCheck?: boolean\n}\n\nconst TEMPLATES_CACHE_FILE = \"templates.json\"\n\nconst buildHeaders = (etag: string | null): Record<string, string> => {\n const headers: Record<string, string> = {\n \"user-agent\": USER_AGENT,\n accept: \"application/json\",\n }\n if (etag) headers[\"If-None-Match\"] = etag\n return headers\n}\n\n/**\n * Fetch the templates registry, with disk cache + retry + offline support.\n *\n * Flow:\n * 1. (If not skipVersionCheck) probe /cli-version and warn if outdated.\n * Failure here is silent — version check is best-effort.\n * 2. If --offline, return the cached body or fail with network_error.\n * 3. Network fetch with retry (250ms / 750ms / 2s backoff, honors 429\n * X-RateLimit-Reset). ETag is sent on every call when we have a cache.\n * 4. On 304, return the cached body.\n * 5. On 200, parse, write cache, return.\n * 6. On terminal failure, fall back to cache if we have one and the\n * body is still parsable. Otherwise surface the network_error.\n */\nexport const fetchTemplates = async (\n apiUrl: string,\n options: FetchOptions = {},\n): Promise<Template[]> => {\n if (!options.skipVersionCheck) {\n await maybeWarnAboutOutdatedCli(apiUrl)\n }\n\n const cached = readDiskCache<TemplatesListResponseV1>(TEMPLATES_CACHE_FILE)\n\n if (options.offline) {\n if (!cached) {\n throw networkError(\n \"no cached registry available. Run without --offline first to populate the cache.\",\n )\n }\n return cached.body.templates\n }\n\n let res: Awaited<ReturnType<typeof fetchWithRetry>>\n try {\n res = await fetchWithRetry({\n apiUrl,\n headers: buildHeaders(cached?.etag ?? null),\n })\n } catch (e) {\n // All retries exhausted on a network error. Fall back to cache.\n if (cached) {\n process.stderr.write(\n \"⚠ Using cached registry (offline — backend unreachable)\\n\",\n )\n return cached.body.templates\n }\n throw networkError(\n `fetch failed: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n\n if (res.status === 304 && cached) {\n return cached.body.templates\n }\n\n if (res.status < 200 || res.status >= 300) {\n // Non-retryable failure (4xx other than 429, or 5xx after all retries).\n if (cached) {\n process.stderr.write(\n `⚠ Using cached registry (offline — server returned HTTP ${res.status})\\n`,\n )\n return cached.body.templates\n }\n throw networkError(`endpoint returned HTTP ${res.status}`)\n }\n\n let body: unknown\n try {\n body = JSON.parse(res.bodyText)\n } catch (e) {\n throw parseError(\n `endpoint returned non-JSON body: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n\n const result = TemplatesListResponseV1.safeParse(body)\n if (!result.success) {\n throw parseError(\n `response shape mismatch: ${result.error.issues.map((i) => `${i.path.join(\".\")} (${i.code})`).join(\", \")}`,\n )\n }\n\n writeDiskCache(TEMPLATES_CACHE_FILE, result.data, res.etag)\n return result.data.templates\n}\n","import pc from \"picocolors\"\nimport type { CliError } from \"./errors.js\"\nimport type { Template } from \"./api.js\"\n\nexport const printJson = (value: unknown): void => {\n process.stdout.write(JSON.stringify(value, null, 2) + \"\\n\")\n}\n\nexport const printError = (err: CliError): void => {\n process.stderr.write(\n `${pc.red(\"Error\")}: ${err.message}\\n` +\n (err.hint ? `${pc.dim(\"Hint\")}: ${err.hint}\\n` : \"\") +\n `${pc.dim(\"Code\")}: ${err.code}\\n`,\n )\n}\n\nexport const printTemplatesTable = (templates: Template[]): void => {\n if (templates.length === 0) {\n process.stdout.write(pc.dim(\"No templates available.\\n\"))\n return\n }\n const headers = [\"slug\", \"name\", \"category\", \"license\"]\n const rows = templates.map((t) => [\n t.slug,\n t.name,\n t.category,\n t.license,\n ])\n printAlignedTable([headers, ...rows])\n}\n\nexport const printTemplateInfo = (t: Template): void => {\n const lines: Array<[string, string]> = [\n [\"slug\", t.slug],\n [\"name\", t.name],\n [\"description\", t.description],\n [\"category\", t.category],\n [\"license\", t.license],\n [\"repo\", `${t.owner}/${t.repo}`],\n [\"labels\", t.labels.join(\", \") || pc.dim(\"(none)\")],\n ]\n if (t.image) lines.push([\"image\", t.image])\n\n const labelWidth = Math.max(...lines.map(([l]) => l.length))\n for (const [label, value] of lines) {\n process.stdout.write(\n `${pc.dim(label.padEnd(labelWidth))} ${value}\\n`,\n )\n }\n}\n\nconst printAlignedTable = (rows: string[][]): void => {\n const firstRow = rows[0]\n if (!firstRow) return\n const widths = firstRow.map((_, col) =>\n Math.max(...rows.map((row) => row[col]?.length ?? 0)),\n )\n for (const row of rows) {\n process.stdout.write(\n row.map((cell, i) => cell.padEnd(widths[i] ?? 0)).join(\" \") + \"\\n\",\n )\n }\n}","import { spawn as nodeSpawn } from \"node:child_process\"\n\nexport type SpawnOptions = {\n cwd?: string\n env?: NodeJS.ProcessEnv\n stdio?: \"inherit\" | \"pipe\" | \"ignore\"\n /** If true, do not throw on non-zero exit codes. Default is `true` (no throw). */\n reject?: boolean\n}\n\n/**\n * Run a command and resolve with its exit code. Never throws on non-zero by\n * default; pass `reject: true` to opt into throwing.\n */\nexport const spawn = (\n command: string,\n args: string[],\n options: SpawnOptions = {},\n): Promise<number> => {\n const { cwd, env, stdio = \"inherit\", reject = false } = options\n return new Promise((resolve, rejectFn) => {\n const child = nodeSpawn(command, args, {\n cwd,\n env: env ?? process.env,\n stdio,\n shell: false,\n })\n child.on(\"error\", (err) => rejectFn(err))\n child.on(\"exit\", (code) => {\n const exit = code ?? 1\n if (reject && exit !== 0) {\n rejectFn(new Error(`${command} exited with code ${exit}`))\n } else {\n resolve(exit)\n }\n })\n })\n}","import { spawn } from \"./spawn.js\"\nimport { gitNotInstalled } from \"../errors.js\"\n\nexport type CloneResult = {\n ref: string\n attempts: string[]\n}\n\n/**\n * Clone a git repo to `dir`. Tries `main` first, then falls back to `master`.\n * Caller can pass an explicit `--ref` to override.\n */\nexport const cloneRepo = async (\n url: string,\n dir: string,\n requestedRef?: string,\n): Promise<CloneResult> => {\n const refs = requestedRef ? [requestedRef] : [\"main\", \"master\"]\n const attempts: string[] = []\n\n for (const ref of refs) {\n attempts.push(ref)\n const code = await spawn(\n \"git\",\n [\"clone\", \"--depth\", \"1\", \"--branch\", ref, url, dir],\n { stdio: \"inherit\", reject: false },\n )\n if (code === 0) {\n return { ref, attempts }\n }\n }\n\n // All attempts failed. Probe whether git is even installed.\n const probe = await spawn(\"git\", [\"--version\"], {\n stdio: \"ignore\",\n reject: false,\n })\n if (probe !== 0) {\n throw gitNotInstalled()\n }\n\n // Git works but neither ref matched. Re-throw with attempts context.\n throw new Error(\n `git clone failed for refs: ${refs.join(\", \")}. Tried: ${attempts.join(\", \")}.`,\n )\n}","import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nexport type PackageManager = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\"\n\nexport type PackageManagerInfo = {\n pm: PackageManager\n /** Raw value from packageManager field, e.g. \"pnpm@9.0.0\". May include version. */\n raw?: string\n}\n\n/**\n * Detect the package manager for a directory, in priority order:\n * 1. `packageManager` field in package.json (Corepack convention)\n * 2. Lockfile presence\n * 3. Returns null if nothing matches (caller decides whether to fail)\n */\nexport const detectPackageManager = (\n cwd: string,\n): PackageManagerInfo | null => {\n const pkg = readPackageJson(cwd)\n if (pkg?.packageManager) {\n const pm = parsePackageManagerField(pkg.packageManager)\n if (pm) return pm\n }\n\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return { pm: \"pnpm\" }\n if (existsSync(join(cwd, \"bun.lockb\"))) return { pm: \"bun\" }\n if (existsSync(join(cwd, \"yarn.lock\"))) return { pm: \"yarn\" }\n if (existsSync(join(cwd, \"package-lock.json\"))) return { pm: \"npm\" }\n\n return null\n}\n\nexport const getInstallCommand = (info: PackageManagerInfo): string => {\n switch (info.pm) {\n case \"pnpm\":\n return \"pnpm install\"\n case \"npm\":\n return \"npm install\"\n case \"yarn\":\n return \"yarn install\"\n case \"bun\":\n return \"bun install\"\n }\n}\n\nconst readPackageJson = (\n cwd: string,\n): { packageManager?: string } | null => {\n const path = join(cwd, \"package.json\")\n if (!existsSync(path)) return null\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as {\n packageManager?: string\n }\n } catch {\n return null\n }\n}\n\nexport const parsePackageManagerField = (\n raw: string,\n): PackageManagerInfo | null => {\n // Format: \"<name>@<version>\" or just \"<name>\". Common names: pnpm, npm, yarn, bun.\n const name = raw.split(\"@\")[0]?.trim().toLowerCase()\n if (name === \"pnpm\" || name === \"npm\" || name === \"yarn\" || name === \"bun\") {\n return { pm: name, raw }\n }\n return null\n}","import { existsSync } from \"node:fs\"\nimport { resolve } from \"node:path\"\nimport { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\nimport { fetchTemplates } from \"../api.js\"\nimport { DEFAULT_API_URL } from \"../constants.js\"\nimport {\n installFailed,\n internal,\n notFound,\n targetExists,\n} from \"../errors.js\"\nimport { printError, printJson } from \"../output.js\"\nimport { cloneRepo } from \"../utils/git.js\"\nimport {\n detectPackageManager,\n getInstallCommand,\n type PackageManagerInfo,\n} from \"../utils/detect-pm.js\"\nimport { spawn } from \"../utils/spawn.js\"\n\nexport const initCommand = new Command(\"init\")\n .description(\"Clone a template repo + install dependencies\")\n .argument(\"<slug>\", \"template slug (use `deessejs list` to see options)\")\n .option(\"--pm <name>\", \"override detected package manager (pnpm|npm|yarn|bun)\")\n .option(\"--dir <path>\", \"target directory (default: ./<slug>)\")\n .option(\"--ref <branch>\", \"git ref to clone (default: tries main, falls back to master)\")\n .option(\"--no-install\", \"skip the install step\")\n .option(\"--force\", \"overwrite target directory if it exists\")\n .option(\"--json\", \"JSON output for scripting\")\n .action(\n async (\n slug: string,\n opts: {\n pm?: string\n dir?: string\n ref?: string\n install: boolean\n force?: boolean\n json?: boolean\n },\n ) => {\n const apiUrl = initCommand.parent?.getOptionValue(\"apiUrl\") as\n | string\n | undefined\n const offline = initCommand.parent?.getOptionValue(\"offline\") as\n | boolean\n | undefined\n\n try {\n const templates = await fetchTemplates(\n apiUrl ?? process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL,\n { offline: Boolean(offline) },\n )\n const template = templates.find((t) => t.slug === slug)\n if (!template) {\n throw notFound(\n slug,\n templates.map((t) => t.slug),\n )\n }\n\n const dir = resolve(process.cwd(), opts.dir ?? `./${slug}`)\n if (existsSync(dir) && !opts.force) {\n throw targetExists(dir)\n }\n\n const repoUrl =\n template.cloneUrl ?? `https://github.com/${template.owner}/${template.repo}`\n\n const cloneSpinner = ora(`Cloning ${pc.cyan(template.owner + \"/\" + template.repo)}...`).start()\n let cloneResult\n try {\n cloneResult = await cloneRepo(repoUrl, dir, opts.ref)\n cloneSpinner.succeed(`Cloned into ${pc.cyan(dir)} (ref: ${cloneResult.ref})`)\n } catch (err) {\n cloneSpinner.fail(\"Clone failed\")\n throw err\n }\n\n if (!opts.install) {\n if (opts.json) {\n printJson({\n ok: true,\n slug: template.slug,\n dir,\n ref: cloneResult.ref,\n installed: false,\n })\n } else {\n console.log(pc.dim(`\\nNext: cd ${dir} && <your package manager> install\\n`))\n }\n return\n }\n\n const VALID_PMS = [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const\n type ValidPm = (typeof VALID_PMS)[number]\n const pmInfo: PackageManagerInfo | null =\n opts.pm && (VALID_PMS as readonly string[]).includes(opts.pm)\n ? { pm: opts.pm as ValidPm }\n : detectPackageManager(dir)\n\n if (!pmInfo) {\n console.log(\n pc.yellow(\n \"\\nNo package manager detected (no packageManager field, no lockfile).\",\n ),\n )\n console.log(\n pc.dim(\"Skipping install. Run your install command manually inside the directory.\\n\"),\n )\n } else {\n const installSpinner = ora(\n `Installing dependencies via ${pc.cyan(pmInfo.pm)}...`,\n ).start()\n const cmd = getInstallCommand(pmInfo)\n const cmdParts = cmd.split(\" \")\n const bin = cmdParts[0] ?? \"npm\"\n const args = cmdParts.slice(1)\n const code = await spawn(bin, args, { cwd: dir, stdio: \"inherit\", reject: false })\n if (code !== 0) {\n installSpinner.fail(`${pmInfo.pm} install failed`)\n throw installFailed(pmInfo.pm, code)\n }\n installSpinner.succeed(\"Dependencies installed\")\n }\n\n if (opts.json) {\n printJson({\n ok: true,\n slug: template.slug,\n dir,\n ref: cloneResult.ref,\n installed: pmInfo !== null,\n packageManager: pmInfo?.pm ?? null,\n })\n } else {\n console.log()\n console.log(pc.green(\"✓ Template ready\"))\n console.log(pc.dim(` cd ${dir}`))\n console.log(\n pc.dim(\n pmInfo\n ? ` ${getInstallCommand(pmInfo).split(\" \")[0]} dev`\n : ` install deps, then start`,\n ),\n )\n console.log()\n }\n } catch (err) {\n if (err instanceof Error && err.name === \"CliError\") {\n if (opts.json) {\n printJson({\n ok: false,\n code: (err as { code?: string }).code,\n message: err.message,\n hint: (err as { hint?: string }).hint,\n })\n } else {\n printError(err as Parameters<typeof printError>[0])\n }\n process.exit((err as { exitCode?: () => number }).exitCode?.() ?? 1)\n }\n throw internal(err instanceof Error ? err.message : String(err))\n }\n },\n )","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\nimport { fetchTemplates } from \"../api.js\"\nimport { DEFAULT_API_URL } from \"../constants.js\"\nimport { internal } from \"../errors.js\"\nimport { printError, printJson, printTemplatesTable } from \"../output.js\"\n\nexport const listCommand = new Command(\"list\")\n .description(\"List available templates\")\n .option(\"--category <name>\", \"filter to a single category\")\n .option(\"--json\", \"JSON output for scripting\")\n .action(\n async (\n opts: { category?: string; json?: boolean },\n command: Command,\n ) => {\n const apiUrl = command.parent?.getOptionValue(\"apiUrl\") as\n | string\n | undefined\n const offline = command.parent?.getOptionValue(\"offline\") as\n | boolean\n | undefined\n\n const spinner = opts.json\n ? null\n : ora(offline ? \"Reading cached templates...\" : \"Fetching templates...\").start()\n\n try {\n const all = await fetchTemplates(\n apiUrl ?? process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL,\n { offline: Boolean(offline) },\n )\n const filtered = opts.category\n ? all.filter((t) => t.category === opts.category)\n : all\n\n spinner?.stop()\n\n if (opts.json) {\n printJson({ templates: filtered })\n } else {\n if (opts.category) {\n console.log(pc.dim(`Category: ${opts.category}`))\n }\n printTemplatesTable(filtered)\n console.log()\n console.log(\n pc.dim(\n `${filtered.length} template${filtered.length === 1 ? \"\" : \"s\"}.` +\n (opts.category\n ? \"\"\n : \" Use --category <name> to filter, --json for scripting.\"),\n ),\n )\n }\n } catch (err) {\n spinner?.fail(\"Failed to fetch templates\")\n if (err instanceof Error && err.name === \"CliError\") {\n if (opts.json) {\n printJson({\n ok: false,\n code: (err as { code?: string }).code,\n message: err.message,\n hint: (err as { hint?: string }).hint,\n })\n } else {\n printError(err as Parameters<typeof printError>[0])\n }\n process.exit(1)\n }\n throw internal(err instanceof Error ? err.message : String(err))\n }\n },\n )","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport { fetchTemplates } from \"../api.js\"\nimport { DEFAULT_API_URL } from \"../constants.js\"\nimport { internal, notFound } from \"../errors.js\"\nimport { printError, printJson, printTemplateInfo } from \"../output.js\"\n\nexport const infoCommand = new Command(\"info\")\n .description(\"Show details for one template\")\n .argument(\"<slug>\", \"template slug\")\n .option(\"--json\", \"JSON output for scripting\")\n .action(\n async (slug: string, opts: { json?: boolean }, command: Command) => {\n const apiUrl = command.parent?.getOptionValue(\"apiUrl\") as\n | string\n | undefined\n const offline = command.parent?.getOptionValue(\"offline\") as\n | boolean\n | undefined\n\n const spinner = opts.json\n ? null\n : ora(offline ? \"Reading cached template...\" : \"Fetching template...\").start()\n\n try {\n const all = await fetchTemplates(\n apiUrl ?? process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL,\n { offline: Boolean(offline) },\n )\n const template = all.find((t) => t.slug === slug)\n spinner?.stop()\n\n if (!template) {\n throw notFound(slug, all.map((t) => t.slug))\n }\n\n if (opts.json) {\n printJson({ template })\n } else {\n printTemplateInfo(template)\n console.log()\n console.log(\n `Install: ${`deessejs init ${template.slug}`}`,\n )\n }\n } catch (err) {\n spinner?.fail(\"Failed to fetch template\")\n if (err instanceof Error && err.name === \"CliError\") {\n if (opts.json) {\n printJson({\n ok: false,\n code: (err as { code?: string }).code,\n message: err.message,\n hint: (err as { hint?: string }).hint,\n })\n } else {\n printError(err as Parameters<typeof printError>[0])\n }\n process.exit(1)\n }\n throw internal(err instanceof Error ? err.message : String(err))\n }\n },\n )","import { Command } from \"commander\"\nimport pc from \"picocolors\"\nimport { DEFAULT_API_URL, USER_AGENT } from \"./constants.js\"\nimport { initCommand } from \"./commands/init.js\"\nimport { listCommand } from \"./commands/list.js\"\nimport { infoCommand } from \"./commands/info.js\"\n\nconst program = new Command()\n\nprogram\n .name(\"deessejs\")\n .description(\"CLI for the DeesseJS template registry\")\n .version(\"0.1.0\")\n .option(\"--api-url <url>\", \"templates endpoint URL\", process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL)\n .option(\"--offline\", \"skip the network, serve the on-disk cache (~/.deessejs/templates.json)\")\n\nprogram.addCommand(listCommand)\nprogram.addCommand(infoCommand)\nprogram.addCommand(initCommand)\n\nprogram.parseAsync(process.argv).catch((err) => {\n // Last-resort error handler. Per-command handlers catch CliError and exit\n // cleanly with the right code. Anything that lands here is an uncaught bug.\n process.stderr.write(\n `${pc.red(\"Internal error\")}: ${err instanceof Error ? err.message : String(err)}\\n`,\n )\n if (process.env.DEESSEJS_DEBUG) {\n process.stderr.write(`\\n${err instanceof Error && err.stack ? err.stack : \"\"}\\n`)\n }\n process.exit(1)\n})\n\nvoid USER_AGENT // re-exported for downstream consumers if needed"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deessejs/cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "CLI for the DeesseJS template registry.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -31,7 +31,8 @@
31
31
  "@deessejs/fp": "^1.0.0",
32
32
  "commander": "^12.1.0",
33
33
  "ora": "^8.1.1",
34
- "picocolors": "^1.1.1"
34
+ "picocolors": "^1.1.1",
35
+ "@workspace/contracts": "0.0.1"
35
36
  },
36
37
  "devDependencies": {
37
38
  "@types/node": "^24",
@@ -41,8 +42,8 @@
41
42
  "tsup": "^8.3.5",
42
43
  "typescript": "^6.0.3",
43
44
  "vitest": "^2.1.5",
44
- "@workspace/eslint-config": "0.0.0",
45
- "@workspace/typescript-config": "0.0.0"
45
+ "@workspace/typescript-config": "0.0.0",
46
+ "@workspace/eslint-config": "0.0.0"
46
47
  },
47
48
  "engines": {
48
49
  "node": ">=18.18.0"
@@ -52,12 +53,14 @@
52
53
  "provenance": true
53
54
  },
54
55
  "scripts": {
56
+ "prebuild": "pnpm --filter @workspace/contracts build",
55
57
  "build": "tsup",
58
+ "predev": "pnpm --filter @workspace/contracts build",
56
59
  "dev": "tsup --watch",
57
60
  "lint": "eslint",
58
61
  "format": "prettier --write \"**/*.{ts,tsx,json,md}\"",
59
62
  "typecheck": "tsc --noEmit",
60
- "pretest": "tsup",
63
+ "pretest": "pnpm --filter @workspace/contracts build && tsup",
61
64
  "test": "vitest run",
62
65
  "test:watch": "vitest",
63
66
  "start": "node ./dist/index.js"