@deessejs/cli 1.1.1 → 2.0.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.
- package/dist/index.js +121 -252
- package/dist/index.js.map +1 -1
- package/package.json +11 -8
package/dist/index.js
CHANGED
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
-
import
|
|
4
|
-
import { existsSync, readFileSync
|
|
5
|
-
import {
|
|
3
|
+
import pc3 from 'picocolors';
|
|
4
|
+
import { existsSync, readFileSync } from 'fs';
|
|
5
|
+
import { resolve, join } from 'path';
|
|
6
6
|
import ora from 'ora';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { createORPCClient, toORPCError } from '@orpc/client';
|
|
8
|
+
import { RetryAfterPlugin, ClientRetryPlugin } from '@orpc/client/plugins';
|
|
9
|
+
import { RPCLink } from '@orpc/client/fetch';
|
|
9
10
|
import { spawn as spawn$1 } from 'child_process';
|
|
10
11
|
|
|
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)";
|
|
12
|
+
// src/constants/exit.ts
|
|
14
13
|
var EXIT_ERROR = 1;
|
|
15
14
|
|
|
16
|
-
// src/errors.ts
|
|
15
|
+
// src/errors/network.ts
|
|
16
|
+
var networkError = (detail) => new CliError(
|
|
17
|
+
"network_error",
|
|
18
|
+
`could not reach the templates endpoint`,
|
|
19
|
+
detail
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// src/errors/not-found.ts
|
|
23
|
+
var notFound = (slug, available) => new CliError(
|
|
24
|
+
"not_found",
|
|
25
|
+
`template "${slug}" not found`,
|
|
26
|
+
`available templates: ${available.join(", ")}`
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// src/errors/index.ts
|
|
17
30
|
var CliError = class extends Error {
|
|
18
31
|
code;
|
|
19
32
|
hint;
|
|
@@ -25,16 +38,6 @@ var CliError = class extends Error {
|
|
|
25
38
|
}
|
|
26
39
|
exitCode = () => EXIT_ERROR;
|
|
27
40
|
};
|
|
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
41
|
var gitNotInstalled = () => new CliError(
|
|
39
42
|
"git_not_installed",
|
|
40
43
|
"`git` is not installed or not on PATH",
|
|
@@ -50,98 +53,18 @@ var installFailed = (pm, code) => new CliError(
|
|
|
50
53
|
`${pm} install exited with code ${code ?? "unknown"}`,
|
|
51
54
|
"check the output above, then run the install command manually inside the cloned directory"
|
|
52
55
|
);
|
|
53
|
-
var parseError = (detail) => new CliError(
|
|
54
|
-
"parse_error",
|
|
55
|
-
"templates endpoint returned malformed data",
|
|
56
|
-
detail
|
|
57
|
-
);
|
|
58
56
|
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
57
|
|
|
93
|
-
//
|
|
94
|
-
var
|
|
95
|
-
var
|
|
96
|
-
var
|
|
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
|
-
};
|
|
58
|
+
// ../../packages/api/dist/constants/base-path.js
|
|
59
|
+
var API_BASE_PATH_V1 = "/api/v1";
|
|
60
|
+
var API_BASE_PATH = API_BASE_PATH_V1;
|
|
61
|
+
var API_RPC_PATH = `${API_BASE_PATH}/rpc`;
|
|
139
62
|
|
|
140
|
-
// src/
|
|
141
|
-
var CLI_PACKAGE_VERSION = "
|
|
63
|
+
// src/api/self-version.ts
|
|
64
|
+
var CLI_PACKAGE_VERSION = "2.0.0";
|
|
142
65
|
var readPackageVersion = () => CLI_PACKAGE_VERSION;
|
|
143
66
|
|
|
144
|
-
// src/version
|
|
67
|
+
// src/version/check.ts
|
|
145
68
|
var SEMVER_RE = /^\d+\.\d+\.\d+$/;
|
|
146
69
|
var parseSemver = (v) => {
|
|
147
70
|
if (!SEMVER_RE.test(v)) return null;
|
|
@@ -156,14 +79,13 @@ var compareSemver = (a, b) => {
|
|
|
156
79
|
if (pa[1] !== pb[1]) return pa[1] - pb[1];
|
|
157
80
|
return pa[2] - pb[2];
|
|
158
81
|
};
|
|
159
|
-
var maybeWarnAboutOutdatedCli = async (
|
|
82
|
+
var maybeWarnAboutOutdatedCli = async () => {
|
|
160
83
|
let bodyText;
|
|
161
84
|
try {
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
});
|
|
85
|
+
const versionUrl = `${API_BASE_PATH}/version`;
|
|
86
|
+
const res = await fetch(versionUrl);
|
|
165
87
|
if (res.status !== 200) return;
|
|
166
|
-
bodyText = res.
|
|
88
|
+
bodyText = await res.text();
|
|
167
89
|
} catch {
|
|
168
90
|
return;
|
|
169
91
|
}
|
|
@@ -187,91 +109,42 @@ var maybeWarnAboutOutdatedCli = async (apiUrl) => {
|
|
|
187
109
|
);
|
|
188
110
|
}
|
|
189
111
|
};
|
|
112
|
+
var isTransientNetworkError = (e) => e instanceof TypeError;
|
|
113
|
+
var link = new RPCLink({
|
|
114
|
+
url: API_RPC_PATH,
|
|
115
|
+
plugins: [
|
|
116
|
+
new RetryAfterPlugin(),
|
|
117
|
+
new ClientRetryPlugin({
|
|
118
|
+
default: {
|
|
119
|
+
retry: 3,
|
|
120
|
+
shouldRetry: ({ error }) => isTransientNetworkError(error)
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
]
|
|
124
|
+
});
|
|
125
|
+
var orpc = createORPCClient(link);
|
|
190
126
|
|
|
191
|
-
// src/api.ts
|
|
192
|
-
var
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
};
|
|
198
|
-
if (etag) headers["If-None-Match"] = etag;
|
|
199
|
-
return headers;
|
|
127
|
+
// src/api/index.ts
|
|
128
|
+
var normaliseError = (e) => {
|
|
129
|
+
if (e instanceof TypeError) {
|
|
130
|
+
return networkError(e.message);
|
|
131
|
+
}
|
|
132
|
+
return toORPCError(e);
|
|
200
133
|
};
|
|
201
|
-
var fetchTemplates = async (
|
|
134
|
+
var fetchTemplates = async (options = {}) => {
|
|
202
135
|
if (!options.skipVersionCheck) {
|
|
203
|
-
await maybeWarnAboutOutdatedCli(
|
|
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}`);
|
|
136
|
+
await maybeWarnAboutOutdatedCli();
|
|
243
137
|
}
|
|
244
|
-
let body;
|
|
245
138
|
try {
|
|
246
|
-
|
|
139
|
+
const result = await orpc.templates.list();
|
|
140
|
+
return result.templates;
|
|
247
141
|
} catch (e) {
|
|
248
|
-
throw
|
|
249
|
-
`endpoint returned non-JSON body: ${e instanceof Error ? e.message : String(e)}`
|
|
250
|
-
);
|
|
142
|
+
throw normaliseError(e);
|
|
251
143
|
}
|
|
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
144
|
};
|
|
272
145
|
var printTemplatesTable = (templates) => {
|
|
273
146
|
if (templates.length === 0) {
|
|
274
|
-
process.stdout.write(
|
|
147
|
+
process.stdout.write(pc3.dim("No templates available.\n"));
|
|
275
148
|
return;
|
|
276
149
|
}
|
|
277
150
|
const headers = ["slug", "name", "category", "license"];
|
|
@@ -291,13 +164,13 @@ var printTemplateInfo = (t) => {
|
|
|
291
164
|
["category", t.category],
|
|
292
165
|
["license", t.license],
|
|
293
166
|
["repo", `${t.owner}/${t.repo}`],
|
|
294
|
-
["labels", t.labels.join(", ") ||
|
|
167
|
+
["labels", t.labels.join(", ") || pc3.dim("(none)")]
|
|
295
168
|
];
|
|
296
169
|
if (t.image) lines.push(["image", t.image]);
|
|
297
170
|
const labelWidth = Math.max(...lines.map(([l]) => l.length));
|
|
298
171
|
for (const [label, value] of lines) {
|
|
299
172
|
process.stdout.write(
|
|
300
|
-
`${
|
|
173
|
+
`${pc3.dim(label.padEnd(labelWidth))} ${value}
|
|
301
174
|
`
|
|
302
175
|
);
|
|
303
176
|
}
|
|
@@ -314,6 +187,19 @@ var printAlignedTable = (rows) => {
|
|
|
314
187
|
);
|
|
315
188
|
}
|
|
316
189
|
};
|
|
190
|
+
|
|
191
|
+
// src/output/index.ts
|
|
192
|
+
var printJson = (value) => {
|
|
193
|
+
process.stdout.write(JSON.stringify(value, null, 2) + "\n");
|
|
194
|
+
};
|
|
195
|
+
var printError = (err) => {
|
|
196
|
+
process.stderr.write(
|
|
197
|
+
`${pc3.red("Error")}: ${err.message}
|
|
198
|
+
` + (err.hint ? `${pc3.dim("Hint")}: ${err.hint}
|
|
199
|
+
` : "") + `${pc3.dim("Code")}: ${err.code}
|
|
200
|
+
`
|
|
201
|
+
);
|
|
202
|
+
};
|
|
317
203
|
var spawn = (command, args, options = {}) => {
|
|
318
204
|
const { cwd, env, stdio = "inherit", reject = false } = options;
|
|
319
205
|
return new Promise((resolve2, rejectFn) => {
|
|
@@ -405,13 +291,8 @@ var parsePackageManagerField = (raw) => {
|
|
|
405
291
|
// src/commands/init.ts
|
|
406
292
|
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
293
|
async (slug, opts) => {
|
|
408
|
-
const apiUrl = initCommand.parent?.getOptionValue("apiUrl");
|
|
409
|
-
const offline = initCommand.parent?.getOptionValue("offline");
|
|
410
294
|
try {
|
|
411
|
-
const templates = await fetchTemplates(
|
|
412
|
-
apiUrl ?? process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL,
|
|
413
|
-
{ offline: Boolean(offline) }
|
|
414
|
-
);
|
|
295
|
+
const templates = await fetchTemplates();
|
|
415
296
|
const template = templates.find((t) => t.slug === slug);
|
|
416
297
|
if (!template) {
|
|
417
298
|
throw notFound(
|
|
@@ -424,11 +305,11 @@ var initCommand = new Command("init").description("Clone a template repo + insta
|
|
|
424
305
|
throw targetExists(dir);
|
|
425
306
|
}
|
|
426
307
|
const repoUrl = template.cloneUrl ?? `https://github.com/${template.owner}/${template.repo}`;
|
|
427
|
-
const cloneSpinner = ora(`Cloning ${
|
|
308
|
+
const cloneSpinner = ora(`Cloning ${pc3.cyan(template.owner + "/" + template.repo)}...`).start();
|
|
428
309
|
let cloneResult;
|
|
429
310
|
try {
|
|
430
311
|
cloneResult = await cloneRepo(repoUrl, dir, opts.ref);
|
|
431
|
-
cloneSpinner.succeed(`Cloned into ${
|
|
312
|
+
cloneSpinner.succeed(`Cloned into ${pc3.cyan(dir)} (ref: ${cloneResult.ref})`);
|
|
432
313
|
} catch (err) {
|
|
433
314
|
cloneSpinner.fail("Clone failed");
|
|
434
315
|
throw err;
|
|
@@ -443,7 +324,7 @@ var initCommand = new Command("init").description("Clone a template repo + insta
|
|
|
443
324
|
installed: false
|
|
444
325
|
});
|
|
445
326
|
} else {
|
|
446
|
-
console.log(
|
|
327
|
+
console.log(pc3.dim(`
|
|
447
328
|
Next: cd ${dir} && <your package manager> install
|
|
448
329
|
`));
|
|
449
330
|
}
|
|
@@ -453,16 +334,16 @@ Next: cd ${dir} && <your package manager> install
|
|
|
453
334
|
const pmInfo = opts.pm && VALID_PMS.includes(opts.pm) ? { pm: opts.pm } : detectPackageManager(dir);
|
|
454
335
|
if (!pmInfo) {
|
|
455
336
|
console.log(
|
|
456
|
-
|
|
337
|
+
pc3.yellow(
|
|
457
338
|
"\nNo package manager detected (no packageManager field, no lockfile)."
|
|
458
339
|
)
|
|
459
340
|
);
|
|
460
341
|
console.log(
|
|
461
|
-
|
|
342
|
+
pc3.dim("Skipping install. Run your install command manually inside the directory.\n")
|
|
462
343
|
);
|
|
463
344
|
} else {
|
|
464
345
|
const installSpinner = ora(
|
|
465
|
-
`Installing dependencies via ${
|
|
346
|
+
`Installing dependencies via ${pc3.cyan(pmInfo.pm)}...`
|
|
466
347
|
).start();
|
|
467
348
|
const cmd = getInstallCommand(pmInfo);
|
|
468
349
|
const cmdParts = cmd.split(" ");
|
|
@@ -486,10 +367,10 @@ Next: cd ${dir} && <your package manager> install
|
|
|
486
367
|
});
|
|
487
368
|
} else {
|
|
488
369
|
console.log();
|
|
489
|
-
console.log(
|
|
490
|
-
console.log(
|
|
370
|
+
console.log(pc3.green("\u2713 Template ready"));
|
|
371
|
+
console.log(pc3.dim(` cd ${dir}`));
|
|
491
372
|
console.log(
|
|
492
|
-
|
|
373
|
+
pc3.dim(
|
|
493
374
|
pmInfo ? ` ${getInstallCommand(pmInfo).split(" ")[0]} dev` : ` install deps, then start`
|
|
494
375
|
)
|
|
495
376
|
);
|
|
@@ -514,27 +395,22 @@ Next: cd ${dir} && <your package manager> install
|
|
|
514
395
|
}
|
|
515
396
|
);
|
|
516
397
|
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
|
|
518
|
-
const
|
|
519
|
-
const offline = command.parent?.getOptionValue("offline");
|
|
520
|
-
const spinner = opts.json ? null : ora(offline ? "Reading cached templates..." : "Fetching templates...").start();
|
|
398
|
+
async (opts) => {
|
|
399
|
+
const spinner = opts.json ? null : ora("Fetching templates...").start();
|
|
521
400
|
try {
|
|
522
|
-
const all = await fetchTemplates(
|
|
523
|
-
apiUrl ?? process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL,
|
|
524
|
-
{ offline: Boolean(offline) }
|
|
525
|
-
);
|
|
401
|
+
const all = await fetchTemplates();
|
|
526
402
|
const filtered = opts.category ? all.filter((t) => t.category === opts.category) : all;
|
|
527
403
|
spinner?.stop();
|
|
528
404
|
if (opts.json) {
|
|
529
405
|
printJson({ templates: filtered });
|
|
530
406
|
} else {
|
|
531
407
|
if (opts.category) {
|
|
532
|
-
console.log(
|
|
408
|
+
console.log(pc3.dim(`Category: ${opts.category}`));
|
|
533
409
|
}
|
|
534
410
|
printTemplatesTable(filtered);
|
|
535
411
|
console.log();
|
|
536
412
|
console.log(
|
|
537
|
-
|
|
413
|
+
pc3.dim(
|
|
538
414
|
`${filtered.length} template${filtered.length === 1 ? "" : "s"}.` + (opts.category ? "" : " Use --category <name> to filter, --json for scripting.")
|
|
539
415
|
)
|
|
540
416
|
);
|
|
@@ -558,59 +434,52 @@ var listCommand = new Command("list").description("List available templates").op
|
|
|
558
434
|
}
|
|
559
435
|
}
|
|
560
436
|
);
|
|
561
|
-
var infoCommand = new Command("info").description("Show details for one template").argument("<slug>", "template slug").option("--json", "JSON output for scripting").action(
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
437
|
+
var infoCommand = new Command("info").description("Show details for one template").argument("<slug>", "template slug").option("--json", "JSON output for scripting").action(async (slug, opts) => {
|
|
438
|
+
const spinner = opts.json ? null : ora("Fetching template...").start();
|
|
439
|
+
try {
|
|
440
|
+
const all = await fetchTemplates();
|
|
441
|
+
const template = all.find((t) => t.slug === slug);
|
|
442
|
+
spinner?.stop();
|
|
443
|
+
if (!template) {
|
|
444
|
+
throw notFound(slug, all.map((t) => t.slug));
|
|
445
|
+
}
|
|
446
|
+
if (opts.json) {
|
|
447
|
+
printJson({ template });
|
|
448
|
+
} else {
|
|
449
|
+
printTemplateInfo(template);
|
|
450
|
+
console.log();
|
|
451
|
+
console.log(
|
|
452
|
+
`Install: ${`deessejs init ${template.slug}`}`
|
|
570
453
|
);
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
}
|
|
454
|
+
}
|
|
455
|
+
} catch (err) {
|
|
456
|
+
spinner?.fail("Failed to fetch template");
|
|
457
|
+
if (err instanceof Error && err.name === "CliError") {
|
|
576
458
|
if (opts.json) {
|
|
577
|
-
printJson({
|
|
459
|
+
printJson({
|
|
460
|
+
ok: false,
|
|
461
|
+
code: err.code,
|
|
462
|
+
message: err.message,
|
|
463
|
+
hint: err.hint
|
|
464
|
+
});
|
|
578
465
|
} else {
|
|
579
|
-
|
|
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);
|
|
466
|
+
printError(err);
|
|
599
467
|
}
|
|
600
|
-
|
|
468
|
+
process.exit(1);
|
|
601
469
|
}
|
|
470
|
+
throw internal(err instanceof Error ? err.message : String(err));
|
|
602
471
|
}
|
|
603
|
-
);
|
|
472
|
+
});
|
|
604
473
|
|
|
605
474
|
// src/index.ts
|
|
606
475
|
var program = new Command();
|
|
607
|
-
program.name("deessejs").description("CLI for the DeesseJS template registry").version("0.1.0")
|
|
476
|
+
program.name("deessejs").description("CLI for the DeesseJS template registry").version("0.1.0");
|
|
608
477
|
program.addCommand(listCommand);
|
|
609
478
|
program.addCommand(infoCommand);
|
|
610
479
|
program.addCommand(initCommand);
|
|
611
480
|
program.parseAsync(process.argv).catch((err) => {
|
|
612
481
|
process.stderr.write(
|
|
613
|
-
`${
|
|
482
|
+
`${pc3.red("Internal error")}: ${err instanceof Error ? err.message : String(err)}
|
|
614
483
|
`
|
|
615
484
|
);
|
|
616
485
|
if (process.env.DEESSEJS_DEBUG) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants/exit.ts","../src/errors/network.ts","../src/errors/not-found.ts","../src/errors/index.ts","../../../packages/api/dist/constants/base-path.js","../src/api/self-version.ts","../src/version/check.ts","../src/api/client.ts","../src/api/index.ts","../src/output/table.ts","../src/output/index.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":["pc","resolve","nodeSpawn","existsSync","Command","ora"],"mappings":"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","file":"index.js","sourcesContent":["export const EXIT_SUCCESS = 0\nexport const EXIT_ERROR = 1\n","import { CliError } from \"./index.js\"\n\nexport const networkError = (detail: string): CliError =>\n new CliError(\n \"network_error\",\n `could not reach the templates endpoint`,\n detail,\n )\n","import { CliError } from \"./index.js\"\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","import { EXIT_ERROR } from \"../constants/exit.js\"\n\n// Public surface (per ADR-010 §2): the closed list of error codes\n// that downstream tooling may pattern-match against. Adding a code\n// here is a breaking change.\nexport type CliErrorCode =\n | \"not_found\"\n | \"network_error\"\n | \"parse_error\"\n | \"cli_outdated\"\n\n// Internal codes, used only inside the CLI. Not surfaced as a public\n// pattern-match surface. Adding a code here is non-breaking.\nexport type InternalCliErrorCode =\n | \"git_not_installed\"\n | \"target_exists\"\n | \"install_failed\"\n | \"internal\"\n\nexport type AnyCliErrorCode = CliErrorCode | InternalCliErrorCode\n\nexport class CliError extends Error {\n public readonly code: AnyCliErrorCode\n public readonly hint: string | undefined\n\n constructor(code: AnyCliErrorCode, 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\n// Public factories (re-export the per-code files).\nexport { networkError } from \"./network.js\"\nexport { parseError } from \"./parse.js\"\nexport { notFound } from \"./not-found.js\"\nexport { cliOutdated } from \"./outdated.js\"\n\n// Internal factories, kept in this file because they are not part of\n// the public surface (ADR-010 §2 \"What this rule allows\": internal\n// error codes are not surfaced to the user).\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 internal = (detail: string): CliError =>\n new CliError(\"internal\", \"unexpected internal error\", detail)\n","/**\n * Single source of truth for the API path.\n *\n * The Next.js catch-all at `apps/app/app/api/[[...route]]/route.ts` exposes\n * every route under the active base path. Hono is mounted with\n * `basePath(API_BASE_PATH)`, and the oRPC client targets `API_RPC_PATH` to\n * reach the procedures endpoint.\n *\n * Versioning strategy (locked in docs/engineering/plans/robust-shared-backend.md):\n * - Each contract version lives under `packages/contracts/src/vN/`.\n * - The HTTP URL prefix mirrors that: `API_BASE_PATH_V1 = \"/api/v1\"`.\n * - `API_BASE_PATH` aliases the *active* version. When a V2 is introduced,\n * define `API_BASE_PATH_V2`, point `API_BASE_PATH` at it, and keep V1\n * served as a deprecated alias for installed CLI V1.x clients.\n *\n * Renaming the API prefix means:\n * 1. Edit `API_BASE_PATH_V*` below.\n * 2. Move (or alias) the Next.js catch-all to match.\n * 3. If you later introduce a `NEXT_PUBLIC_API_BASE_PATH` env override,\n * read it here and have `API_BASE_PATH` default to it.\n *\n * Do NOT introduce a parallel \"API path\" hardcoded in any app or package —\n * always import from this module.\n *\n * Note: Hono routes are kept *relative* to `basePath`, so the Hono-side\n * patterns (`/health`, `/rpc/*`) are NOT exposed here — only the full\n * client-facing paths.\n */\nexport const API_BASE_PATH_V1 = \"/api/v1\";\n/** Active version. Alias of the latest released base path. */\nexport const API_BASE_PATH = API_BASE_PATH_V1;\nexport const API_RPC_PATH = `${API_BASE_PATH}/rpc`;\nexport const API_AUTH_PATH = `${API_BASE_PATH}/auth`;\nexport const API_HEALTH_PATH = `${API_BASE_PATH}/health`;\nexport const API_READY_PATH = `${API_BASE_PATH}/ready`;\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 = \"2.0.0\"\n\nexport const readPackageVersion = (): string => CLI_PACKAGE_VERSION\n","import { API_BASE_PATH } from \"@workspace/api/base-path\"\n\nimport { readPackageVersion } from \"../api/self-version.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_BASE_PATH}/version` (a system route per ADR-011, served\n * by Hono direct, not through oRPC). If the local CLI version is\n * strictly below minSupported, prints a warning to stderr. The caller\n * does NOT abort; the user might have a workflow that depends on the\n * old version. The warning is loud but not 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 (): Promise<void> => {\n let bodyText: string\n try {\n const versionUrl = `${API_BASE_PATH}/version`\n const res = await fetch(versionUrl)\n if (res.status !== 200) return\n bodyText = await res.text()\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 {\n ClientRetryPlugin,\n RetryAfterPlugin,\n} from \"@orpc/client/plugins\"\nimport { RPCLink } from \"@orpc/client/fetch\"\nimport { createORPCClient } from \"@orpc/client\"\nimport type { RouterClient } from \"@orpc/server\"\n\nimport { appRouter } from \"@workspace/api/router\"\nimport { API_RPC_PATH } from \"@workspace/api/base-path\"\n\n/**\n * Typed oRPC link for the CLI.\n *\n * Internal to the CLI. The public surface (`fetchTemplates`) lives in\n * ../api/index.ts. Tests that target the typed client (Server-Side Client\n * pattern) import `appRouter` directly from `@workspace/api/router` and\n * bypass this module entirely.\n *\n * Resilience is delegated to the official oRPC plugins\n * (`ClientRetryPlugin`, `RetryAfterPlugin`); the HTTP fetch itself is\n * `globalThis.fetch` (the oRPC default). The plugins cover retry on\n * transient network errors and on 429 / 503 honouring `Retry-After`.\n *\n * See `apps/internal-documentation/content/docs/knowledge-base/orpc/client-plugins.mdx`\n * for the full coverage analysis.\n *\n * The previous custom `orpcFetch` hook (which injected the User-Agent\n * header and did bespoke retries) was removed in favour of the plugins.\n * The User-Agent header is no longer sent from the typed client. The\n * system-level version probe (`apps/cli/src/version/check.ts`) still\n * sends a User-Agent because it hits a Hono-direct endpoint, not an\n * oRPC procedure.\n */\n/**\n * Whether an error thrown from the wire layer is a transient network\n * error (DNS failure, TCP reset, timeout). These are worth retrying;\n * typed ORPCError and other application errors are not.\n */\nconst isTransientNetworkError = (e: unknown): boolean =>\n e instanceof TypeError\n\nconst link = new RPCLink({\n url: API_RPC_PATH,\n plugins: [\n new RetryAfterPlugin(),\n new ClientRetryPlugin({\n default: {\n retry: 3,\n shouldRetry: ({ error }) => isTransientNetworkError(error),\n },\n }),\n ],\n})\n\nexport type ORPCClient = RouterClient<typeof appRouter>\n\nexport const orpc: ORPCClient = createORPCClient(link)\n","import { toORPCError } from \"@orpc/client\"\nimport { TemplatesListResponseV1 } from \"@workspace/contracts/v1\"\n\nimport { networkError } from \"../errors/index.js\"\nimport { maybeWarnAboutOutdatedCli } from \"../version/check.js\"\nimport { orpc } from \"./client.js\"\n\nexport type Template = TemplatesListResponseV1[\"templates\"][number]\n\nexport type FetchOptions = {\n /** Skip the version probe. Used by tests and by the version probe itself. */\n skipVersionCheck?: boolean\n}\n\n/**\n * Normalise an error thrown from the typed oRPC client.\n *\n * Uses `toORPCError` from `@orpc/client` to do the shape matching. This is\n * the canonical entry point: the lib does the matching internally and\n * exposes `[Symbol.hasInstance]` for the Next.js multi-context case.\n *\n * In V1 the only mapping is `TypeError -> networkError`, because that\n * is the only error the global `fetch` throws for an unreachable network.\n * `ORPCError` instances are propagated as-is: the calling command knows\n * the procedure semantics and decides how to surface them.\n */\nexport const normaliseError = (e: unknown): Error => {\n // The global fetch throws a TypeError for unreachable networks.\n // `toORPCError` from @orpc/client wraps anything into an ORPCError\n // (replacing the original cause), so we must check TypeError BEFORE\n // calling it.\n if (e instanceof TypeError) {\n return networkError(e.message)\n }\n // For anything that is already (or can be normalised to) an\n // ORPCError, propagate as-is. The calling command knows the\n // procedure semantics and decides how to surface them.\n return toORPCError(e) as Error\n}\n\n/**\n * Fetch the templates registry.\n *\n * Flow:\n * 1. (If not skipVersionCheck) probe /version and warn if outdated.\n * Failure here is silent — version check is best-effort.\n * 2. Call templates.list on the shared typed client. Retry on\n * 5xx and 429 is handled by the official oRPC plugins configured\n * in ./client.ts.\n * 3. Surface typed errors via `normaliseError`.\n *\n * The URL is fixed at `API_RPC_PATH` (imported from\n * `@workspace/api/base-path`). A per-command override is intentionally\n * not part of the public surface in V1.\n *\n * Testing:\n * - The procedure contract is tested via the Server-Side Client\n * pattern in `test/contract/orpc-to-cli-error.test.ts`. Call\n * `appRouter.templates.list()` directly, no HTTP.\n */\nexport const fetchTemplates = async (\n options: FetchOptions = {},\n): Promise<Template[]> => {\n if (!options.skipVersionCheck) {\n await maybeWarnAboutOutdatedCli()\n }\n\n try {\n const result = await orpc.templates.list()\n return result.templates\n } catch (e) {\n throw normaliseError(e)\n }\n}\n","import pc from \"picocolors\"\n\nimport type { Template } from \"../api/index.js\"\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}\n","import pc from \"picocolors\"\n\nimport type { CliError } from \"../errors/index.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 { printTemplatesTable, printTemplateInfo } from \"./table.js\"\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/index.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/index.js\"\nimport {\n installFailed,\n internal,\n notFound,\n targetExists,\n} from \"../errors/index.js\"\nimport { printError, printJson } from \"../output/index.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 try {\n const templates = await fetchTemplates()\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 )\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\nimport { fetchTemplates } from \"../api/index.js\"\nimport { internal } from \"../errors/index.js\"\nimport { printError, printJson, printTemplatesTable } from \"../output/index.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 (opts: { category?: string; json?: boolean }) => {\n const spinner = opts.json ? null : ora(\"Fetching templates...\").start()\n\n try {\n const all = await fetchTemplates()\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 )\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport { fetchTemplates } from \"../api/index.js\"\nimport { internal, notFound } from \"../errors/index.js\"\nimport { printError, printJson, printTemplateInfo } from \"../output/index.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(async (slug: string, opts: { json?: boolean }) => {\n const spinner = opts.json ? null : ora(\"Fetching template...\").start()\n\n try {\n const all = await fetchTemplates()\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 { 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\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deessejs/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "CLI for the DeesseJS template registry.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"keywords": [
|
|
12
12
|
"cli",
|
|
13
13
|
"deessejs",
|
|
14
|
-
"
|
|
14
|
+
"deessejs-main-app",
|
|
15
15
|
"scaffolding"
|
|
16
16
|
],
|
|
17
17
|
"private": false,
|
|
@@ -29,10 +29,12 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@deessejs/errors": "^1.1.1",
|
|
31
31
|
"@deessejs/fp": "^1.0.0",
|
|
32
|
+
"@orpc/client": "^1.14.7",
|
|
33
|
+
"@orpc/server": "^1.14.7",
|
|
32
34
|
"commander": "^12.1.0",
|
|
33
35
|
"ora": "^8.1.1",
|
|
34
36
|
"picocolors": "^1.1.1",
|
|
35
|
-
"@workspace/
|
|
37
|
+
"@workspace/api": "0.0.2"
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
38
40
|
"@types/node": "^24",
|
|
@@ -42,8 +44,9 @@
|
|
|
42
44
|
"tsup": "^8.3.5",
|
|
43
45
|
"typescript": "^6.0.3",
|
|
44
46
|
"vitest": "^2.1.5",
|
|
45
|
-
"@workspace/
|
|
46
|
-
"@workspace/
|
|
47
|
+
"@workspace/eslint-config": "0.0.0",
|
|
48
|
+
"@workspace/contracts": "0.0.1",
|
|
49
|
+
"@workspace/typescript-config": "0.0.0"
|
|
47
50
|
},
|
|
48
51
|
"engines": {
|
|
49
52
|
"node": ">=18.18.0"
|
|
@@ -53,14 +56,14 @@
|
|
|
53
56
|
"provenance": true
|
|
54
57
|
},
|
|
55
58
|
"scripts": {
|
|
56
|
-
"prebuild": "pnpm --filter @workspace/contracts build",
|
|
59
|
+
"prebuild": "pnpm --filter @workspace/contracts --filter @workspace/api build",
|
|
57
60
|
"build": "tsup",
|
|
58
|
-
"predev": "pnpm --filter @workspace/contracts build",
|
|
61
|
+
"predev": "pnpm --filter @workspace/contracts --filter @workspace/api build",
|
|
59
62
|
"dev": "tsup --watch",
|
|
60
63
|
"lint": "eslint",
|
|
61
64
|
"format": "prettier --write \"**/*.{ts,tsx,json,md}\"",
|
|
62
65
|
"typecheck": "tsc --noEmit",
|
|
63
|
-
"pretest": "pnpm --filter @workspace/contracts build && tsup",
|
|
66
|
+
"pretest": "pnpm --filter @workspace/contracts --filter @workspace/api build && tsup",
|
|
64
67
|
"test": "vitest run",
|
|
65
68
|
"test:watch": "vitest",
|
|
66
69
|
"start": "node ./dist/index.js"
|