@deessejs/cli 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +37 -37
- package/package.json +64 -64
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -456
- package/dist/index.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Deessejs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
# @deessejs/cli
|
|
2
|
-
|
|
3
|
-
CLI for the DeesseJS template registry.
|
|
4
|
-
|
|
5
|
-
## Install (V1)
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npx deessejs@latest <command>
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Future (V1.1+, when pro templates need auth): `npm i -g @deessejs/cli`.
|
|
12
|
-
|
|
13
|
-
## Commands
|
|
14
|
-
|
|
15
|
-
| Command | Role |
|
|
16
|
-
|---|---|
|
|
17
|
-
| `deessejs init <slug>` | Clone a template repo + install dependencies |
|
|
18
|
-
| `deessejs list` | List available templates |
|
|
19
|
-
| `deessejs info <slug>` | Show details for one template |
|
|
20
|
-
|
|
21
|
-
## Examples
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
deessejs list
|
|
25
|
-
deessejs list --category saas --json
|
|
26
|
-
deessejs info saas-starter --json
|
|
27
|
-
deessejs init saas-starter
|
|
28
|
-
deessejs init saas-starter --ref develop --no-install
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Global flags
|
|
32
|
-
|
|
33
|
-
- `--api-url <url>` — override the templates endpoint (default: `https://deessejs.com/api/templates`)
|
|
34
|
-
- `--json` — JSON output for scripting
|
|
35
|
-
|
|
36
|
-
## License
|
|
37
|
-
|
|
1
|
+
# @deessejs/cli
|
|
2
|
+
|
|
3
|
+
CLI for the DeesseJS template registry.
|
|
4
|
+
|
|
5
|
+
## Install (V1)
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx deessejs@latest <command>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Future (V1.1+, when pro templates need auth): `npm i -g @deessejs/cli`.
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
| Command | Role |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `deessejs init <slug>` | Clone a template repo + install dependencies |
|
|
18
|
+
| `deessejs list` | List available templates |
|
|
19
|
+
| `deessejs info <slug>` | Show details for one template |
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
deessejs list
|
|
25
|
+
deessejs list --category saas --json
|
|
26
|
+
deessejs info saas-starter --json
|
|
27
|
+
deessejs init saas-starter
|
|
28
|
+
deessejs init saas-starter --ref develop --no-install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Global flags
|
|
32
|
+
|
|
33
|
+
- `--api-url <url>` — override the templates endpoint (default: `https://deessejs.com/api/templates`)
|
|
34
|
+
- `--json` — JSON output for scripting
|
|
35
|
+
|
|
36
|
+
## License
|
|
37
|
+
|
|
38
38
|
UNLICENSED for V1 (private). License TBD before npm publish.
|
package/package.json
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@deessejs/cli",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "CLI for the DeesseJS template registry.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/deessejs/deessejs.git"
|
|
10
|
-
},
|
|
11
|
-
"keywords": [
|
|
12
|
-
"cli",
|
|
13
|
-
"deessejs",
|
|
14
|
-
"saas-template",
|
|
15
|
-
"scaffolding"
|
|
16
|
-
],
|
|
17
|
-
"private": false,
|
|
18
|
-
"bin": {
|
|
19
|
-
"deessejs": "./dist/index.js"
|
|
20
|
-
},
|
|
21
|
-
"main": "./dist/index.js",
|
|
22
|
-
"module": "./dist/index.js",
|
|
23
|
-
"types": "./dist/index.d.ts",
|
|
24
|
-
"files": [
|
|
25
|
-
"dist",
|
|
26
|
-
"README.md",
|
|
27
|
-
"../../LICENSE"
|
|
28
|
-
],
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
},
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@deessejs/cli",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "CLI for the DeesseJS template registry.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/deessejs/deessejs.git"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"cli",
|
|
13
|
+
"deessejs",
|
|
14
|
+
"saas-template",
|
|
15
|
+
"scaffolding"
|
|
16
|
+
],
|
|
17
|
+
"private": false,
|
|
18
|
+
"bin": {
|
|
19
|
+
"deessejs": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"module": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"../../LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@deessejs/errors": "^1.1.1",
|
|
31
|
+
"@deessejs/fp": "^1.0.0",
|
|
32
|
+
"commander": "^12.1.0",
|
|
33
|
+
"ora": "^8.1.1",
|
|
34
|
+
"picocolors": "^1.1.1"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^24",
|
|
38
|
+
"eslint": "^9",
|
|
39
|
+
"prettier": "^3.9.4",
|
|
40
|
+
"prettier-plugin-tailwindcss": "^0.8.0",
|
|
41
|
+
"tsup": "^8.3.5",
|
|
42
|
+
"typescript": "^6.0.3",
|
|
43
|
+
"vitest": "^2.1.5",
|
|
44
|
+
"@workspace/eslint-config": "0.0.0",
|
|
45
|
+
"@workspace/typescript-config": "0.0.0"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18.18.0"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public",
|
|
52
|
+
"provenance": true
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsup",
|
|
56
|
+
"dev": "tsup --watch",
|
|
57
|
+
"lint": "eslint",
|
|
58
|
+
"format": "prettier --write \"**/*.{ts,tsx,json,md}\"",
|
|
59
|
+
"typecheck": "tsc --noEmit",
|
|
60
|
+
"pretest": "tsup",
|
|
61
|
+
"test": "vitest run",
|
|
62
|
+
"test:watch": "vitest",
|
|
63
|
+
"start": "node ./dist/index.js"
|
|
64
|
+
}
|
|
65
65
|
}
|
package/dist/index.d.ts
DELETED
package/dist/index.js
DELETED
|
@@ -1,456 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { Command } from 'commander';
|
|
3
|
-
import pc2 from 'picocolors';
|
|
4
|
-
import { existsSync, readFileSync } from 'fs';
|
|
5
|
-
import { resolve, join } from 'path';
|
|
6
|
-
import ora from 'ora';
|
|
7
|
-
import { spawn as spawn$1 } from 'child_process';
|
|
8
|
-
|
|
9
|
-
// src/constants.ts
|
|
10
|
-
var DEFAULT_API_URL = "https://app.deessejs.com/api/templates";
|
|
11
|
-
var USER_AGENT = "deessejs-cli/0.1.0 (https://deessejs.com)";
|
|
12
|
-
var EXIT_ERROR = 1;
|
|
13
|
-
|
|
14
|
-
// src/errors.ts
|
|
15
|
-
var CliError = class extends Error {
|
|
16
|
-
code;
|
|
17
|
-
hint;
|
|
18
|
-
constructor(code, message, hint) {
|
|
19
|
-
super(message);
|
|
20
|
-
this.name = "CliError";
|
|
21
|
-
this.code = code;
|
|
22
|
-
this.hint = hint;
|
|
23
|
-
}
|
|
24
|
-
exitCode = () => EXIT_ERROR;
|
|
25
|
-
};
|
|
26
|
-
var notFound = (slug, available) => new CliError(
|
|
27
|
-
"not_found",
|
|
28
|
-
`template "${slug}" not found`,
|
|
29
|
-
`available templates: ${available.join(", ")}`
|
|
30
|
-
);
|
|
31
|
-
var networkError = (detail) => new CliError(
|
|
32
|
-
"network_error",
|
|
33
|
-
`could not reach the templates endpoint`,
|
|
34
|
-
detail
|
|
35
|
-
);
|
|
36
|
-
var gitNotInstalled = () => new CliError(
|
|
37
|
-
"git_not_installed",
|
|
38
|
-
"`git` is not installed or not on PATH",
|
|
39
|
-
"install git from https://git-scm.com and try again"
|
|
40
|
-
);
|
|
41
|
-
var targetExists = (dir) => new CliError(
|
|
42
|
-
"target_exists",
|
|
43
|
-
`target directory "${dir}" already exists`,
|
|
44
|
-
"remove the directory or pass --force to overwrite"
|
|
45
|
-
);
|
|
46
|
-
var installFailed = (pm, code) => new CliError(
|
|
47
|
-
"install_failed",
|
|
48
|
-
`${pm} install exited with code ${code ?? "unknown"}`,
|
|
49
|
-
"check the output above, then run the install command manually inside the cloned directory"
|
|
50
|
-
);
|
|
51
|
-
var parseError = (detail) => new CliError(
|
|
52
|
-
"parse_error",
|
|
53
|
-
"templates endpoint returned malformed data",
|
|
54
|
-
detail
|
|
55
|
-
);
|
|
56
|
-
var internal = (detail) => new CliError("internal", "unexpected internal error", detail);
|
|
57
|
-
|
|
58
|
-
// src/api.ts
|
|
59
|
-
var fetchTemplates = async (apiUrl) => {
|
|
60
|
-
let res;
|
|
61
|
-
try {
|
|
62
|
-
res = await fetch(apiUrl, {
|
|
63
|
-
headers: { "user-agent": USER_AGENT, accept: "application/json" }
|
|
64
|
-
});
|
|
65
|
-
} catch (e) {
|
|
66
|
-
throw networkError(
|
|
67
|
-
`fetch failed: ${e instanceof Error ? e.message : String(e)}`
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
if (!res.ok) {
|
|
71
|
-
throw networkError(
|
|
72
|
-
`endpoint returned HTTP ${res.status} ${res.statusText}`
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
let body;
|
|
76
|
-
try {
|
|
77
|
-
body = await res.json();
|
|
78
|
-
} catch (e) {
|
|
79
|
-
throw parseError(
|
|
80
|
-
`endpoint returned non-JSON body: ${e instanceof Error ? e.message : String(e)}`
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
if (!isApiResponse(body)) {
|
|
84
|
-
throw parseError('response is missing "templates" array');
|
|
85
|
-
}
|
|
86
|
-
return body.templates;
|
|
87
|
-
};
|
|
88
|
-
var isApiResponse = (value) => {
|
|
89
|
-
if (typeof value !== "object" || value === null) return false;
|
|
90
|
-
const obj = value;
|
|
91
|
-
if (!Array.isArray(obj.templates)) return false;
|
|
92
|
-
return obj.templates.every(isTemplate);
|
|
93
|
-
};
|
|
94
|
-
var isTemplate = (value) => {
|
|
95
|
-
if (typeof value !== "object" || value === null) return false;
|
|
96
|
-
const obj = value;
|
|
97
|
-
return typeof obj.slug === "string" && typeof obj.name === "string" && typeof obj.description === "string" && typeof obj.owner === "string" && typeof obj.repo === "string" && typeof obj.license === "string" && typeof obj.category === "string" && Array.isArray(obj.labels) && obj.labels.every((l) => typeof l === "string") && (obj.cloneUrl === void 0 || typeof obj.cloneUrl === "string");
|
|
98
|
-
};
|
|
99
|
-
var printJson = (value) => {
|
|
100
|
-
process.stdout.write(JSON.stringify(value, null, 2) + "\n");
|
|
101
|
-
};
|
|
102
|
-
var printError = (err) => {
|
|
103
|
-
process.stderr.write(
|
|
104
|
-
`${pc2.red("Error")}: ${err.message}
|
|
105
|
-
` + (err.hint ? `${pc2.dim("Hint")}: ${err.hint}
|
|
106
|
-
` : "") + `${pc2.dim("Code")}: ${err.code}
|
|
107
|
-
`
|
|
108
|
-
);
|
|
109
|
-
};
|
|
110
|
-
var printTemplatesTable = (templates) => {
|
|
111
|
-
if (templates.length === 0) {
|
|
112
|
-
process.stdout.write(pc2.dim("No templates available.\n"));
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
const headers = ["slug", "name", "category", "license"];
|
|
116
|
-
const rows = templates.map((t) => [
|
|
117
|
-
t.slug,
|
|
118
|
-
t.name,
|
|
119
|
-
t.category,
|
|
120
|
-
t.license
|
|
121
|
-
]);
|
|
122
|
-
printAlignedTable([headers, ...rows]);
|
|
123
|
-
};
|
|
124
|
-
var printTemplateInfo = (t) => {
|
|
125
|
-
const lines = [
|
|
126
|
-
["slug", t.slug],
|
|
127
|
-
["name", t.name],
|
|
128
|
-
["description", t.description],
|
|
129
|
-
["category", t.category],
|
|
130
|
-
["license", t.license],
|
|
131
|
-
["repo", `${t.owner}/${t.repo}`],
|
|
132
|
-
["labels", t.labels.join(", ") || pc2.dim("(none)")]
|
|
133
|
-
];
|
|
134
|
-
if (t.image) lines.push(["image", t.image]);
|
|
135
|
-
const labelWidth = Math.max(...lines.map(([l]) => l.length));
|
|
136
|
-
for (const [label, value] of lines) {
|
|
137
|
-
process.stdout.write(
|
|
138
|
-
`${pc2.dim(label.padEnd(labelWidth))} ${value}
|
|
139
|
-
`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
var printAlignedTable = (rows) => {
|
|
144
|
-
const firstRow = rows[0];
|
|
145
|
-
if (!firstRow) return;
|
|
146
|
-
const widths = firstRow.map(
|
|
147
|
-
(_, col) => Math.max(...rows.map((row) => row[col]?.length ?? 0))
|
|
148
|
-
);
|
|
149
|
-
for (const row of rows) {
|
|
150
|
-
process.stdout.write(
|
|
151
|
-
row.map((cell, i) => cell.padEnd(widths[i] ?? 0)).join(" ") + "\n"
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
var spawn = (command, args, options = {}) => {
|
|
156
|
-
const { cwd, env, stdio = "inherit", reject = false } = options;
|
|
157
|
-
return new Promise((resolve2, rejectFn) => {
|
|
158
|
-
const child = spawn$1(command, args, {
|
|
159
|
-
cwd,
|
|
160
|
-
env: env ?? process.env,
|
|
161
|
-
stdio,
|
|
162
|
-
shell: false
|
|
163
|
-
});
|
|
164
|
-
child.on("error", (err) => rejectFn(err));
|
|
165
|
-
child.on("exit", (code) => {
|
|
166
|
-
const exit = code ?? 1;
|
|
167
|
-
if (reject && exit !== 0) {
|
|
168
|
-
rejectFn(new Error(`${command} exited with code ${exit}`));
|
|
169
|
-
} else {
|
|
170
|
-
resolve2(exit);
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
// src/utils/git.ts
|
|
177
|
-
var cloneRepo = async (url, dir, requestedRef) => {
|
|
178
|
-
const refs = requestedRef ? [requestedRef] : ["main", "master"];
|
|
179
|
-
const attempts = [];
|
|
180
|
-
for (const ref of refs) {
|
|
181
|
-
attempts.push(ref);
|
|
182
|
-
const code = await spawn(
|
|
183
|
-
"git",
|
|
184
|
-
["clone", "--depth", "1", "--branch", ref, url, dir],
|
|
185
|
-
{ stdio: "inherit", reject: false }
|
|
186
|
-
);
|
|
187
|
-
if (code === 0) {
|
|
188
|
-
return { ref, attempts };
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
const probe = await spawn("git", ["--version"], {
|
|
192
|
-
stdio: "ignore",
|
|
193
|
-
reject: false
|
|
194
|
-
});
|
|
195
|
-
if (probe !== 0) {
|
|
196
|
-
throw gitNotInstalled();
|
|
197
|
-
}
|
|
198
|
-
throw new Error(
|
|
199
|
-
`git clone failed for refs: ${refs.join(", ")}. Tried: ${attempts.join(", ")}.`
|
|
200
|
-
);
|
|
201
|
-
};
|
|
202
|
-
var detectPackageManager = (cwd) => {
|
|
203
|
-
const pkg = readPackageJson(cwd);
|
|
204
|
-
if (pkg?.packageManager) {
|
|
205
|
-
const pm = parsePackageManagerField(pkg.packageManager);
|
|
206
|
-
if (pm) return pm;
|
|
207
|
-
}
|
|
208
|
-
if (existsSync(join(cwd, "pnpm-lock.yaml"))) return { pm: "pnpm" };
|
|
209
|
-
if (existsSync(join(cwd, "bun.lockb"))) return { pm: "bun" };
|
|
210
|
-
if (existsSync(join(cwd, "yarn.lock"))) return { pm: "yarn" };
|
|
211
|
-
if (existsSync(join(cwd, "package-lock.json"))) return { pm: "npm" };
|
|
212
|
-
return null;
|
|
213
|
-
};
|
|
214
|
-
var getInstallCommand = (info) => {
|
|
215
|
-
switch (info.pm) {
|
|
216
|
-
case "pnpm":
|
|
217
|
-
return "pnpm install";
|
|
218
|
-
case "npm":
|
|
219
|
-
return "npm install";
|
|
220
|
-
case "yarn":
|
|
221
|
-
return "yarn install";
|
|
222
|
-
case "bun":
|
|
223
|
-
return "bun install";
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
|
-
var readPackageJson = (cwd) => {
|
|
227
|
-
const path = join(cwd, "package.json");
|
|
228
|
-
if (!existsSync(path)) return null;
|
|
229
|
-
try {
|
|
230
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
231
|
-
} catch {
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
var parsePackageManagerField = (raw) => {
|
|
236
|
-
const name = raw.split("@")[0]?.trim().toLowerCase();
|
|
237
|
-
if (name === "pnpm" || name === "npm" || name === "yarn" || name === "bun") {
|
|
238
|
-
return { pm: name, raw };
|
|
239
|
-
}
|
|
240
|
-
return null;
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
// src/commands/init.ts
|
|
244
|
-
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(
|
|
245
|
-
async (slug, opts) => {
|
|
246
|
-
const apiUrl = initCommand.parent?.getOptionValue("apiUrl");
|
|
247
|
-
try {
|
|
248
|
-
const templates = await fetchTemplates(
|
|
249
|
-
apiUrl ?? process.env.DEESSEJS_API_URL ?? "https://deessejs.com/api/templates"
|
|
250
|
-
);
|
|
251
|
-
const template = templates.find((t) => t.slug === slug);
|
|
252
|
-
if (!template) {
|
|
253
|
-
throw notFound(
|
|
254
|
-
slug,
|
|
255
|
-
templates.map((t) => t.slug)
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
const dir = resolve(process.cwd(), opts.dir ?? `./${slug}`);
|
|
259
|
-
if (existsSync(dir) && !opts.force) {
|
|
260
|
-
throw targetExists(dir);
|
|
261
|
-
}
|
|
262
|
-
const repoUrl = template.cloneUrl ?? `https://github.com/${template.owner}/${template.repo}`;
|
|
263
|
-
const cloneSpinner = ora(`Cloning ${pc2.cyan(template.owner + "/" + template.repo)}...`).start();
|
|
264
|
-
let cloneResult;
|
|
265
|
-
try {
|
|
266
|
-
cloneResult = await cloneRepo(repoUrl, dir, opts.ref);
|
|
267
|
-
cloneSpinner.succeed(`Cloned into ${pc2.cyan(dir)} (ref: ${cloneResult.ref})`);
|
|
268
|
-
} catch (err) {
|
|
269
|
-
cloneSpinner.fail("Clone failed");
|
|
270
|
-
throw err;
|
|
271
|
-
}
|
|
272
|
-
if (!opts.install) {
|
|
273
|
-
if (opts.json) {
|
|
274
|
-
printJson({
|
|
275
|
-
ok: true,
|
|
276
|
-
slug: template.slug,
|
|
277
|
-
dir,
|
|
278
|
-
ref: cloneResult.ref,
|
|
279
|
-
installed: false
|
|
280
|
-
});
|
|
281
|
-
} else {
|
|
282
|
-
console.log(pc2.dim(`
|
|
283
|
-
Next: cd ${dir} && <your package manager> install
|
|
284
|
-
`));
|
|
285
|
-
}
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
const VALID_PMS = ["pnpm", "npm", "yarn", "bun"];
|
|
289
|
-
const pmInfo = opts.pm && VALID_PMS.includes(opts.pm) ? { pm: opts.pm } : detectPackageManager(dir);
|
|
290
|
-
if (!pmInfo) {
|
|
291
|
-
console.log(
|
|
292
|
-
pc2.yellow(
|
|
293
|
-
"\nNo package manager detected (no packageManager field, no lockfile)."
|
|
294
|
-
)
|
|
295
|
-
);
|
|
296
|
-
console.log(
|
|
297
|
-
pc2.dim("Skipping install. Run your install command manually inside the directory.\n")
|
|
298
|
-
);
|
|
299
|
-
} else {
|
|
300
|
-
const installSpinner = ora(
|
|
301
|
-
`Installing dependencies via ${pc2.cyan(pmInfo.pm)}...`
|
|
302
|
-
).start();
|
|
303
|
-
const cmd = getInstallCommand(pmInfo);
|
|
304
|
-
const cmdParts = cmd.split(" ");
|
|
305
|
-
const bin = cmdParts[0] ?? "npm";
|
|
306
|
-
const args = cmdParts.slice(1);
|
|
307
|
-
const code = await spawn(bin, args, { cwd: dir, stdio: "inherit", reject: false });
|
|
308
|
-
if (code !== 0) {
|
|
309
|
-
installSpinner.fail(`${pmInfo.pm} install failed`);
|
|
310
|
-
throw installFailed(pmInfo.pm, code);
|
|
311
|
-
}
|
|
312
|
-
installSpinner.succeed("Dependencies installed");
|
|
313
|
-
}
|
|
314
|
-
if (opts.json) {
|
|
315
|
-
printJson({
|
|
316
|
-
ok: true,
|
|
317
|
-
slug: template.slug,
|
|
318
|
-
dir,
|
|
319
|
-
ref: cloneResult.ref,
|
|
320
|
-
installed: pmInfo !== null,
|
|
321
|
-
packageManager: pmInfo?.pm ?? null
|
|
322
|
-
});
|
|
323
|
-
} else {
|
|
324
|
-
console.log();
|
|
325
|
-
console.log(pc2.green("\u2713 Template ready"));
|
|
326
|
-
console.log(pc2.dim(` cd ${dir}`));
|
|
327
|
-
console.log(
|
|
328
|
-
pc2.dim(
|
|
329
|
-
pmInfo ? ` ${getInstallCommand(pmInfo).split(" ")[0]} dev` : ` install deps, then start`
|
|
330
|
-
)
|
|
331
|
-
);
|
|
332
|
-
console.log();
|
|
333
|
-
}
|
|
334
|
-
} catch (err) {
|
|
335
|
-
if (err instanceof Error && err.name === "CliError") {
|
|
336
|
-
if (opts.json) {
|
|
337
|
-
printJson({
|
|
338
|
-
ok: false,
|
|
339
|
-
code: err.code,
|
|
340
|
-
message: err.message,
|
|
341
|
-
hint: err.hint
|
|
342
|
-
});
|
|
343
|
-
} else {
|
|
344
|
-
printError(err);
|
|
345
|
-
}
|
|
346
|
-
process.exit(err.exitCode?.() ?? 1);
|
|
347
|
-
}
|
|
348
|
-
throw internal(err instanceof Error ? err.message : String(err));
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
);
|
|
352
|
-
var listCommand = new Command("list").description("List available templates").option("--category <name>", "filter to a single category").option("--json", "JSON output for scripting").action(
|
|
353
|
-
async (opts, command) => {
|
|
354
|
-
const apiUrl = command.parent?.getOptionValue("apiUrl");
|
|
355
|
-
const spinner = opts.json ? null : ora("Fetching templates...").start();
|
|
356
|
-
try {
|
|
357
|
-
const all = await fetchTemplates(
|
|
358
|
-
apiUrl ?? process.env.DEESSEJS_API_URL ?? "https://deessejs.com/api/templates"
|
|
359
|
-
);
|
|
360
|
-
const filtered = opts.category ? all.filter((t) => t.category === opts.category) : all;
|
|
361
|
-
spinner?.stop();
|
|
362
|
-
if (opts.json) {
|
|
363
|
-
printJson({ templates: filtered });
|
|
364
|
-
} else {
|
|
365
|
-
if (opts.category) {
|
|
366
|
-
console.log(pc2.dim(`Category: ${opts.category}`));
|
|
367
|
-
}
|
|
368
|
-
printTemplatesTable(filtered);
|
|
369
|
-
console.log();
|
|
370
|
-
console.log(
|
|
371
|
-
pc2.dim(
|
|
372
|
-
`${filtered.length} template${filtered.length === 1 ? "" : "s"}.` + (opts.category ? "" : " Use --category <name> to filter, --json for scripting.")
|
|
373
|
-
)
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
} catch (err) {
|
|
377
|
-
spinner?.fail("Failed to fetch templates");
|
|
378
|
-
if (err instanceof Error && err.name === "CliError") {
|
|
379
|
-
if (opts.json) {
|
|
380
|
-
printJson({
|
|
381
|
-
ok: false,
|
|
382
|
-
code: err.code,
|
|
383
|
-
message: err.message,
|
|
384
|
-
hint: err.hint
|
|
385
|
-
});
|
|
386
|
-
} else {
|
|
387
|
-
printError(err);
|
|
388
|
-
}
|
|
389
|
-
process.exit(1);
|
|
390
|
-
}
|
|
391
|
-
throw internal(err instanceof Error ? err.message : String(err));
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
);
|
|
395
|
-
var infoCommand = new Command("info").description("Show details for one template").argument("<slug>", "template slug").option("--json", "JSON output for scripting").action(
|
|
396
|
-
async (slug, opts, command) => {
|
|
397
|
-
const apiUrl = command.parent?.getOptionValue("apiUrl");
|
|
398
|
-
const spinner = opts.json ? null : ora("Fetching template...").start();
|
|
399
|
-
try {
|
|
400
|
-
const all = await fetchTemplates(
|
|
401
|
-
apiUrl ?? process.env.DEESSEJS_API_URL ?? "https://deessejs.com/api/templates"
|
|
402
|
-
);
|
|
403
|
-
const template = all.find((t) => t.slug === slug);
|
|
404
|
-
spinner?.stop();
|
|
405
|
-
if (!template) {
|
|
406
|
-
throw notFound(slug, all.map((t) => t.slug));
|
|
407
|
-
}
|
|
408
|
-
if (opts.json) {
|
|
409
|
-
printJson({ template });
|
|
410
|
-
} else {
|
|
411
|
-
printTemplateInfo(template);
|
|
412
|
-
console.log();
|
|
413
|
-
console.log(
|
|
414
|
-
`Install: ${`deessejs init ${template.slug}`}`
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
} catch (err) {
|
|
418
|
-
spinner?.fail("Failed to fetch template");
|
|
419
|
-
if (err instanceof Error && err.name === "CliError") {
|
|
420
|
-
if (opts.json) {
|
|
421
|
-
printJson({
|
|
422
|
-
ok: false,
|
|
423
|
-
code: err.code,
|
|
424
|
-
message: err.message,
|
|
425
|
-
hint: err.hint
|
|
426
|
-
});
|
|
427
|
-
} else {
|
|
428
|
-
printError(err);
|
|
429
|
-
}
|
|
430
|
-
process.exit(1);
|
|
431
|
-
}
|
|
432
|
-
throw internal(err instanceof Error ? err.message : String(err));
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
);
|
|
436
|
-
|
|
437
|
-
// src/index.ts
|
|
438
|
-
var program = new Command();
|
|
439
|
-
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);
|
|
440
|
-
program.addCommand(listCommand);
|
|
441
|
-
program.addCommand(infoCommand);
|
|
442
|
-
program.addCommand(initCommand);
|
|
443
|
-
program.parseAsync(process.argv).catch((err) => {
|
|
444
|
-
process.stderr.write(
|
|
445
|
-
`${pc2.red("Internal error")}: ${err instanceof Error ? err.message : String(err)}
|
|
446
|
-
`
|
|
447
|
-
);
|
|
448
|
-
if (process.env.DEESSEJS_DEBUG) {
|
|
449
|
-
process.stderr.write(`
|
|
450
|
-
${err instanceof Error && err.stack ? err.stack : ""}
|
|
451
|
-
`);
|
|
452
|
-
}
|
|
453
|
-
process.exit(1);
|
|
454
|
-
});
|
|
455
|
-
//# sourceMappingURL=index.js.map
|
|
456
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/errors.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":["pc","resolve","nodeSpawn","existsSync","Command","ora"],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_API_URL = \"https://app.deessejs.com/api/templates\"\r\n\r\nexport const USER_AGENT = \"deessejs-cli/0.1.0 (https://deessejs.com)\"\r\n\r\nexport const EXIT_SUCCESS = 0\r\nexport const EXIT_ERROR = 1","import { EXIT_ERROR } from \"./constants.js\"\r\n\r\nexport type CliErrorCode =\r\n | \"not_found\"\r\n | \"network_error\"\r\n | \"git_not_installed\"\r\n | \"target_exists\"\r\n | \"install_failed\"\r\n | \"parse_error\"\r\n | \"internal\"\r\n\r\nexport class CliError extends Error {\r\n public readonly code: CliErrorCode\r\n public readonly hint: string | undefined\r\n\r\n constructor(code: CliErrorCode, message: string, hint?: string) {\r\n super(message)\r\n this.name = \"CliError\"\r\n this.code = code\r\n this.hint = hint\r\n }\r\n\r\n public exitCode = (): number => EXIT_ERROR\r\n}\r\n\r\nexport const notFound = (slug: string, available: string[]): CliError =>\r\n new CliError(\r\n \"not_found\",\r\n `template \"${slug}\" not found`,\r\n `available templates: ${available.join(\", \")}`,\r\n )\r\n\r\nexport const networkError = (detail: string): CliError =>\r\n new CliError(\r\n \"network_error\",\r\n `could not reach the templates endpoint`,\r\n detail,\r\n )\r\n\r\nexport const gitNotInstalled = (): CliError =>\r\n new CliError(\r\n \"git_not_installed\",\r\n \"`git` is not installed or not on PATH\",\r\n \"install git from https://git-scm.com and try again\",\r\n )\r\n\r\nexport const targetExists = (dir: string): CliError =>\r\n new CliError(\r\n \"target_exists\",\r\n `target directory \"${dir}\" already exists`,\r\n \"remove the directory or pass --force to overwrite\",\r\n )\r\n\r\nexport const installFailed = (\r\n pm: string,\r\n code: number | null,\r\n): CliError =>\r\n new CliError(\r\n \"install_failed\",\r\n `${pm} install exited with code ${code ?? \"unknown\"}`,\r\n \"check the output above, then run the install command manually inside the cloned directory\",\r\n )\r\n\r\nexport const parseError = (detail: string): CliError =>\r\n new CliError(\r\n \"parse_error\",\r\n \"templates endpoint returned malformed data\",\r\n detail,\r\n )\r\n\r\nexport const internal = (detail: string): CliError =>\r\n new CliError(\"internal\", \"unexpected internal error\", detail)","import { USER_AGENT } from \"./constants.js\"\r\nimport { networkError, parseError } from \"./errors.js\"\r\n\r\nexport type Template = {\r\n slug: string\r\n name: string\r\n description: string\r\n owner: string\r\n repo: string\r\n license: string\r\n category: string\r\n labels: string[]\r\n image?: string\r\n /** Optional override for the clone URL. Falls back to `https://github.com/<owner>/<repo>`. */\r\n cloneUrl?: string\r\n}\r\n\r\nexport type ApiResponse = { templates: Template[] }\r\n\r\nexport const fetchTemplates = async (\r\n apiUrl: string,\r\n): Promise<Template[]> => {\r\n let res: Response\r\n try {\r\n res = await fetch(apiUrl, {\r\n headers: { \"user-agent\": USER_AGENT, accept: \"application/json\" },\r\n })\r\n } catch (e) {\r\n throw networkError(\r\n `fetch failed: ${e instanceof Error ? e.message : String(e)}`,\r\n )\r\n }\r\n\r\n if (!res.ok) {\r\n throw networkError(\r\n `endpoint returned HTTP ${res.status} ${res.statusText}`,\r\n )\r\n }\r\n\r\n let body: unknown\r\n try {\r\n body = await res.json()\r\n } catch (e) {\r\n throw parseError(\r\n `endpoint returned non-JSON body: ${e instanceof Error ? e.message : String(e)}`,\r\n )\r\n }\r\n\r\n if (!isApiResponse(body)) {\r\n throw parseError('response is missing \"templates\" array')\r\n }\r\n\r\n return body.templates\r\n}\r\n\r\nconst isApiResponse = (value: unknown): value is ApiResponse => {\r\n if (typeof value !== \"object\" || value === null) return false\r\n const obj = value as Record<string, unknown>\r\n if (!Array.isArray(obj.templates)) return false\r\n return obj.templates.every(isTemplate)\r\n}\r\n\r\nconst isTemplate = (value: unknown): value is Template => {\r\n if (typeof value !== \"object\" || value === null) return false\r\n const obj = value as Record<string, unknown>\r\n return (\r\n typeof obj.slug === \"string\" &&\r\n typeof obj.name === \"string\" &&\r\n typeof obj.description === \"string\" &&\r\n typeof obj.owner === \"string\" &&\r\n typeof obj.repo === \"string\" &&\r\n typeof obj.license === \"string\" &&\r\n typeof obj.category === \"string\" &&\r\n Array.isArray(obj.labels) &&\r\n obj.labels.every((l) => typeof l === \"string\") &&\r\n (obj.cloneUrl === undefined || typeof obj.cloneUrl === \"string\")\r\n )\r\n}","import pc from \"picocolors\"\r\nimport type { CliError } from \"./errors.js\"\r\nimport type { Template } from \"./api.js\"\r\n\r\nexport const printJson = (value: unknown): void => {\r\n process.stdout.write(JSON.stringify(value, null, 2) + \"\\n\")\r\n}\r\n\r\nexport const printError = (err: CliError): void => {\r\n process.stderr.write(\r\n `${pc.red(\"Error\")}: ${err.message}\\n` +\r\n (err.hint ? `${pc.dim(\"Hint\")}: ${err.hint}\\n` : \"\") +\r\n `${pc.dim(\"Code\")}: ${err.code}\\n`,\r\n )\r\n}\r\n\r\nexport const printTemplatesTable = (templates: Template[]): void => {\r\n if (templates.length === 0) {\r\n process.stdout.write(pc.dim(\"No templates available.\\n\"))\r\n return\r\n }\r\n const headers = [\"slug\", \"name\", \"category\", \"license\"]\r\n const rows = templates.map((t) => [\r\n t.slug,\r\n t.name,\r\n t.category,\r\n t.license,\r\n ])\r\n printAlignedTable([headers, ...rows])\r\n}\r\n\r\nexport const printTemplateInfo = (t: Template): void => {\r\n const lines: Array<[string, string]> = [\r\n [\"slug\", t.slug],\r\n [\"name\", t.name],\r\n [\"description\", t.description],\r\n [\"category\", t.category],\r\n [\"license\", t.license],\r\n [\"repo\", `${t.owner}/${t.repo}`],\r\n [\"labels\", t.labels.join(\", \") || pc.dim(\"(none)\")],\r\n ]\r\n if (t.image) lines.push([\"image\", t.image])\r\n\r\n const labelWidth = Math.max(...lines.map(([l]) => l.length))\r\n for (const [label, value] of lines) {\r\n process.stdout.write(\r\n `${pc.dim(label.padEnd(labelWidth))} ${value}\\n`,\r\n )\r\n }\r\n}\r\n\r\nconst printAlignedTable = (rows: string[][]): void => {\r\n const firstRow = rows[0]\r\n if (!firstRow) return\r\n const widths = firstRow.map((_, col) =>\r\n Math.max(...rows.map((row) => row[col]?.length ?? 0)),\r\n )\r\n for (const row of rows) {\r\n process.stdout.write(\r\n row.map((cell, i) => cell.padEnd(widths[i] ?? 0)).join(\" \") + \"\\n\",\r\n )\r\n }\r\n}","import { spawn as nodeSpawn } from \"node:child_process\"\r\n\r\nexport type SpawnOptions = {\r\n cwd?: string\r\n env?: NodeJS.ProcessEnv\r\n stdio?: \"inherit\" | \"pipe\" | \"ignore\"\r\n /** If true, do not throw on non-zero exit codes. Default is `true` (no throw). */\r\n reject?: boolean\r\n}\r\n\r\n/**\r\n * Run a command and resolve with its exit code. Never throws on non-zero by\r\n * default; pass `reject: true` to opt into throwing.\r\n */\r\nexport const spawn = (\r\n command: string,\r\n args: string[],\r\n options: SpawnOptions = {},\r\n): Promise<number> => {\r\n const { cwd, env, stdio = \"inherit\", reject = false } = options\r\n return new Promise((resolve, rejectFn) => {\r\n const child = nodeSpawn(command, args, {\r\n cwd,\r\n env: env ?? process.env,\r\n stdio,\r\n shell: false,\r\n })\r\n child.on(\"error\", (err) => rejectFn(err))\r\n child.on(\"exit\", (code) => {\r\n const exit = code ?? 1\r\n if (reject && exit !== 0) {\r\n rejectFn(new Error(`${command} exited with code ${exit}`))\r\n } else {\r\n resolve(exit)\r\n }\r\n })\r\n })\r\n}","import { spawn } from \"./spawn.js\"\r\nimport { gitNotInstalled } from \"../errors.js\"\r\n\r\nexport type CloneResult = {\r\n ref: string\r\n attempts: string[]\r\n}\r\n\r\n/**\r\n * Clone a git repo to `dir`. Tries `main` first, then falls back to `master`.\r\n * Caller can pass an explicit `--ref` to override.\r\n */\r\nexport const cloneRepo = async (\r\n url: string,\r\n dir: string,\r\n requestedRef?: string,\r\n): Promise<CloneResult> => {\r\n const refs = requestedRef ? [requestedRef] : [\"main\", \"master\"]\r\n const attempts: string[] = []\r\n\r\n for (const ref of refs) {\r\n attempts.push(ref)\r\n const code = await spawn(\r\n \"git\",\r\n [\"clone\", \"--depth\", \"1\", \"--branch\", ref, url, dir],\r\n { stdio: \"inherit\", reject: false },\r\n )\r\n if (code === 0) {\r\n return { ref, attempts }\r\n }\r\n }\r\n\r\n // All attempts failed. Probe whether git is even installed.\r\n const probe = await spawn(\"git\", [\"--version\"], {\r\n stdio: \"ignore\",\r\n reject: false,\r\n })\r\n if (probe !== 0) {\r\n throw gitNotInstalled()\r\n }\r\n\r\n // Git works but neither ref matched. Re-throw with attempts context.\r\n throw new Error(\r\n `git clone failed for refs: ${refs.join(\", \")}. Tried: ${attempts.join(\", \")}.`,\r\n )\r\n}","import { existsSync, readFileSync } from \"node:fs\"\r\nimport { join } from \"node:path\"\r\n\r\nexport type PackageManager = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\"\r\n\r\nexport type PackageManagerInfo = {\r\n pm: PackageManager\r\n /** Raw value from packageManager field, e.g. \"pnpm@9.0.0\". May include version. */\r\n raw?: string\r\n}\r\n\r\n/**\r\n * Detect the package manager for a directory, in priority order:\r\n * 1. `packageManager` field in package.json (Corepack convention)\r\n * 2. Lockfile presence\r\n * 3. Returns null if nothing matches (caller decides whether to fail)\r\n */\r\nexport const detectPackageManager = (\r\n cwd: string,\r\n): PackageManagerInfo | null => {\r\n const pkg = readPackageJson(cwd)\r\n if (pkg?.packageManager) {\r\n const pm = parsePackageManagerField(pkg.packageManager)\r\n if (pm) return pm\r\n }\r\n\r\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return { pm: \"pnpm\" }\r\n if (existsSync(join(cwd, \"bun.lockb\"))) return { pm: \"bun\" }\r\n if (existsSync(join(cwd, \"yarn.lock\"))) return { pm: \"yarn\" }\r\n if (existsSync(join(cwd, \"package-lock.json\"))) return { pm: \"npm\" }\r\n\r\n return null\r\n}\r\n\r\nexport const getInstallCommand = (info: PackageManagerInfo): string => {\r\n switch (info.pm) {\r\n case \"pnpm\":\r\n return \"pnpm install\"\r\n case \"npm\":\r\n return \"npm install\"\r\n case \"yarn\":\r\n return \"yarn install\"\r\n case \"bun\":\r\n return \"bun install\"\r\n }\r\n}\r\n\r\nconst readPackageJson = (\r\n cwd: string,\r\n): { packageManager?: string } | null => {\r\n const path = join(cwd, \"package.json\")\r\n if (!existsSync(path)) return null\r\n try {\r\n return JSON.parse(readFileSync(path, \"utf8\")) as {\r\n packageManager?: string\r\n }\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\nexport const parsePackageManagerField = (\r\n raw: string,\r\n): PackageManagerInfo | null => {\r\n // Format: \"<name>@<version>\" or just \"<name>\". Common names: pnpm, npm, yarn, bun.\r\n const name = raw.split(\"@\")[0]?.trim().toLowerCase()\r\n if (name === \"pnpm\" || name === \"npm\" || name === \"yarn\" || name === \"bun\") {\r\n return { pm: name, raw }\r\n }\r\n return null\r\n}","import { existsSync } from \"node:fs\"\r\nimport { resolve } from \"node:path\"\r\nimport { Command } from \"commander\"\r\nimport ora from \"ora\"\r\nimport pc from \"picocolors\"\r\nimport { fetchTemplates } from \"../api.js\"\r\nimport {\r\n installFailed,\r\n internal,\r\n notFound,\r\n targetExists,\r\n} from \"../errors.js\"\r\nimport { printError, printJson } from \"../output.js\"\r\nimport { cloneRepo } from \"../utils/git.js\"\r\nimport {\r\n detectPackageManager,\r\n getInstallCommand,\r\n type PackageManagerInfo,\r\n} from \"../utils/detect-pm.js\"\r\nimport { spawn } from \"../utils/spawn.js\"\r\n\r\nexport const initCommand = new Command(\"init\")\r\n .description(\"Clone a template repo + install dependencies\")\r\n .argument(\"<slug>\", \"template slug (use `deessejs list` to see options)\")\r\n .option(\"--pm <name>\", \"override detected package manager (pnpm|npm|yarn|bun)\")\r\n .option(\"--dir <path>\", \"target directory (default: ./<slug>)\")\r\n .option(\"--ref <branch>\", \"git ref to clone (default: tries main, falls back to master)\")\r\n .option(\"--no-install\", \"skip the install step\")\r\n .option(\"--force\", \"overwrite target directory if it exists\")\r\n .option(\"--json\", \"JSON output for scripting\")\r\n .action(\r\n async (\r\n slug: string,\r\n opts: {\r\n pm?: string\r\n dir?: string\r\n ref?: string\r\n install: boolean\r\n force?: boolean\r\n json?: boolean\r\n },\r\n ) => {\r\n const apiUrl = initCommand.parent?.getOptionValue(\"apiUrl\") as\r\n | string\r\n | undefined\r\n\r\n try {\r\n const templates = await fetchTemplates(\r\n apiUrl ?? process.env.DEESSEJS_API_URL ?? \"https://deessejs.com/api/templates\",\r\n )\r\n const template = templates.find((t) => t.slug === slug)\r\n if (!template) {\r\n throw notFound(\r\n slug,\r\n templates.map((t) => t.slug),\r\n )\r\n }\r\n\r\n const dir = resolve(process.cwd(), opts.dir ?? `./${slug}`)\r\n if (existsSync(dir) && !opts.force) {\r\n throw targetExists(dir)\r\n }\r\n\r\n const repoUrl =\r\n template.cloneUrl ?? `https://github.com/${template.owner}/${template.repo}`\r\n\r\n const cloneSpinner = ora(`Cloning ${pc.cyan(template.owner + \"/\" + template.repo)}...`).start()\r\n let cloneResult\r\n try {\r\n cloneResult = await cloneRepo(repoUrl, dir, opts.ref)\r\n cloneSpinner.succeed(`Cloned into ${pc.cyan(dir)} (ref: ${cloneResult.ref})`)\r\n } catch (err) {\r\n cloneSpinner.fail(\"Clone failed\")\r\n throw err\r\n }\r\n\r\n if (!opts.install) {\r\n if (opts.json) {\r\n printJson({\r\n ok: true,\r\n slug: template.slug,\r\n dir,\r\n ref: cloneResult.ref,\r\n installed: false,\r\n })\r\n } else {\r\n console.log(pc.dim(`\\nNext: cd ${dir} && <your package manager> install\\n`))\r\n }\r\n return\r\n }\r\n\r\n const VALID_PMS = [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const\r\n type ValidPm = (typeof VALID_PMS)[number]\r\n const pmInfo: PackageManagerInfo | null =\r\n opts.pm && (VALID_PMS as readonly string[]).includes(opts.pm)\r\n ? { pm: opts.pm as ValidPm }\r\n : detectPackageManager(dir)\r\n\r\n if (!pmInfo) {\r\n console.log(\r\n pc.yellow(\r\n \"\\nNo package manager detected (no packageManager field, no lockfile).\",\r\n ),\r\n )\r\n console.log(\r\n pc.dim(\"Skipping install. Run your install command manually inside the directory.\\n\"),\r\n )\r\n } else {\r\n const installSpinner = ora(\r\n `Installing dependencies via ${pc.cyan(pmInfo.pm)}...`,\r\n ).start()\r\n const cmd = getInstallCommand(pmInfo)\r\n const cmdParts = cmd.split(\" \")\r\n const bin = cmdParts[0] ?? \"npm\"\r\n const args = cmdParts.slice(1)\r\n const code = await spawn(bin, args, { cwd: dir, stdio: \"inherit\", reject: false })\r\n if (code !== 0) {\r\n installSpinner.fail(`${pmInfo.pm} install failed`)\r\n throw installFailed(pmInfo.pm, code)\r\n }\r\n installSpinner.succeed(\"Dependencies installed\")\r\n }\r\n\r\n if (opts.json) {\r\n printJson({\r\n ok: true,\r\n slug: template.slug,\r\n dir,\r\n ref: cloneResult.ref,\r\n installed: pmInfo !== null,\r\n packageManager: pmInfo?.pm ?? null,\r\n })\r\n } else {\r\n console.log()\r\n console.log(pc.green(\"✓ Template ready\"))\r\n console.log(pc.dim(` cd ${dir}`))\r\n console.log(\r\n pc.dim(\r\n pmInfo\r\n ? ` ${getInstallCommand(pmInfo).split(\" \")[0]} dev`\r\n : ` install deps, then start`,\r\n ),\r\n )\r\n console.log()\r\n }\r\n } catch (err) {\r\n if (err instanceof Error && err.name === \"CliError\") {\r\n if (opts.json) {\r\n printJson({\r\n ok: false,\r\n code: (err as { code?: string }).code,\r\n message: err.message,\r\n hint: (err as { hint?: string }).hint,\r\n })\r\n } else {\r\n printError(err as Parameters<typeof printError>[0])\r\n }\r\n process.exit((err as { exitCode?: () => number }).exitCode?.() ?? 1)\r\n }\r\n throw internal(err instanceof Error ? err.message : String(err))\r\n }\r\n },\r\n )","import { Command } from \"commander\"\r\nimport ora from \"ora\"\r\nimport pc from \"picocolors\"\r\nimport { fetchTemplates } from \"../api.js\"\r\nimport { internal } from \"../errors.js\"\r\nimport { printError, printJson, printTemplatesTable } from \"../output.js\"\r\n\r\nexport const listCommand = new Command(\"list\")\r\n .description(\"List available templates\")\r\n .option(\"--category <name>\", \"filter to a single category\")\r\n .option(\"--json\", \"JSON output for scripting\")\r\n .action(\r\n async (\r\n opts: { category?: string; json?: boolean },\r\n command: Command,\r\n ) => {\r\n const apiUrl = command.parent?.getOptionValue(\"apiUrl\") as\r\n | string\r\n | undefined\r\n\r\n const spinner = opts.json\r\n ? null\r\n : ora(\"Fetching templates...\").start()\r\n\r\n try {\r\n const all = await fetchTemplates(\r\n apiUrl ?? process.env.DEESSEJS_API_URL ?? \"https://deessejs.com/api/templates\",\r\n )\r\n const filtered = opts.category\r\n ? all.filter((t) => t.category === opts.category)\r\n : all\r\n\r\n spinner?.stop()\r\n\r\n if (opts.json) {\r\n printJson({ templates: filtered })\r\n } else {\r\n if (opts.category) {\r\n console.log(pc.dim(`Category: ${opts.category}`))\r\n }\r\n printTemplatesTable(filtered)\r\n console.log()\r\n console.log(\r\n pc.dim(\r\n `${filtered.length} template${filtered.length === 1 ? \"\" : \"s\"}.` +\r\n (opts.category\r\n ? \"\"\r\n : \" Use --category <name> to filter, --json for scripting.\"),\r\n ),\r\n )\r\n }\r\n } catch (err) {\r\n spinner?.fail(\"Failed to fetch templates\")\r\n if (err instanceof Error && err.name === \"CliError\") {\r\n if (opts.json) {\r\n printJson({\r\n ok: false,\r\n code: (err as { code?: string }).code,\r\n message: err.message,\r\n hint: (err as { hint?: string }).hint,\r\n })\r\n } else {\r\n printError(err as Parameters<typeof printError>[0])\r\n }\r\n process.exit(1)\r\n }\r\n throw internal(err instanceof Error ? err.message : String(err))\r\n }\r\n },\r\n )","import { Command } from \"commander\"\r\nimport ora from \"ora\"\r\nimport { fetchTemplates } from \"../api.js\"\r\nimport { internal, notFound } from \"../errors.js\"\r\nimport { printError, printJson, printTemplateInfo } from \"../output.js\"\r\n\r\nexport const infoCommand = new Command(\"info\")\r\n .description(\"Show details for one template\")\r\n .argument(\"<slug>\", \"template slug\")\r\n .option(\"--json\", \"JSON output for scripting\")\r\n .action(\r\n async (slug: string, opts: { json?: boolean }, command: Command) => {\r\n const apiUrl = command.parent?.getOptionValue(\"apiUrl\") as\r\n | string\r\n | undefined\r\n\r\n const spinner = opts.json ? null : ora(\"Fetching template...\").start()\r\n\r\n try {\r\n const all = await fetchTemplates(\r\n apiUrl ?? process.env.DEESSEJS_API_URL ?? \"https://deessejs.com/api/templates\",\r\n )\r\n const template = all.find((t) => t.slug === slug)\r\n spinner?.stop()\r\n\r\n if (!template) {\r\n throw notFound(slug, all.map((t) => t.slug))\r\n }\r\n\r\n if (opts.json) {\r\n printJson({ template })\r\n } else {\r\n printTemplateInfo(template)\r\n console.log()\r\n console.log(\r\n `Install: ${`deessejs init ${template.slug}`}`,\r\n )\r\n }\r\n } catch (err) {\r\n spinner?.fail(\"Failed to fetch template\")\r\n if (err instanceof Error && err.name === \"CliError\") {\r\n if (opts.json) {\r\n printJson({\r\n ok: false,\r\n code: (err as { code?: string }).code,\r\n message: err.message,\r\n hint: (err as { hint?: string }).hint,\r\n })\r\n } else {\r\n printError(err as Parameters<typeof printError>[0])\r\n }\r\n process.exit(1)\r\n }\r\n throw internal(err instanceof Error ? err.message : String(err))\r\n }\r\n },\r\n )","import { Command } from \"commander\"\r\nimport pc from \"picocolors\"\r\nimport { DEFAULT_API_URL, USER_AGENT } from \"./constants.js\"\r\nimport { initCommand } from \"./commands/init.js\"\r\nimport { listCommand } from \"./commands/list.js\"\r\nimport { infoCommand } from \"./commands/info.js\"\r\n\r\nconst program = new Command()\r\n\r\nprogram\r\n .name(\"deessejs\")\r\n .description(\"CLI for the DeesseJS template registry\")\r\n .version(\"0.1.0\")\r\n .option(\"--api-url <url>\", \"templates endpoint URL\", process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL)\r\n\r\nprogram.addCommand(listCommand)\r\nprogram.addCommand(infoCommand)\r\nprogram.addCommand(initCommand)\r\n\r\nprogram.parseAsync(process.argv).catch((err) => {\r\n // Last-resort error handler. Per-command handlers catch CliError and exit\r\n // cleanly with the right code. Anything that lands here is an uncaught bug.\r\n process.stderr.write(\r\n `${pc.red(\"Internal error\")}: ${err instanceof Error ? err.message : String(err)}\\n`,\r\n )\r\n if (process.env.DEESSEJS_DEBUG) {\r\n process.stderr.write(`\\n${err instanceof Error && err.stack ? err.stack : \"\"}\\n`)\r\n }\r\n process.exit(1)\r\n})\r\n\r\nvoid USER_AGENT // re-exported for downstream consumers if needed"]}
|