create-kide-app 0.3.4 → 0.3.5

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.
Files changed (2) hide show
  1. package/index.js +35 -23
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import * as p from "@clack/prompts";
4
- import { execFileSync, execSync, spawn } from "node:child_process";
4
+ import { execSync, spawn } from "node:child_process";
5
5
  import {
6
6
  cpSync,
7
7
  existsSync,
@@ -31,6 +31,27 @@ const runAsync = (cmd, cwd) =>
31
31
  });
32
32
  });
33
33
 
34
+ // Argv-based variant: no shell, so untrusted values (like the project directory)
35
+ // are passed as single arguments and can never be reinterpreted as commands.
36
+ const runFileAsync = (file, args, cwd) =>
37
+ new Promise((resolve, reject) => {
38
+ const child = spawn(file, args, { cwd });
39
+ let stdout = "";
40
+ let stderr = "";
41
+ child.stdout.on("data", (d) => (stdout += d.toString()));
42
+ child.stderr.on("data", (d) => (stderr += d.toString()));
43
+ child.on("error", reject);
44
+ child.on("close", (code) => {
45
+ if (code === 0) resolve(stdout);
46
+ else {
47
+ const err = new Error(`Command failed: ${file} ${args.join(" ")}`);
48
+ err.stderr = stderr;
49
+ err.stdout = stdout;
50
+ reject(err);
51
+ }
52
+ });
53
+ });
54
+
34
55
  // --- Package manager detection ---
35
56
 
36
57
  const pm = {
@@ -97,13 +118,17 @@ const validateProjectName = (value) => {
97
118
 
98
119
  // Resolve the latest release tag (v-prefixed semver) so scaffolds pin to a
99
120
  // deliberate release instead of whatever HEAD happens to be. Returns null when
100
- // the repo has no tags (falls back to the default branch).
101
- const resolveLatestTag = () => {
121
+ // the repo has no tags (falls back to the default branch). Async so the
122
+ // "Downloading template" spinner keeps animating during the network call.
123
+ const resolveLatestTag = async () => {
102
124
  try {
103
- const output = execSync(
104
- `git ls-remote --tags --sort=-v:refname ${REPO} "v*"`,
105
- { stdio: "pipe" },
106
- ).toString();
125
+ const output = await runFileAsync("git", [
126
+ "ls-remote",
127
+ "--tags",
128
+ "--sort=-v:refname",
129
+ REPO,
130
+ "v*",
131
+ ]);
107
132
  for (const line of output.split("\n")) {
108
133
  const match = line.match(/refs\/tags\/(v[0-9][^^\s]*)$/);
109
134
  if (match) return match[1];
@@ -195,27 +220,14 @@ async function main() {
195
220
 
196
221
  s.start("Downloading template");
197
222
 
198
- const templateRef = resolveLatestTag();
223
+ const templateRef = await resolveLatestTag();
199
224
  let templateCommit = null;
200
225
 
201
226
  try {
202
227
  const branchArgs = templateRef ? ["--branch", templateRef] : [];
203
- // execFileSync, not execSync: no shell, so projectDir is passed as one argv entry
204
- // and can never be reinterpreted as a command regardless of what it contains.
205
- execFileSync(
206
- "git",
207
- ["clone", "--depth", "1", ...branchArgs, REPO, projectDir],
208
- {
209
- stdio: "pipe",
210
- },
211
- );
228
+ await runFileAsync("git", ["clone", "--depth", "1", ...branchArgs, REPO, projectDir]);
212
229
  try {
213
- templateCommit = execSync("git rev-parse HEAD", {
214
- cwd: projectDir,
215
- stdio: "pipe",
216
- })
217
- .toString()
218
- .trim();
230
+ templateCommit = (await runFileAsync("git", ["rev-parse", "HEAD"], projectDir)).trim();
219
231
  } catch {
220
232
  // best-effort — stamp without a commit hash
221
233
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kide-app",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Scaffold a new Kide CMS project",
5
5
  "author": "Matti Hernesniemi",
6
6
  "license": "MIT",