create-daloy 0.1.22 → 0.1.24

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.
@@ -3,10 +3,11 @@
3
3
  // Zero runtime dependencies; uses only Node built-ins.
4
4
 
5
5
  import { spawn } from "node:child_process";
6
- import { existsSync } from "node:fs";
6
+ import { existsSync, openSync } from "node:fs";
7
7
  import { mkdir, readdir, readFile, writeFile, copyFile, rm } from "node:fs/promises";
8
8
  import { createInterface } from "node:readline/promises";
9
9
  import { stdin as input, stdout as output } from "node:process";
10
+ import { ReadStream as TtyReadStream } from "node:tty";
10
11
  import path from "node:path";
11
12
  import { fileURLToPath } from "node:url";
12
13
 
@@ -44,10 +45,10 @@ const TEMPLATE_OPTIONS = [
44
45
  ];
45
46
 
46
47
  const PACKAGE_MANAGER_OPTIONS = [
47
- { value: "pnpm", title: "pnpm", description: "Recommended for DaloyJS projects" },
48
- { value: "npm", title: "npm", description: "Use the npm client you already have" },
49
- { value: "yarn", title: "Yarn", description: "Classic create workflow" },
50
- { value: "bun", title: "Bun", description: "Fast install and runtime tooling" },
48
+ { value: "pnpm", title: "pnpm", description: "Recommended default with the hardened pnpm workspace settings" },
49
+ { value: "npm", title: "npm", description: "Use the stock npm CLI with rewritten scripts and docs" },
50
+ { value: "yarn", title: "Yarn", description: "Yarn workflow with rewritten scripts and lockfile-friendly installs" },
51
+ { value: "bun", title: "Bun", description: "Bun package manager for fast installs; runtime templates stay Bun-native" },
51
52
  ];
52
53
 
53
54
  const TEMPLATES = TEMPLATE_OPTIONS.map((option) => option.value);
@@ -794,9 +795,43 @@ function runQuiet(cmd, args, cwd) {
794
795
  //
795
796
  // `ask`/`askYesNo` use readline for resilience (paste, history, multi-line
796
797
  // input). `askChoice` upgrades to raw-mode arrow-key navigation when stdin is
797
- // a TTY, with a numbered fallback used by the readline-driven tests.
798
+ // a TTY. When package-manager wrappers hide raw mode on process.stdin (pnpm
799
+ // does this on some terminals), we reopen the controlling TTY directly before
800
+ // falling back to the numbered prompt used by the readline-driven tests.
798
801
  // ----------------------------------------------------------------------------
799
802
 
803
+ function choiceInputMode({ stdinIsTTY, hasRawMode, platform }) {
804
+ if (stdinIsTTY && hasRawMode) return "stdin";
805
+ if (platform !== "win32") return "tty";
806
+ return "numbered";
807
+ }
808
+
809
+ function openChoiceInputStream() {
810
+ const mode = choiceInputMode({
811
+ stdinIsTTY: process.stdin.isTTY,
812
+ hasRawMode: typeof process.stdin.setRawMode === "function",
813
+ platform: process.platform,
814
+ });
815
+ if (mode === "stdin") {
816
+ return { stream: process.stdin, dispose: () => {} };
817
+ }
818
+ if (mode !== "tty") return null;
819
+ try {
820
+ const fd = openSync("/dev/tty", "r");
821
+ const stream = new TtyReadStream(fd);
822
+ if (!stream.isTTY || typeof stream.setRawMode !== "function") {
823
+ stream.destroy();
824
+ return null;
825
+ }
826
+ return {
827
+ stream,
828
+ dispose: () => stream.destroy(),
829
+ };
830
+ } catch {
831
+ return null;
832
+ }
833
+ }
834
+
800
835
  function printPromptHeader(question) {
801
836
  console.log(`${color(COLORS.cyan, SYMBOLS.stepActive)} ${color(COLORS.bold, question)}`);
802
837
  }
@@ -842,8 +877,9 @@ function optionDescription(option) {
842
877
  // Arrow-key powered choice prompt. Falls back to numbered input whenever raw
843
878
  // mode is unavailable (CI, piped stdin, integration tests).
844
879
  async function askChoice(rl, question, choices, defaultChoice) {
845
- const canRawMode = process.stdin.isTTY && typeof process.stdin.setRawMode === "function";
846
- if (!canRawMode) return askChoiceNumbered(rl, question, choices, defaultChoice);
880
+ const rawInputHandle = openChoiceInputStream();
881
+ if (!rawInputHandle) return askChoiceNumbered(rl, question, choices, defaultChoice);
882
+ const rawInput = rawInputHandle.stream;
847
883
 
848
884
  printPromptHeader(question);
849
885
  printRailLine(color(COLORS.dim, `Use \u2191 \u2193 to navigate, Enter to confirm, type a number to jump.`));
@@ -875,9 +911,9 @@ async function askChoice(rl, question, choices, defaultChoice) {
875
911
 
876
912
  // Pause readline so it doesn't fight us for stdin while we're in raw mode.
877
913
  rl.pause();
878
- process.stdin.setRawMode(true);
879
- process.stdin.resume();
880
- process.stdin.setEncoding("utf8");
914
+ rawInput.setRawMode(true);
915
+ rawInput.resume();
916
+ rawInput.setEncoding("utf8");
881
917
 
882
918
  // Initial render
883
919
  process.stdout.write(render(index) + "\n");
@@ -891,9 +927,10 @@ async function askChoice(rl, question, choices, defaultChoice) {
891
927
  process.stdout.write(render(newIndex) + "\n");
892
928
  }
893
929
  function cleanup() {
894
- process.stdin.removeListener("data", onData);
895
- process.stdin.setRawMode(false);
896
- process.stdin.pause();
930
+ rawInput.removeListener("data", onData);
931
+ rawInput.setRawMode(false);
932
+ rawInput.pause();
933
+ rawInputHandle.dispose();
897
934
  }
898
935
  function onData(chunk) {
899
936
  const data = chunk.toString();
@@ -934,7 +971,7 @@ async function askChoice(rl, question, choices, defaultChoice) {
934
971
  rerender(index);
935
972
  }
936
973
  }
937
- process.stdin.on("data", onData);
974
+ rawInput.on("data", onData);
938
975
  });
939
976
 
940
977
  // Replace the rendered list with a single confirmation line.
@@ -1272,4 +1309,8 @@ async function main() {
1272
1309
  }
1273
1310
  }
1274
1311
 
1275
- await main();
1312
+ if (process.env.DALOY_TEST_IMPORT !== "1") {
1313
+ await main();
1314
+ }
1315
+
1316
+ export { choiceInputMode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-daloy",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "Scaffold a new DaloyJS project. Run with `pnpm create daloy`, `npm create daloy@latest`, `yarn create daloy`, or `bun create daloy`.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -16,7 +16,7 @@
16
16
  "gen": "pnpm gen:openapi && pnpm gen:client"
17
17
  },
18
18
  "dependencies": {
19
- "@daloyjs/core": "^0.5.0",
19
+ "@daloyjs/core": "^0.7.5",
20
20
  "zod": "^4.4.3"
21
21
  },
22
22
  "devDependencies": {
@@ -10,7 +10,7 @@
10
10
  "test": "node --import tsx/esm --test tests/**/*.test.ts"
11
11
  },
12
12
  "dependencies": {
13
- "@daloyjs/core": "^0.5.0",
13
+ "@daloyjs/core": "^0.7.5",
14
14
  "zod": "^4.4.3"
15
15
  },
16
16
  "devDependencies": {
@@ -8,8 +8,8 @@
8
8
  "gen:openapi": "deno run --allow-net --allow-env --allow-read --allow-write scripts/dump-openapi.ts"
9
9
  },
10
10
  "imports": {
11
- "@daloyjs/core": "npm:@daloyjs/core@^0.5.0",
12
- "@daloyjs/core/": "npm:@daloyjs/core@^0.5.0/",
11
+ "@daloyjs/core": "npm:@daloyjs/core@^0.7.5",
12
+ "@daloyjs/core/": "npm:@daloyjs/core@^0.7.5/",
13
13
  "zod": "npm:zod@^4.4.3"
14
14
  },
15
15
  "compilerOptions": {
@@ -18,7 +18,7 @@
18
18
  "audit": "pnpm audit --prod"
19
19
  },
20
20
  "dependencies": {
21
- "@daloyjs/core": "^0.5.0",
21
+ "@daloyjs/core": "^0.7.5",
22
22
  "zod": "^4.4.3"
23
23
  },
24
24
  "devDependencies": {
@@ -10,7 +10,7 @@
10
10
  "test": "node --import tsx/esm --test tests/**/*.test.ts"
11
11
  },
12
12
  "dependencies": {
13
- "@daloyjs/core": "^0.5.0",
13
+ "@daloyjs/core": "^0.7.5",
14
14
  "zod": "^4.4.3"
15
15
  },
16
16
  "devDependencies": {