create-zenbu-app 0.0.19 → 0.0.21
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/README.md +0 -50
- package/dist/index.mjs +47 -1
- package/package.json +1 -1
- package/templates/tailwind/package.json +2 -1
- package/templates/tailwind/src/main/services/cwd.ts.tmpl +7 -0
- package/templates/tailwind/src/renderer/App.tsx.tmpl +1 -1
- package/templates/vanilla/package.json +2 -1
- package/templates/vanilla/src/main/services/cwd.ts.tmpl +7 -0
- package/templates/vanilla/src/renderer/App.tsx.tmpl +1 -1
- package/templates/tailwind/src/main/services/repo.ts.tmpl +0 -11
- package/templates/vanilla/src/main/services/repo.ts.tmpl +0 -11
package/README.md
CHANGED
|
@@ -8,53 +8,3 @@ cd my-app
|
|
|
8
8
|
pnpm dev
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
## Interactive mode
|
|
12
|
-
|
|
13
|
-
Run with no arguments to be prompted for a project name and config options:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
pnpm create zenbu-app
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
You'll be asked for:
|
|
20
|
-
|
|
21
|
-
- **Project name** — defaults to `my-zenbu-app` (just press enter to accept).
|
|
22
|
-
- **Use Tailwind CSS?** — defaults to `yes`.
|
|
23
|
-
|
|
24
|
-
Each prompt's default is selected when you press enter, so a default scaffold
|
|
25
|
-
is just `enter, enter, enter`.
|
|
26
|
-
|
|
27
|
-
## Flags
|
|
28
|
-
|
|
29
|
-
| Flag | Description |
|
|
30
|
-
|---|---|
|
|
31
|
-
| `--yes`, `-y` | Skip every prompt and take each option's default. With no project name, scaffolds into the current directory. |
|
|
32
|
-
| `--no-install` | Skip the post-copy `<pm> install` step. |
|
|
33
|
-
|
|
34
|
-
A few common invocations:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
pnpm create zenbu-app # interactive, then scaffolds ./my-zenbu-app
|
|
38
|
-
pnpm create zenbu-app my-app # interactive options, scaffolds ./my-app
|
|
39
|
-
pnpm create zenbu-app . # interactive options, scaffolds into cwd
|
|
40
|
-
pnpm create zenbu-app --yes # all defaults, scaffolds into cwd
|
|
41
|
-
pnpm create zenbu-app my-app --yes # all defaults, scaffolds ./my-app
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Templates
|
|
45
|
-
|
|
46
|
-
The CLI ships full per-config copies of the project under `templates/<slug>/`
|
|
47
|
-
— there are no in-template conditionals. Today:
|
|
48
|
-
|
|
49
|
-
- `templates/tailwind/` — Tailwind CSS v4 wired up via `@tailwindcss/vite`.
|
|
50
|
-
- `templates/vanilla/` — plain CSS, no utility framework.
|
|
51
|
-
|
|
52
|
-
The selected slug is computed from the answered config options (Tailwind
|
|
53
|
-
contributes `tailwind`; the empty set falls back to `vanilla`).
|
|
54
|
-
|
|
55
|
-
## Package manager support
|
|
56
|
-
|
|
57
|
-
The detected invoking package manager is recorded in `zenbu.config.ts` and
|
|
58
|
-
used for the post-copy install. pnpm, npm, yarn, and bun are all supported,
|
|
59
|
-
but the bundled `.app` re-installs from the project's lockfile at first
|
|
60
|
-
launch — so currently the lockfile must be a pnpm one.
|
package/dist/index.mjs
CHANGED
|
@@ -138,6 +138,51 @@ function probeVersion(pm) {
|
|
|
138
138
|
const match = (res.stdout ?? "").trim().match(/\d+\.\d+\.\d+(?:[-+][\w.]+)?/);
|
|
139
139
|
return match ? match[0] : null;
|
|
140
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* `npx`, `npm create`, and `npm exec` all set the same `npm/<version>`
|
|
143
|
+
* user agent, so when `detectPackageManager` reports `npm` the user may
|
|
144
|
+
* actually prefer a different installed pm. Probe all four candidates,
|
|
145
|
+
* present only the ones present on the machine, and let the user pick
|
|
146
|
+
* (or pick automatically when only one is installed / `--yes`).
|
|
147
|
+
*/
|
|
148
|
+
async function resolveNpmAmbiguity(detected, opts) {
|
|
149
|
+
const candidates = [
|
|
150
|
+
"pnpm",
|
|
151
|
+
"npm",
|
|
152
|
+
"yarn",
|
|
153
|
+
"bun"
|
|
154
|
+
];
|
|
155
|
+
const installed = [];
|
|
156
|
+
for (const c of candidates) {
|
|
157
|
+
if (c === "npm") {
|
|
158
|
+
installed.push({
|
|
159
|
+
type: "npm",
|
|
160
|
+
version: detected.version,
|
|
161
|
+
fallback: false
|
|
162
|
+
});
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const v = probeVersion(c);
|
|
166
|
+
if (v) installed.push({
|
|
167
|
+
type: c,
|
|
168
|
+
version: v,
|
|
169
|
+
fallback: false
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (installed.length === 1) return installed[0];
|
|
173
|
+
const preferPnpm = installed.find((p) => p.type === "pnpm");
|
|
174
|
+
if (opts.yes) return preferPnpm ?? installed.find((p) => p.type === "npm");
|
|
175
|
+
const pick = await p.select({
|
|
176
|
+
message: "Which package manager should this app use?",
|
|
177
|
+
initialValue: preferPnpm?.type ?? "npm",
|
|
178
|
+
options: installed.map((p) => ({
|
|
179
|
+
value: p.type,
|
|
180
|
+
label: p.type === "pnpm" ? "pnpm (recommended)" : p.type
|
|
181
|
+
}))
|
|
182
|
+
});
|
|
183
|
+
if (p.isCancel(pick)) bail("Scaffolding cancelled.");
|
|
184
|
+
return installed.find((p) => p.type === pick);
|
|
185
|
+
}
|
|
141
186
|
function renderTemplate(value, ctx) {
|
|
142
187
|
return value.replace(/\{\{(\w+)\}\}/g, (full, key) => {
|
|
143
188
|
return Object.prototype.hasOwnProperty.call(ctx, key) ? ctx[key] : full;
|
|
@@ -407,7 +452,8 @@ async function main() {
|
|
|
407
452
|
templateDir = path.join(TEMPLATES_DIR, slug);
|
|
408
453
|
}
|
|
409
454
|
if (!fs.existsSync(templateDir)) bail(`No template found for configuration "${slug}".`);
|
|
410
|
-
|
|
455
|
+
let pm = detectPackageManager();
|
|
456
|
+
if (pm.type === "npm") pm = await resolveNpmAmbiguity(pm, { yes });
|
|
411
457
|
p.log.step(`Scaffolding Zenbu ${pluginMode ? "plugin" : "app"} in "${displayName}" (template: ${slug})`);
|
|
412
458
|
const ctx = pluginMode ? {
|
|
413
459
|
projectName: displayName,
|
package/package.json
CHANGED
|
@@ -27,7 +27,7 @@ function Home() {
|
|
|
27
27
|
className="bg-indigo-600 hover:bg-indigo-700 transition text-white font-semibold px-4 py-2 rounded text-sm"
|
|
28
28
|
onClick={async () => {
|
|
29
29
|
setCopied(false)
|
|
30
|
-
setCwd(await rpc.app.
|
|
30
|
+
setCwd(await rpc.app.cwd.get())
|
|
31
31
|
}}
|
|
32
32
|
>
|
|
33
33
|
Get cwd
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Service } from "@zenbujs/core/runtime"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Sample RPC service. Methods on the class are callable from the renderer
|
|
5
|
-
* via `useRpc()` — see `src/renderer/App.tsx`.
|
|
6
|
-
*/
|
|
7
|
-
export class Repo extends Service.create({ key: "repo" }) {
|
|
8
|
-
async getCwd() {
|
|
9
|
-
return process.cwd()
|
|
10
|
-
}
|
|
11
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Service } from "@zenbujs/core/runtime"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Sample RPC service. Methods on the class are callable from the renderer
|
|
5
|
-
* via `useRpc()` — see `src/renderer/App.tsx`.
|
|
6
|
-
*/
|
|
7
|
-
export class Repo extends Service.create({ key: "repo" }) {
|
|
8
|
-
async getCwd() {
|
|
9
|
-
return process.cwd()
|
|
10
|
-
}
|
|
11
|
-
}
|