create-rv 0.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.
Files changed (82) hide show
  1. package/README.md +146 -0
  2. package/dist/cli.js +62 -0
  3. package/dist/cli.js.map +1 -0
  4. package/dist/copyDotfiles.js +30 -0
  5. package/dist/copyDotfiles.js.map +1 -0
  6. package/dist/git.js +14 -0
  7. package/dist/git.js.map +1 -0
  8. package/dist/index.js +37 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/installers/eslint.js +17 -0
  11. package/dist/installers/eslint.js.map +1 -0
  12. package/dist/installers/index.js +46 -0
  13. package/dist/installers/index.js.map +1 -0
  14. package/dist/installers/prettier.js +11 -0
  15. package/dist/installers/prettier.js.map +1 -0
  16. package/dist/installers/query.js +8 -0
  17. package/dist/installers/query.js.map +1 -0
  18. package/dist/installers/rhf.js +9 -0
  19. package/dist/installers/rhf.js.map +1 -0
  20. package/dist/installers/router-react-router.js +6 -0
  21. package/dist/installers/router-react-router.js.map +1 -0
  22. package/dist/installers/router-tanstack.js +7 -0
  23. package/dist/installers/router-tanstack.js.map +1 -0
  24. package/dist/installers/router.js +10 -0
  25. package/dist/installers/router.js.map +1 -0
  26. package/dist/installers/shadcn.js +25 -0
  27. package/dist/installers/shadcn.js.map +1 -0
  28. package/dist/installers/zod.js +8 -0
  29. package/dist/installers/zod.js.map +1 -0
  30. package/dist/installers/zustand.js +8 -0
  31. package/dist/installers/zustand.js.map +1 -0
  32. package/dist/log.js +25 -0
  33. package/dist/log.js.map +1 -0
  34. package/dist/options.js +28 -0
  35. package/dist/options.js.map +1 -0
  36. package/dist/pkgManager.js +34 -0
  37. package/dist/pkgManager.js.map +1 -0
  38. package/dist/prompts.js +85 -0
  39. package/dist/prompts.js.map +1 -0
  40. package/dist/scaffold.js +211 -0
  41. package/dist/scaffold.js.map +1 -0
  42. package/package.json +55 -0
  43. package/templates/base/README.md +60 -0
  44. package/templates/base/js/index.html +13 -0
  45. package/templates/base/js/jsconfig.json +16 -0
  46. package/templates/base/js/package.json +22 -0
  47. package/templates/base/js/src/App.jsx +10 -0
  48. package/templates/base/js/src/index.css +6 -0
  49. package/templates/base/js/src/main.jsx +10 -0
  50. package/templates/base/js/vite.config.js +13 -0
  51. package/templates/base/ts/index.html +13 -0
  52. package/templates/base/ts/package.json +26 -0
  53. package/templates/base/ts/src/App.tsx +10 -0
  54. package/templates/base/ts/src/index.css +6 -0
  55. package/templates/base/ts/src/main.tsx +10 -0
  56. package/templates/base/ts/src/vite-env.d.ts +1 -0
  57. package/templates/base/ts/tsconfig.json +27 -0
  58. package/templates/base/ts/tsconfig.node.json +12 -0
  59. package/templates/base/ts/vite.config.ts +13 -0
  60. package/templates/extras/eslint/.eslintignore +3 -0
  61. package/templates/extras/eslint/eslint.config.js +37 -0
  62. package/templates/extras/prettier/.prettierignore +7 -0
  63. package/templates/extras/prettier/.prettierrc +8 -0
  64. package/templates/extras/query/src/main.tsx +15 -0
  65. package/templates/extras/rhf/src/components/ExampleForm.tsx +40 -0
  66. package/templates/extras/router-react-router/src/App.tsx +24 -0
  67. package/templates/extras/router-react-router/src/main.tsx +13 -0
  68. package/templates/extras/router-react-router/src/pages/about.tsx +7 -0
  69. package/templates/extras/router-react-router/src/pages/home.tsx +7 -0
  70. package/templates/extras/router-tanstack/src/main.tsx +19 -0
  71. package/templates/extras/router-tanstack/src/routes/__root.tsx +16 -0
  72. package/templates/extras/router-tanstack/src/routes/about.tsx +13 -0
  73. package/templates/extras/router-tanstack/src/routes/index.tsx +13 -0
  74. package/templates/extras/router-tanstack/vite.config.ts +18 -0
  75. package/templates/extras/shadcn/components.json +19 -0
  76. package/templates/extras/shadcn/src/components/ui/button.tsx +45 -0
  77. package/templates/extras/shadcn/src/components/ui/card.tsx +34 -0
  78. package/templates/extras/shadcn/src/components/ui/input.tsx +19 -0
  79. package/templates/extras/shadcn/src/index.css +85 -0
  80. package/templates/extras/shadcn/src/lib/utils.ts +6 -0
  81. package/templates/extras/zod/src/lib/schemas.ts +8 -0
  82. package/templates/extras/zustand/src/lib/store.ts +15 -0
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # create-rv
2
+
3
+ A zero-config CLI that scaffolds a **Vite + React 19 + Tailwind v4** app with the
4
+ `rollout` stack pre-wired: router, state, data, forms, validation, shadcn/ui,
5
+ lint, and format. Choose **TypeScript or JavaScript** and one of three routers
6
+ interactively, or skip the prompts with flags.
7
+
8
+ ## what you get
9
+
10
+ - **Vite** + **React 19** + **TypeScript** (or JavaScript) with `@/*` path alias
11
+ - **Tailwind v4** wired via `@tailwindcss/vite` — no `tailwind.config.js`,
12
+ no `postcss.config.js`, just `@import "tailwindcss"` in `src/index.css`
13
+ - **Router** — pick one:
14
+ - `tanstack` — TanStack Router (file-based, type-safe, vite plugin, generates `routeTree.gen.ts`)
15
+ - `react-router` — React Router v8 (declarative: `BrowserRouter` + `Link`/`Route`/`Routes` imported from `react-router`)
16
+ - `none` — single-page shell
17
+ - **shadcn/ui** (primed) — `components.json`, `cn()` util, `Button`/`Card`/`Input` components, oklch theme tokens, `tsx` flag in `components.json` flips with language
18
+ - **TanStack Query** — `QueryClientProvider` wired for the chosen router
19
+ - **Zustand** — sample store at `src/lib/store.ts`
20
+ - **React Hook Form + Zod** — example form at `src/components/ExampleForm.tsx`
21
+ - **ESLint** — flat config, Vercel/TS style + import sort + tailwind
22
+ - **Prettier** — with `prettier-plugin-tailwindcss`
23
+ - **4 package managers** — `npm`, `pnpm`, `yarn`, `bun`
24
+ - **Optional** `git init` and dependency install
25
+
26
+ ## usage
27
+
28
+ ### interactive
29
+
30
+ ```bash
31
+ npx create-rv my-app
32
+ ```
33
+
34
+ You'll be prompted for project name, package manager, language, router, and
35
+ extras. Press Enter at the router prompt to accept the default
36
+ (**React Router v8**).
37
+
38
+ ### non-interactive (CI / scripts)
39
+
40
+ ```bash
41
+ npx create-rv my-app \
42
+ --pkg pnpm \
43
+ --lang ts \
44
+ --router react-router \
45
+ --with query,zustand,rhf,zod,eslint,prettier,shadcn \
46
+ --install \
47
+ --yes
48
+ ```
49
+
50
+ `--yes` accepts all defaults and skips prompts.
51
+
52
+ ## flags
53
+
54
+ | flag | values | default |
55
+ | --- | --- | --- |
56
+ | `--pkg` | `npm` \| `pnpm` \| `yarn` \| `bun` | `npm` |
57
+ | `--lang` | `ts` \| `js` | `ts` |
58
+ | `--router` | `tanstack` \| `react-router` \| `none` | `react-router` |
59
+ | `--with` | comma-separated extras | all extras |
60
+ | `--no-git` | skip `git init` | git inits by default |
61
+ | `--install` | run install after scaffold | off |
62
+ | `-y`, `--yes` | accept all defaults, no prompts | off |
63
+
64
+ Available extras: `query`, `zustand`, `rhf`, `zod`, `eslint`, `prettier`, `shadcn`.
65
+
66
+ ## after scaffold
67
+
68
+ ```bash
69
+ cd my-app
70
+ pnpm dev
71
+ ```
72
+
73
+ Add more shadcn components:
74
+
75
+ ```bash
76
+ pnpm dlx shadcn@latest add dialog
77
+ ```
78
+
79
+ Lint and format (if included):
80
+
81
+ ```bash
82
+ pnpm lint
83
+ pnpm format
84
+ ```
85
+
86
+ ## how it works
87
+
88
+ 1. **Parse** CLI args via `commander`.
89
+ 2. **Prompt** for any missing values via `@clack/prompts` (skipped if every
90
+ choice was provided as a flag or `--yes` is set).
91
+ 3. **Copy** `templates/base/<lang>/` (Vite + React skeleton) into the
92
+ destination, then dotfiles from `templates/base/`.
93
+ 4. **Overlay** the chosen router from `templates/extras/router-*/` and
94
+ **install** its package via `src/installers/router-*.ts`.
95
+ 5. **Install** each selected extra by copying its template overlay and adding
96
+ deps + scripts to `package.json`.
97
+ 6. **Rewrite** to JS if `--lang js`: rename `.ts`→`.js`, `.tsx`→`.jsx`, drop
98
+ `.d.ts` and `typescript` deps, strip `tsc` from `build`.
99
+ 7. **Optionally** `git init` and run install.
100
+ 8. **Render** the generated project's `README.md` from a `__STACK_LIST__` /
101
+ `__SCRIPTS_EXTRA__` template.
102
+
103
+ Templates live in `templates/base/{ts,js}/` and `templates/extras/*/`. Each
104
+ extra has an installer in `src/installers/` that copies its overlay and mutates
105
+ `package.json`.
106
+
107
+ ## router notes
108
+
109
+ - **TanStack Router** is file-based. Routes live in `src/routes/`; the vite
110
+ plugin generates `routeTree.gen.ts` on dev/build. `<RouterProvider>` wraps
111
+ the app in `main.tsx`.
112
+ - **React Router v8** uses the declarative API: `BrowserRouter` wraps `<App />`
113
+ in `main.tsx`, and `App.tsx` uses `<Routes>` / `<Route>` / `<Link>`.
114
+ Everything is imported from `react-router` (in v8 the declarative API is in
115
+ the root package; `react-router-dom` is removed).
116
+
117
+ ## project layout
118
+
119
+ ```
120
+ src/
121
+ cli.ts # commander setup + flag parsing
122
+ prompts.ts # clack interactive prompts
123
+ scaffold.ts # main scaffold orchestration
124
+ options.ts # types + valid value lists
125
+ copyDotfiles.ts # walker that copies dotfiles (cpSync skips them on node 25)
126
+ installers/ # one file per extra; mutates pkg + copies overlay
127
+ templates/
128
+ base/{ts,js}/ # Vite+React skeleton
129
+ extras/<name>/ # overlay files copied into the project
130
+ scripts/
131
+ smoke.mjs # scaffolds 4 variants into /tmp and asserts files
132
+ ```
133
+
134
+ ## dev
135
+
136
+ ```bash
137
+ pnpm install
138
+ pnpm build # tsc -> dist/
139
+ node dist/index.js /tmp/demo --pkg npm --with shadcn --no-git --yes
140
+ node scripts/smoke.mjs # scaffolds 4 variants, asserts files
141
+ ```
142
+
143
+ Smoke covers 4 variants: `ts × tanstack`, `js × tanstack`,
144
+ `ts × react-router + shadcn`, `js × react-router + shadcn`, plus a
145
+ regression check that react-router `main.tsx` wraps `<App />` in
146
+ `<BrowserRouter>` imported from `react-router`.
package/dist/cli.js ADDED
@@ -0,0 +1,62 @@
1
+ import { Command } from "commander";
2
+ import { ALL_EXTRAS, LANG_CHOICES, ROUTER_CHOICES, isExtraKey, isLang, isRouterChoice, VALID_PKG, } from "./options.js";
3
+ export function buildProgram() {
4
+ const program = new Command();
5
+ program
6
+ .name("create-rv")
7
+ .description("Scaffold a Vite+React+TS app with the rollout stack.")
8
+ .version("0.1.0")
9
+ .argument("[project-name]", "name of the project directory")
10
+ .option("--pkg <pm>", `package manager: ${VALID_PKG.join("|")}`)
11
+ .option("--router <choice>", `router: ${ROUTER_CHOICES.join("|")} (default: react-router)`)
12
+ .option("--lang <choice>", `language: ${LANG_CHOICES.join("|")} (default: ts)`)
13
+ .option("--with <list>", `comma-separated extras. available: ${ALL_EXTRAS.join(",")}`)
14
+ .option("--no-git", "skip git init")
15
+ .option("--install", "run install after scaffold", false)
16
+ .option("-y, --yes", "accept defaults, no prompts", false)
17
+ .allowExcessArguments(false);
18
+ return program;
19
+ }
20
+ export function parseCli(argv) {
21
+ const program = buildProgram();
22
+ const out = {
23
+ extras: [],
24
+ git: true,
25
+ install: false,
26
+ yes: false,
27
+ };
28
+ program.parse(argv);
29
+ const projectName = program.args[0];
30
+ if (typeof projectName === "string")
31
+ out.projectName = projectName;
32
+ const opts = program.opts();
33
+ if (opts.pkg) {
34
+ if (!VALID_PKG.includes(opts.pkg)) {
35
+ throw new Error(`invalid --pkg, must be one of ${VALID_PKG.join("|")}`);
36
+ }
37
+ out.pkgManager = opts.pkg;
38
+ }
39
+ if (opts.router) {
40
+ if (!isRouterChoice(opts.router)) {
41
+ throw new Error(`invalid --router, must be one of ${ROUTER_CHOICES.join("|")}`);
42
+ }
43
+ out.router = opts.router;
44
+ }
45
+ if (opts.lang) {
46
+ if (!isLang(opts.lang)) {
47
+ throw new Error(`invalid --lang, must be one of ${LANG_CHOICES.join("|")}`);
48
+ }
49
+ out.lang = opts.lang;
50
+ }
51
+ if (opts.with) {
52
+ out.extras = opts.with
53
+ .split(",")
54
+ .map((s) => s.trim())
55
+ .filter((s) => isExtraKey(s));
56
+ }
57
+ out.git = opts.git !== false;
58
+ out.install = opts.install === true;
59
+ out.yes = opts.yes === true;
60
+ return out;
61
+ }
62
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { copyFileSync, existsSync, mkdirSync, readdirSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ /**
4
+ * Recursively copy dotfiles (e.g. `.gitignore`, `.prettierrc`, `.eslintignore`)
5
+ * from `srcRoot` to `destRoot`, preserving relative paths. node 25's cpSync
6
+ * silently skips dotfiles, so we walk manually. Overwrites by default.
7
+ */
8
+ export function copyDotfiles(srcRoot, destRoot, overwrite = true) {
9
+ if (!existsSync(srcRoot))
10
+ return;
11
+ const entries = readdirSync(srcRoot, { withFileTypes: true });
12
+ for (const e of entries) {
13
+ if (e.name === "node_modules" || e.name === ".git" || e.name === "dist")
14
+ continue;
15
+ const srcPath = join(srcRoot, e.name);
16
+ if (e.isDirectory()) {
17
+ copyDotfiles(srcPath, destRoot, overwrite);
18
+ continue;
19
+ }
20
+ if (!e.name.startsWith("."))
21
+ continue;
22
+ const rel = srcPath.startsWith(srcRoot + "/") ? srcPath.slice(srcRoot.length + 1) : srcPath;
23
+ const destPath = join(destRoot, rel);
24
+ if (existsSync(destPath) && !overwrite)
25
+ continue;
26
+ mkdirSync(dirname(destPath), { recursive: true });
27
+ copyFileSync(srcPath, destPath);
28
+ }
29
+ }
30
+ //# sourceMappingURL=copyDotfiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyDotfiles.js","sourceRoot":"","sources":["../src/copyDotfiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,QAAgB,EAAE,SAAS,GAAG,IAAI;IAC9E,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO;IACjC,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAClF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACpB,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;YAC3C,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACtC,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAC5F,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACrC,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS;YAAE,SAAS;QACjD,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;AACH,CAAC"}
package/dist/git.js ADDED
@@ -0,0 +1,14 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { log } from "./log.js";
3
+ export function initializeGit(projectDir) {
4
+ try {
5
+ execFileSync("git", ["init", "-q"], { cwd: projectDir });
6
+ execFileSync("git", ["add", "."], { cwd: projectDir });
7
+ execFileSync("git", ["commit", "-q", "-m", "chore: initial scaffold from create-rv"], { cwd: projectDir });
8
+ log.ok("git initialized with initial commit");
9
+ }
10
+ catch (err) {
11
+ log.warn(`git init skipped: ${err.message}`);
12
+ }
13
+ }
14
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,UAAU,aAAa,CAAC,UAAkB;IAC9C,IAAI,CAAC;QACH,YAAY,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;QACzD,YAAY,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;QACvD,YAAY,CACV,KAAK,EACL,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,wCAAwC,CAAC,EAChE,EAAE,GAAG,EAAE,UAAU,EAAE,CACpB,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,qCAAqC,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,qBAAsB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ import { parseCli } from "./cli.js";
3
+ import { runInteractive } from "./prompts.js";
4
+ import { scaffold } from "./scaffold.js";
5
+ import { parseNameAndPath, ALL_EXTRAS, } from "./options.js";
6
+ import { log } from "./log.js";
7
+ async function main() {
8
+ const cli = parseCli(process.argv);
9
+ const defaults = {
10
+ projectName: cli.projectName ?? "my-app",
11
+ pkgManager: (cli.pkgManager ?? "npm"),
12
+ lang: (cli.lang ?? "ts"),
13
+ router: (cli.router ?? "react-router"),
14
+ extras: cli.extras.length > 0 ? cli.extras : ALL_EXTRAS.slice(),
15
+ git: cli.git,
16
+ install: cli.install,
17
+ };
18
+ const result = cli.yes || cli.pkgManager || cli.router || cli.lang || cli.extras.length > 0
19
+ ? { ...defaults, extras: defaults.extras, install: cli.install, git: cli.git }
20
+ : await runInteractive(cli.projectName, defaults);
21
+ const [scopedAppName, dirName] = parseNameAndPath(result.projectName);
22
+ await scaffold({
23
+ projectName: dirName,
24
+ scopedAppName,
25
+ pkgManager: result.pkgManager,
26
+ git: result.git,
27
+ install: result.install,
28
+ extras: result.extras,
29
+ router: result.router,
30
+ lang: result.lang,
31
+ });
32
+ }
33
+ main().catch((err) => {
34
+ log.err(err.message);
35
+ process.exit(1);
36
+ });
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACL,gBAAgB,EAGhB,UAAU,GAGX,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,KAAK,UAAU,IAAI;IACjB,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG;QACf,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,QAAQ;QACxC,UAAU,EAAE,CAAC,GAAG,CAAC,UAAU,IAAI,KAAK,CAAe;QACnD,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAS;QAChC,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,cAAc,CAAiB;QACtD,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAE,UAAkC,CAAC,KAAK,EAAE;QACxF,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,OAAO,EAAE,GAAG,CAAC,OAAO;KACrB,CAAC;IAEF,MAAM,MAAM,GACV,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAC1E,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE;QAC9E,CAAC,CAAC,MAAM,cAAc,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAEtD,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,gBAAgB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAEtE,MAAM,QAAQ,CAAC;QACb,WAAW,EAAE,OAAO;QACpB,aAAa;QACb,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI;KAClB,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,GAAG,CAAC,GAAG,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { copyOverlay } from "./index.js";
2
+ const install = (ctx) => {
3
+ copyOverlay("eslint", ctx.projectDir);
4
+ ctx.pkg.devDependencies["eslint"] = "latest";
5
+ ctx.pkg.devDependencies["@typescript-eslint/parser"] = "latest";
6
+ ctx.pkg.devDependencies["@typescript-eslint/eslint-plugin"] = "latest";
7
+ ctx.pkg.devDependencies["eslint-plugin-react"] = "latest";
8
+ ctx.pkg.devDependencies["eslint-plugin-react-hooks"] = "latest";
9
+ ctx.pkg.devDependencies["eslint-plugin-import"] = "latest";
10
+ ctx.pkg.devDependencies["eslint-plugin-simple-import-sort"] = "latest";
11
+ ctx.pkg.devDependencies["eslint-plugin-tailwindcss"] = "latest";
12
+ ctx.pkg.scripts["lint"] = "eslint .";
13
+ ctx.pkg.scripts["lint:fix"] = "eslint . --fix";
14
+ ctx.log("eslint wired (flat config, vercel style + import sort + tailwind)");
15
+ };
16
+ export { install };
17
+ //# sourceMappingURL=eslint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint.js","sourceRoot":"","sources":["../../src/installers/eslint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAEzD,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAC7C,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,2BAA2B,CAAC,GAAG,QAAQ,CAAC;IAChE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,kCAAkC,CAAC,GAAG,QAAQ,CAAC;IACvE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,qBAAqB,CAAC,GAAG,QAAQ,CAAC;IAC1D,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,2BAA2B,CAAC,GAAG,QAAQ,CAAC;IAChE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,sBAAsB,CAAC,GAAG,QAAQ,CAAC;IAC3D,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,kCAAkC,CAAC,GAAG,QAAQ,CAAC;IACvE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,2BAA2B,CAAC,GAAG,QAAQ,CAAC;IAChE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC;IACrC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,gBAAgB,CAAC;IAC/C,GAAG,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;AAC/E,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { cpSync, existsSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { copyDotfiles } from "../copyDotfiles.js";
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ function findTemplatesDir(start) {
7
+ let cur = start;
8
+ for (let i = 0; i < 8; i++) {
9
+ const candidate = resolve(cur, "templates");
10
+ if (existsSync(candidate))
11
+ return candidate;
12
+ const parent = dirname(cur);
13
+ if (parent === cur)
14
+ break;
15
+ cur = parent;
16
+ }
17
+ throw new Error("could not locate templates/ directory");
18
+ }
19
+ const TEMPLATES_DIR = findTemplatesDir(__dirname);
20
+ const INSTALLER_FILES = {
21
+ query: "query.js",
22
+ zustand: "zustand.js",
23
+ rhf: "rhf.js",
24
+ zod: "zod.js",
25
+ eslint: "eslint.js",
26
+ prettier: "prettier.js",
27
+ shadcn: "shadcn.js",
28
+ };
29
+ const cache = new Map();
30
+ export async function getInstaller(key) {
31
+ if (cache.has(key))
32
+ return cache.get(key);
33
+ const file = INSTALLER_FILES[key];
34
+ const mod = (await import(`./${file}`));
35
+ cache.set(key, mod.install);
36
+ return mod.install;
37
+ }
38
+ export function copyOverlay(key, dest) {
39
+ const overlay = join(TEMPLATES_DIR, "extras", key);
40
+ if (!existsSync(overlay))
41
+ return false;
42
+ cpSync(overlay, dest, { recursive: true, force: true });
43
+ copyDotfiles(overlay, dest);
44
+ return true;
45
+ }
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/installers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,SAAS,gBAAgB,CAAC,KAAa;IACrC,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAC5C,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QAC1B,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;AAC3D,CAAC;AACD,MAAM,aAAa,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAiBlD,MAAM,eAAe,GAA6B;IAChD,KAAK,EAAE,UAAU;IACjB,OAAO,EAAE,YAAY;IACrB,GAAG,EAAE,QAAQ;IACb,GAAG,EAAE,QAAQ;IACb,MAAM,EAAE,WAAW;IACnB,QAAQ,EAAE,aAAa;IACvB,MAAM,EAAE,WAAW;CACpB,CAAC;AAEF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAa;IAC9C,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;IAC3C,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAA2B,CAAC;IAClE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5B,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,IAAY;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { copyOverlay } from "./index.js";
2
+ const install = (ctx) => {
3
+ copyOverlay("prettier", ctx.projectDir);
4
+ ctx.pkg.devDependencies["prettier"] = "latest";
5
+ ctx.pkg.devDependencies["prettier-plugin-tailwindcss"] = "latest";
6
+ ctx.pkg.scripts["format"] = "prettier --write .";
7
+ ctx.pkg.scripts["format:check"] = "prettier --check .";
8
+ ctx.log("prettier wired");
9
+ };
10
+ export { install };
11
+ //# sourceMappingURL=prettier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prettier.js","sourceRoot":"","sources":["../../src/installers/prettier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAEzD,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,WAAW,CAAC,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC;IAC/C,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,6BAA6B,CAAC,GAAG,QAAQ,CAAC;IAClE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,oBAAoB,CAAC;IACjD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,oBAAoB,CAAC;IACvD,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { copyOverlay } from "./index.js";
2
+ const install = (ctx) => {
3
+ copyOverlay("query", ctx.projectDir);
4
+ ctx.pkg.dependencies["@tanstack/react-query"] = "latest";
5
+ ctx.log("tanstack query wired (QueryClientProvider)");
6
+ };
7
+ export { install };
8
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/installers/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAEzD,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,uBAAuB,CAAC,GAAG,QAAQ,CAAC;IACzD,GAAG,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;AACxD,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { copyOverlay } from "./index.js";
2
+ const install = (ctx) => {
3
+ copyOverlay("rhf", ctx.projectDir);
4
+ ctx.pkg.dependencies["react-hook-form"] = "latest";
5
+ ctx.pkg.dependencies["@hookform/resolvers"] = "latest";
6
+ ctx.log("react-hook-form wired (example form in src/components/ExampleForm.tsx)");
7
+ };
8
+ export { install };
9
+ //# sourceMappingURL=rhf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rhf.js","sourceRoot":"","sources":["../../src/installers/rhf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAEzD,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,iBAAiB,CAAC,GAAG,QAAQ,CAAC;IACnD,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,qBAAqB,CAAC,GAAG,QAAQ,CAAC;IACvD,GAAG,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC;AACpF,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,6 @@
1
+ const install = (ctx) => {
2
+ ctx.pkg.dependencies["react-router"] = "^8";
3
+ ctx.log("react-router v8 wired (declarative: BrowserRouter + Link/Route/Routes from react-router)");
4
+ };
5
+ export { install };
6
+ //# sourceMappingURL=router-react-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router-react-router.js","sourceRoot":"","sources":["../../src/installers/router-react-router.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;IAC5C,GAAG,CAAC,GAAG,CAAC,0FAA0F,CAAC,CAAC;AACtG,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ const install = (ctx) => {
2
+ ctx.pkg.dependencies["@tanstack/react-router"] = "latest";
3
+ ctx.pkg.devDependencies["@tanstack/router-plugin"] = "latest";
4
+ ctx.log("tanstack router wired (file-based routes, vite plugin, routeTree.gen)");
5
+ };
6
+ export { install };
7
+ //# sourceMappingURL=router-tanstack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router-tanstack.js","sourceRoot":"","sources":["../../src/installers/router-tanstack.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,wBAAwB,CAAC,GAAG,QAAQ,CAAC;IAC1D,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,yBAAyB,CAAC,GAAG,QAAQ,CAAC;IAC9D,GAAG,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;AACnF,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { copyOverlay } from "./index.js";
2
+ const install = (ctx) => {
3
+ copyOverlay("router", ctx.projectDir);
4
+ ctx.pkg.dependencies["@tanstack/react-router"] = "latest";
5
+ ctx.pkg.devDependencies["@tanstack/router-plugin"] = "latest";
6
+ ctx.pkg.scripts["dev"] = "vite";
7
+ ctx.log("tanstack router wired (file-based routes, vite plugin)");
8
+ };
9
+ export { install };
10
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/installers/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAEzD,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,wBAAwB,CAAC,GAAG,QAAQ,CAAC;IAC1D,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,yBAAyB,CAAC,GAAG,QAAQ,CAAC;IAC9D,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;IAChC,GAAG,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;AACpE,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { copyOverlay } from "./index.js";
4
+ const install = (ctx) => {
5
+ copyOverlay("shadcn", ctx.projectDir);
6
+ ctx.pkg.dependencies["class-variance-authority"] = "latest";
7
+ ctx.pkg.dependencies["clsx"] = "latest";
8
+ ctx.pkg.dependencies["tailwind-merge"] = "latest";
9
+ ctx.pkg.dependencies["lucide-react"] = "latest";
10
+ ctx.pkg.dependencies["@radix-ui/react-slot"] = "latest";
11
+ ctx.pkg.devDependencies["tailwindcss-animate"] = "latest";
12
+ // flip components.json tsx flag based on lang
13
+ const cfgPath = join(ctx.projectDir, "components.json");
14
+ try {
15
+ const cfg = JSON.parse(readFileSync(cfgPath, "utf8"));
16
+ cfg.tsx = ctx.lang === "ts";
17
+ writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n");
18
+ }
19
+ catch {
20
+ // components.json absent — skip
21
+ }
22
+ ctx.log(`shadcn/ui primed (tailwind v4, tsx=${ctx.lang === "ts"}, cn() + Button/Card/Input)`);
23
+ };
24
+ export { install };
25
+ //# sourceMappingURL=shadcn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shadcn.js","sourceRoot":"","sources":["../../src/installers/shadcn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAEzD,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,0BAA0B,CAAC,GAAG,QAAQ,CAAC;IAC5D,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC;IACxC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC,GAAG,QAAQ,CAAC;IAClD,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,cAAc,CAAC,GAAG,QAAQ,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,sBAAsB,CAAC,GAAG,QAAQ,CAAC;IACxD,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,qBAAqB,CAAC,GAAG,QAAQ,CAAC;IAE1D,8CAA8C;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAsB,CAAC;QAC3E,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC;QAC5B,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IACD,GAAG,CAAC,GAAG,CAAC,sCAAsC,GAAG,CAAC,IAAI,KAAK,IAAI,6BAA6B,CAAC,CAAC;AAChG,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { copyOverlay } from "./index.js";
2
+ const install = (ctx) => {
3
+ copyOverlay("zod", ctx.projectDir);
4
+ ctx.pkg.dependencies["zod"] = "latest";
5
+ ctx.log("zod wired (schemas in src/lib/schemas.ts)");
6
+ };
7
+ export { install };
8
+ //# sourceMappingURL=zod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod.js","sourceRoot":"","sources":["../../src/installers/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAEzD,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;IACvC,GAAG,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { copyOverlay } from "./index.js";
2
+ const install = (ctx) => {
3
+ copyOverlay("zustand", ctx.projectDir);
4
+ ctx.pkg.dependencies["zustand"] = "latest";
5
+ ctx.log("zustand wired (sample store in src/lib/store.ts)");
6
+ };
7
+ export { install };
8
+ //# sourceMappingURL=zustand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zustand.js","sourceRoot":"","sources":["../../src/installers/zustand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAEzD,MAAM,OAAO,GAAc,CAAC,GAAG,EAAE,EAAE;IACjC,WAAW,CAAC,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACvC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;IAC3C,GAAG,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;AAC9D,CAAC,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
package/dist/log.js ADDED
@@ -0,0 +1,25 @@
1
+ import pc from "picocolors";
2
+ const isTTY = process.stdout.isTTY;
3
+ const dim = (s) => (isTTY ? pc.dim(s) : s);
4
+ const green = (s) => (isTTY ? pc.green(s) : s);
5
+ const red = (s) => (isTTY ? pc.red(s) : s);
6
+ const cyan = (s) => (isTTY ? pc.cyan(s) : s);
7
+ const bold = (s) => (isTTY ? pc.bold(s) : s);
8
+ export const log = {
9
+ info(msg) {
10
+ console.log(`${cyan("info")} ${msg}`);
11
+ },
12
+ ok(msg) {
13
+ console.log(`${green("done")} ${msg}`);
14
+ },
15
+ warn(msg) {
16
+ console.warn(`${dim("warn")} ${msg}`);
17
+ },
18
+ err(msg) {
19
+ console.error(`${red("fail")} ${msg}`);
20
+ },
21
+ step(label, msg) {
22
+ console.log(`${bold(label)} ${msg}`);
23
+ },
24
+ };
25
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;AACnC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3D,MAAM,KAAK,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3D,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7D,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,IAAI,CAAC,GAAW;QACd,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,EAAE,CAAC,GAAW;QACZ,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,CAAC,GAAW;QACd,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,GAAG,CAAC,GAAW;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,CAAC,KAAa,EAAE,GAAW;QAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACvC,CAAC;CACF,CAAC"}
@@ -0,0 +1,28 @@
1
+ export const ALL_EXTRAS = [
2
+ "query",
3
+ "zustand",
4
+ "rhf",
5
+ "zod",
6
+ "eslint",
7
+ "prettier",
8
+ "shadcn",
9
+ ];
10
+ export const VALID_PKG = ["npm", "pnpm", "yarn", "bun"];
11
+ export const ROUTER_CHOICES = ["tanstack", "react-router", "none"];
12
+ export const LANG_CHOICES = ["ts", "js"];
13
+ export function parseNameAndPath(input) {
14
+ const parts = input.split("/");
15
+ const dir = parts[parts.length - 1] ?? "my-app";
16
+ const scoped = parts.length > 1 ? `@${parts[0]}/${dir}` : dir;
17
+ return [scoped, dir];
18
+ }
19
+ export function isExtraKey(s) {
20
+ return ALL_EXTRAS.includes(s);
21
+ }
22
+ export function isRouterChoice(s) {
23
+ return ROUTER_CHOICES.includes(s);
24
+ }
25
+ export function isLang(s) {
26
+ return LANG_CHOICES.includes(s);
27
+ }
28
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO;IACP,SAAS;IACT,KAAK;IACL,KAAK;IACL,QAAQ;IACR,UAAU;IACV,QAAQ;CACA,CAAC;AAKX,MAAM,CAAC,MAAM,SAAS,GAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAEtE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,cAAc,EAAE,MAAM,CAAU,CAAC;AAG5E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,IAAI,CAAU,CAAC;AAclD,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC;IAChD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAC9D,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAQ,UAAgC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,OAAQ,cAAoC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,CAAS;IAC9B,OAAQ,YAAkC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { execFileSync } from "node:child_process";
2
+ export function getPkgManagerVersion(pm) {
3
+ try {
4
+ const out = execFileSync(pm, ["-v"], { encoding: "utf8" });
5
+ return out.trim();
6
+ }
7
+ catch {
8
+ return "latest";
9
+ }
10
+ }
11
+ export function pkgManagerField(pm) {
12
+ if (pm === "bun")
13
+ return undefined; // bun ignores the field
14
+ return `${pm}@${getPkgManagerVersion(pm)}`;
15
+ }
16
+ export function installCmd(pm) {
17
+ if (pm === "npm")
18
+ return ["npm", ["install"]];
19
+ if (pm === "pnpm")
20
+ return ["pnpm", ["install"]];
21
+ if (pm === "yarn")
22
+ return ["yarn", ["install"]];
23
+ return ["bun", ["install"]];
24
+ }
25
+ export function addCmd(pm, name, dev = false) {
26
+ if (pm === "npm")
27
+ return ["npm", [dev ? "install" : "install", "--save-dev", name]];
28
+ if (pm === "pnpm")
29
+ return ["pnpm", ["add", dev ? "-D" : "", name].filter(Boolean)];
30
+ if (pm === "yarn")
31
+ return ["yarn", [dev ? "add" : "add", name]];
32
+ return ["bun", ["add", name]];
33
+ }
34
+ //# sourceMappingURL=pkgManager.js.map