@korajs/cli 0.0.0-canary-20261008174129

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 (310) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -0
  3. package/dist/bin.cjs +9465 -0
  4. package/dist/bin.cjs.map +1 -0
  5. package/dist/bin.js +3150 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/chunk-5NI2FEQL.js +92 -0
  8. package/dist/chunk-5NI2FEQL.js.map +1 -0
  9. package/dist/chunk-6C4BHSRA.js +82 -0
  10. package/dist/chunk-6C4BHSRA.js.map +1 -0
  11. package/dist/chunk-7Y4J2GXP.js +796 -0
  12. package/dist/chunk-7Y4J2GXP.js.map +1 -0
  13. package/dist/chunk-BURFQVMV.js +719 -0
  14. package/dist/chunk-BURFQVMV.js.map +1 -0
  15. package/dist/chunk-TVIRMDER.js +2569 -0
  16. package/dist/chunk-TVIRMDER.js.map +1 -0
  17. package/dist/create.cjs +1368 -0
  18. package/dist/create.cjs.map +1 -0
  19. package/dist/create.js +11 -0
  20. package/dist/create.js.map +1 -0
  21. package/dist/index.cjs +3489 -0
  22. package/dist/index.cjs.map +1 -0
  23. package/dist/index.d.cts +772 -0
  24. package/dist/index.d.ts +772 -0
  25. package/dist/index.js +129 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/lab-manager-KUDII6BT.js +280 -0
  28. package/dist/lab-manager-KUDII6BT.js.map +1 -0
  29. package/dist/schema-loader-GGHECMTM.js +9 -0
  30. package/dist/schema-loader-GGHECMTM.js.map +1 -0
  31. package/dist/spectator-manager-FTH2NFSE.js +145 -0
  32. package/dist/spectator-manager-FTH2NFSE.js.map +1 -0
  33. package/dist/studio-server-XLGZNGG5.js +1747 -0
  34. package/dist/studio-server-XLGZNGG5.js.map +1 -0
  35. package/dist/vite.cjs +351 -0
  36. package/dist/vite.cjs.map +1 -0
  37. package/dist/vite.d.cts +161 -0
  38. package/dist/vite.d.ts +161 -0
  39. package/dist/vite.js +321 -0
  40. package/dist/vite.js.map +1 -0
  41. package/package.json +79 -0
  42. package/templates/react-basic/.env.example +3 -0
  43. package/templates/react-basic/AGENTS.md +87 -0
  44. package/templates/react-basic/README.md.hbs +62 -0
  45. package/templates/react-basic/index.html.hbs +12 -0
  46. package/templates/react-basic/kora.config.ts +13 -0
  47. package/templates/react-basic/package.json.hbs +35 -0
  48. package/templates/react-basic/src/App.tsx +132 -0
  49. package/templates/react-basic/src/index.css +287 -0
  50. package/templates/react-basic/src/kora-worker.ts +9 -0
  51. package/templates/react-basic/src/main.tsx +24 -0
  52. package/templates/react-basic/src/modules/todos/todo.mutations.ts +25 -0
  53. package/templates/react-basic/src/modules/todos/todo.queries.ts +5 -0
  54. package/templates/react-basic/src/modules/todos/todo.schema.ts +10 -0
  55. package/templates/react-basic/src/modules/todos/useTodos.ts +31 -0
  56. package/templates/react-basic/src/schema.ts +9 -0
  57. package/templates/react-basic/src/vite-env.d.ts +18 -0
  58. package/templates/react-basic/tsconfig.json.hbs +14 -0
  59. package/templates/react-basic/vite.config.ts +88 -0
  60. package/templates/react-sync/.env.example +25 -0
  61. package/templates/react-sync/AGENTS.md +87 -0
  62. package/templates/react-sync/README.md.hbs +106 -0
  63. package/templates/react-sync/index.html.hbs +12 -0
  64. package/templates/react-sync/kora.config.ts +17 -0
  65. package/templates/react-sync/package.json.hbs +44 -0
  66. package/templates/react-sync/server.ts +141 -0
  67. package/templates/react-sync/src/App.tsx +160 -0
  68. package/templates/react-sync/src/auth.ts +25 -0
  69. package/templates/react-sync/src/index.css +350 -0
  70. package/templates/react-sync/src/kora-worker.ts +9 -0
  71. package/templates/react-sync/src/main.tsx +52 -0
  72. package/templates/react-sync/src/modules/todos/todo.mutations.ts +25 -0
  73. package/templates/react-sync/src/modules/todos/todo.queries.ts +5 -0
  74. package/templates/react-sync/src/modules/todos/todo.schema.ts +10 -0
  75. package/templates/react-sync/src/modules/todos/useTodos.ts +31 -0
  76. package/templates/react-sync/src/schema.ts +9 -0
  77. package/templates/react-sync/src/vite-env.d.ts +19 -0
  78. package/templates/react-sync/tsconfig.json.hbs +14 -0
  79. package/templates/react-sync/vite.config.ts +105 -0
  80. package/templates/react-tailwind/.env.example +3 -0
  81. package/templates/react-tailwind/AGENTS.md +87 -0
  82. package/templates/react-tailwind/README.md.hbs +62 -0
  83. package/templates/react-tailwind/index.html.hbs +12 -0
  84. package/templates/react-tailwind/kora.config.ts +13 -0
  85. package/templates/react-tailwind/package.json.hbs +38 -0
  86. package/templates/react-tailwind/src/App.tsx +201 -0
  87. package/templates/react-tailwind/src/index.css +7 -0
  88. package/templates/react-tailwind/src/kora-worker.ts +9 -0
  89. package/templates/react-tailwind/src/main.tsx +31 -0
  90. package/templates/react-tailwind/src/modules/todos/todo.mutations.ts +25 -0
  91. package/templates/react-tailwind/src/modules/todos/todo.queries.ts +5 -0
  92. package/templates/react-tailwind/src/modules/todos/todo.schema.ts +10 -0
  93. package/templates/react-tailwind/src/modules/todos/useTodos.ts +31 -0
  94. package/templates/react-tailwind/src/schema.ts +9 -0
  95. package/templates/react-tailwind/src/vite-env.d.ts +18 -0
  96. package/templates/react-tailwind/tsconfig.json.hbs +14 -0
  97. package/templates/react-tailwind/vite.config.ts +95 -0
  98. package/templates/react-tailwind-sync/.env.example +25 -0
  99. package/templates/react-tailwind-sync/AGENTS.md +89 -0
  100. package/templates/react-tailwind-sync/README.md.hbs +106 -0
  101. package/templates/react-tailwind-sync/index.html.hbs +12 -0
  102. package/templates/react-tailwind-sync/kora.config.ts +17 -0
  103. package/templates/react-tailwind-sync/package.json.hbs +47 -0
  104. package/templates/react-tailwind-sync/server.ts +141 -0
  105. package/templates/react-tailwind-sync/src/App.tsx +293 -0
  106. package/templates/react-tailwind-sync/src/auth.ts +25 -0
  107. package/templates/react-tailwind-sync/src/index.css +7 -0
  108. package/templates/react-tailwind-sync/src/kora-worker.ts +9 -0
  109. package/templates/react-tailwind-sync/src/kora.ts +32 -0
  110. package/templates/react-tailwind-sync/src/main.tsx +44 -0
  111. package/templates/react-tailwind-sync/src/modules/todos/todo.mutations.ts +21 -0
  112. package/templates/react-tailwind-sync/src/modules/todos/todo.queries.ts +5 -0
  113. package/templates/react-tailwind-sync/src/modules/todos/todo.schema.ts +10 -0
  114. package/templates/react-tailwind-sync/src/modules/todos/useTodos.ts +31 -0
  115. package/templates/react-tailwind-sync/src/schema.ts +9 -0
  116. package/templates/react-tailwind-sync/src/vite-env.d.ts +19 -0
  117. package/templates/react-tailwind-sync/tsconfig.json.hbs +14 -0
  118. package/templates/react-tailwind-sync/vite.config.ts +112 -0
  119. package/templates/svelte-basic/.env.example +3 -0
  120. package/templates/svelte-basic/AGENTS.md +76 -0
  121. package/templates/svelte-basic/README.md.hbs +62 -0
  122. package/templates/svelte-basic/index.html.hbs +12 -0
  123. package/templates/svelte-basic/kora.config.ts +12 -0
  124. package/templates/svelte-basic/package.json.hbs +33 -0
  125. package/templates/svelte-basic/src/App.svelte +128 -0
  126. package/templates/svelte-basic/src/Root.svelte +14 -0
  127. package/templates/svelte-basic/src/index.css +287 -0
  128. package/templates/svelte-basic/src/kora-worker.ts +9 -0
  129. package/templates/svelte-basic/src/main.ts +16 -0
  130. package/templates/svelte-basic/src/modules/todos/todo.mutations.ts +25 -0
  131. package/templates/svelte-basic/src/modules/todos/todo.queries.ts +5 -0
  132. package/templates/svelte-basic/src/modules/todos/todo.schema.ts +10 -0
  133. package/templates/svelte-basic/src/modules/todos/useTodos.ts +25 -0
  134. package/templates/svelte-basic/src/schema.ts +9 -0
  135. package/templates/svelte-basic/src/vite-env.d.ts +12 -0
  136. package/templates/svelte-basic/svelte.config.js +5 -0
  137. package/templates/svelte-basic/tsconfig.json.hbs +14 -0
  138. package/templates/svelte-basic/vite.config.ts +57 -0
  139. package/templates/svelte-sync/.env.example +25 -0
  140. package/templates/svelte-sync/AGENTS.md +76 -0
  141. package/templates/svelte-sync/README.md.hbs +106 -0
  142. package/templates/svelte-sync/index.html.hbs +12 -0
  143. package/templates/svelte-sync/kora.config.ts +17 -0
  144. package/templates/svelte-sync/package.json.hbs +43 -0
  145. package/templates/svelte-sync/server.ts +141 -0
  146. package/templates/svelte-sync/src/App.svelte +151 -0
  147. package/templates/svelte-sync/src/Root.svelte +22 -0
  148. package/templates/svelte-sync/src/auth.ts +25 -0
  149. package/templates/svelte-sync/src/index.css +339 -0
  150. package/templates/svelte-sync/src/kora-worker.ts +9 -0
  151. package/templates/svelte-sync/src/main.ts +32 -0
  152. package/templates/svelte-sync/src/modules/todos/todo.mutations.ts +25 -0
  153. package/templates/svelte-sync/src/modules/todos/todo.queries.ts +5 -0
  154. package/templates/svelte-sync/src/modules/todos/todo.schema.ts +10 -0
  155. package/templates/svelte-sync/src/modules/todos/useTodos.ts +25 -0
  156. package/templates/svelte-sync/src/schema.ts +9 -0
  157. package/templates/svelte-sync/src/vite-env.d.ts +22 -0
  158. package/templates/svelte-sync/svelte.config.js +5 -0
  159. package/templates/svelte-sync/tsconfig.json.hbs +14 -0
  160. package/templates/svelte-sync/vite.config.ts +91 -0
  161. package/templates/svelte-tailwind/AGENTS.md +76 -0
  162. package/templates/svelte-tailwind/README.md.hbs +62 -0
  163. package/templates/svelte-tailwind/index.html.hbs +12 -0
  164. package/templates/svelte-tailwind/kora.config.ts +12 -0
  165. package/templates/svelte-tailwind/package.json.hbs +36 -0
  166. package/templates/svelte-tailwind/src/App.svelte +76 -0
  167. package/templates/svelte-tailwind/src/Root.svelte +14 -0
  168. package/templates/svelte-tailwind/src/index.css +7 -0
  169. package/templates/svelte-tailwind/src/kora-worker.ts +9 -0
  170. package/templates/svelte-tailwind/src/main.ts +16 -0
  171. package/templates/svelte-tailwind/src/modules/todos/todo.mutations.ts +25 -0
  172. package/templates/svelte-tailwind/src/modules/todos/todo.queries.ts +5 -0
  173. package/templates/svelte-tailwind/src/modules/todos/todo.schema.ts +10 -0
  174. package/templates/svelte-tailwind/src/modules/todos/useTodos.ts +25 -0
  175. package/templates/svelte-tailwind/src/schema.ts +9 -0
  176. package/templates/svelte-tailwind/src/vite-env.d.ts +12 -0
  177. package/templates/svelte-tailwind/svelte.config.js +5 -0
  178. package/templates/svelte-tailwind/tsconfig.json.hbs +14 -0
  179. package/templates/svelte-tailwind/vite.config.ts +64 -0
  180. package/templates/svelte-tailwind-sync/.env.example +25 -0
  181. package/templates/svelte-tailwind-sync/AGENTS.md +76 -0
  182. package/templates/svelte-tailwind-sync/README.md.hbs +106 -0
  183. package/templates/svelte-tailwind-sync/index.html.hbs +12 -0
  184. package/templates/svelte-tailwind-sync/kora.config.ts +17 -0
  185. package/templates/svelte-tailwind-sync/package.json.hbs +46 -0
  186. package/templates/svelte-tailwind-sync/server.ts +141 -0
  187. package/templates/svelte-tailwind-sync/src/App.svelte +193 -0
  188. package/templates/svelte-tailwind-sync/src/Root.svelte +26 -0
  189. package/templates/svelte-tailwind-sync/src/auth.ts +25 -0
  190. package/templates/svelte-tailwind-sync/src/index.css +7 -0
  191. package/templates/svelte-tailwind-sync/src/kora-worker.ts +9 -0
  192. package/templates/svelte-tailwind-sync/src/main.ts +32 -0
  193. package/templates/svelte-tailwind-sync/src/modules/todos/todo.mutations.ts +25 -0
  194. package/templates/svelte-tailwind-sync/src/modules/todos/todo.queries.ts +5 -0
  195. package/templates/svelte-tailwind-sync/src/modules/todos/todo.schema.ts +10 -0
  196. package/templates/svelte-tailwind-sync/src/modules/todos/useTodos.ts +25 -0
  197. package/templates/svelte-tailwind-sync/src/schema.ts +9 -0
  198. package/templates/svelte-tailwind-sync/src/vite-env.d.ts +22 -0
  199. package/templates/svelte-tailwind-sync/svelte.config.js +5 -0
  200. package/templates/svelte-tailwind-sync/tsconfig.json.hbs +14 -0
  201. package/templates/svelte-tailwind-sync/vite.config.ts +98 -0
  202. package/templates/tauri-react/.env.example +27 -0
  203. package/templates/tauri-react/.github/workflows/release-desktop.yml +107 -0
  204. package/templates/tauri-react/AGENTS.md +91 -0
  205. package/templates/tauri-react/README.md.hbs +183 -0
  206. package/templates/tauri-react/dev.ts +37 -0
  207. package/templates/tauri-react/index.html.hbs +16 -0
  208. package/templates/tauri-react/kora.config.ts +17 -0
  209. package/templates/tauri-react/package.json.hbs +46 -0
  210. package/templates/tauri-react/server.ts +148 -0
  211. package/templates/tauri-react/src/App.tsx +803 -0
  212. package/templates/tauri-react/src/AppShell.tsx +158 -0
  213. package/templates/tauri-react/src/SetupScreen.tsx +288 -0
  214. package/templates/tauri-react/src/auth.ts +45 -0
  215. package/templates/tauri-react/src/main.tsx +9 -0
  216. package/templates/tauri-react/src/modules/todos/todo.mutations.ts +25 -0
  217. package/templates/tauri-react/src/modules/todos/todo.queries.ts +5 -0
  218. package/templates/tauri-react/src/modules/todos/todo.schema.ts +10 -0
  219. package/templates/tauri-react/src/modules/todos/useTodos.ts +31 -0
  220. package/templates/tauri-react/src/schema.ts +9 -0
  221. package/templates/tauri-react/src/sync-config.ts +103 -0
  222. package/templates/tauri-react/src/updater.ts +38 -0
  223. package/templates/tauri-react/src/vite-env.d.ts +19 -0
  224. package/templates/tauri-react/src-tauri/Cargo.toml +19 -0
  225. package/templates/tauri-react/src-tauri/build.rs +3 -0
  226. package/templates/tauri-react/src-tauri/capabilities/default.json +12 -0
  227. package/templates/tauri-react/src-tauri/icons/128x128.png +0 -0
  228. package/templates/tauri-react/src-tauri/icons/128x128@2x.png +0 -0
  229. package/templates/tauri-react/src-tauri/icons/32x32.png +0 -0
  230. package/templates/tauri-react/src-tauri/icons/icon.icns +0 -0
  231. package/templates/tauri-react/src-tauri/icons/icon.ico +0 -0
  232. package/templates/tauri-react/src-tauri/src/lib.rs +8 -0
  233. package/templates/tauri-react/src-tauri/src/main.rs +6 -0
  234. package/templates/tauri-react/src-tauri/tauri.conf.json +44 -0
  235. package/templates/tauri-react/tsconfig.json.hbs +14 -0
  236. package/templates/tauri-react/vite.config.ts +15 -0
  237. package/templates/vue-basic/AGENTS.md +84 -0
  238. package/templates/vue-basic/README.md.hbs +62 -0
  239. package/templates/vue-basic/index.html.hbs +12 -0
  240. package/templates/vue-basic/kora.config.ts +12 -0
  241. package/templates/vue-basic/package.json.hbs +32 -0
  242. package/templates/vue-basic/src/App.vue +117 -0
  243. package/templates/vue-basic/src/index.css +287 -0
  244. package/templates/vue-basic/src/kora-worker.ts +9 -0
  245. package/templates/vue-basic/src/main.ts +20 -0
  246. package/templates/vue-basic/src/modules/todos/todo.mutations.ts +25 -0
  247. package/templates/vue-basic/src/modules/todos/todo.queries.ts +5 -0
  248. package/templates/vue-basic/src/modules/todos/todo.schema.ts +10 -0
  249. package/templates/vue-basic/src/modules/todos/useTodos.ts +32 -0
  250. package/templates/vue-basic/src/schema.ts +9 -0
  251. package/templates/vue-basic/src/vite-env.d.ts +17 -0
  252. package/templates/vue-basic/tsconfig.json.hbs +15 -0
  253. package/templates/vue-basic/vite.config.ts +74 -0
  254. package/templates/vue-sync/.env.example +25 -0
  255. package/templates/vue-sync/AGENTS.md +84 -0
  256. package/templates/vue-sync/README.md.hbs +106 -0
  257. package/templates/vue-sync/index.html.hbs +12 -0
  258. package/templates/vue-sync/kora.config.ts +17 -0
  259. package/templates/vue-sync/package.json.hbs +42 -0
  260. package/templates/vue-sync/server.ts +141 -0
  261. package/templates/vue-sync/src/App.vue +135 -0
  262. package/templates/vue-sync/src/auth.ts +25 -0
  263. package/templates/vue-sync/src/index.css +339 -0
  264. package/templates/vue-sync/src/kora-worker.ts +9 -0
  265. package/templates/vue-sync/src/main.ts +47 -0
  266. package/templates/vue-sync/src/modules/todos/todo.mutations.ts +25 -0
  267. package/templates/vue-sync/src/modules/todos/todo.queries.ts +5 -0
  268. package/templates/vue-sync/src/modules/todos/todo.schema.ts +10 -0
  269. package/templates/vue-sync/src/modules/todos/useTodos.ts +32 -0
  270. package/templates/vue-sync/src/schema.ts +9 -0
  271. package/templates/vue-sync/src/vite-env.d.ts +27 -0
  272. package/templates/vue-sync/tsconfig.json.hbs +15 -0
  273. package/templates/vue-sync/vite.config.ts +91 -0
  274. package/templates/vue-tailwind/AGENTS.md +84 -0
  275. package/templates/vue-tailwind/README.md.hbs +62 -0
  276. package/templates/vue-tailwind/index.html.hbs +12 -0
  277. package/templates/vue-tailwind/kora.config.ts +12 -0
  278. package/templates/vue-tailwind/package.json.hbs +35 -0
  279. package/templates/vue-tailwind/src/App.vue +135 -0
  280. package/templates/vue-tailwind/src/index.css +7 -0
  281. package/templates/vue-tailwind/src/kora-worker.ts +9 -0
  282. package/templates/vue-tailwind/src/main.ts +31 -0
  283. package/templates/vue-tailwind/src/modules/todos/todo.mutations.ts +25 -0
  284. package/templates/vue-tailwind/src/modules/todos/todo.queries.ts +5 -0
  285. package/templates/vue-tailwind/src/modules/todos/todo.schema.ts +10 -0
  286. package/templates/vue-tailwind/src/modules/todos/useTodos.ts +32 -0
  287. package/templates/vue-tailwind/src/schema.ts +9 -0
  288. package/templates/vue-tailwind/src/vite-env.d.ts +17 -0
  289. package/templates/vue-tailwind/tsconfig.json.hbs +15 -0
  290. package/templates/vue-tailwind/vite.config.ts +75 -0
  291. package/templates/vue-tailwind-sync/.env.example +25 -0
  292. package/templates/vue-tailwind-sync/AGENTS.md +84 -0
  293. package/templates/vue-tailwind-sync/README.md.hbs +106 -0
  294. package/templates/vue-tailwind-sync/index.html.hbs +12 -0
  295. package/templates/vue-tailwind-sync/kora.config.ts +17 -0
  296. package/templates/vue-tailwind-sync/package.json.hbs +45 -0
  297. package/templates/vue-tailwind-sync/server.ts +141 -0
  298. package/templates/vue-tailwind-sync/src/App.vue +245 -0
  299. package/templates/vue-tailwind-sync/src/auth.ts +25 -0
  300. package/templates/vue-tailwind-sync/src/index.css +7 -0
  301. package/templates/vue-tailwind-sync/src/kora-worker.ts +9 -0
  302. package/templates/vue-tailwind-sync/src/main.ts +56 -0
  303. package/templates/vue-tailwind-sync/src/modules/todos/todo.mutations.ts +25 -0
  304. package/templates/vue-tailwind-sync/src/modules/todos/todo.queries.ts +5 -0
  305. package/templates/vue-tailwind-sync/src/modules/todos/todo.schema.ts +10 -0
  306. package/templates/vue-tailwind-sync/src/modules/todos/useTodos.ts +32 -0
  307. package/templates/vue-tailwind-sync/src/schema.ts +9 -0
  308. package/templates/vue-tailwind-sync/src/vite-env.d.ts +27 -0
  309. package/templates/vue-tailwind-sync/tsconfig.json.hbs +15 -0
  310. package/templates/vue-tailwind-sync/vite.config.ts +92 -0
@@ -0,0 +1,1368 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/create.ts
26
+ var import_citty2 = require("citty");
27
+
28
+ // src/commands/create/create-command.ts
29
+ var import_node_child_process2 = require("child_process");
30
+ var import_node_fs2 = require("fs");
31
+ var import_node_path6 = require("path");
32
+ var import_node_url2 = require("url");
33
+ var import_citty = require("citty");
34
+
35
+ // src/errors.ts
36
+ var import_core = require("@korajs/core");
37
+ var ProjectExistsError = class extends import_core.KoraError {
38
+ constructor(directory) {
39
+ super(
40
+ `Directory "${directory}" already exists. Choose a different name or remove the existing directory.`,
41
+ "PROJECT_EXISTS",
42
+ { directory }
43
+ );
44
+ this.directory = directory;
45
+ this.name = "ProjectExistsError";
46
+ }
47
+ directory;
48
+ };
49
+
50
+ // src/prompts/preferences.ts
51
+ var import_conf = __toESM(require("conf"), 1);
52
+ var DEFAULT_PREFERENCES = {
53
+ platform: "web",
54
+ framework: "react",
55
+ tailwind: true,
56
+ sync: true,
57
+ db: "sqlite",
58
+ dbProvider: "none",
59
+ auth: "none",
60
+ packageManager: "pnpm"
61
+ };
62
+ var PREFERENCES_KEY = "create.defaults";
63
+ var PreferenceStore = class {
64
+ store;
65
+ constructor() {
66
+ this.store = new import_conf.default({
67
+ projectName: "korajs-cli"
68
+ });
69
+ }
70
+ getCreatePreferences() {
71
+ return this.store.get(PREFERENCES_KEY) ?? null;
72
+ }
73
+ saveCreatePreferences(preferences) {
74
+ this.store.set(PREFERENCES_KEY, preferences);
75
+ }
76
+ clearCreatePreferences() {
77
+ this.store.delete(PREFERENCES_KEY);
78
+ }
79
+ };
80
+ function getCreatePreferencesOrDefault(store) {
81
+ return store.getCreatePreferences() ?? DEFAULT_PREFERENCES;
82
+ }
83
+ function getDefaultCreatePreferences() {
84
+ return { ...DEFAULT_PREFERENCES };
85
+ }
86
+
87
+ // src/prompts/prompt-client.ts
88
+ var import_prompts = require("@clack/prompts");
89
+
90
+ // src/utils/prompt.ts
91
+ var import_node_readline = require("readline");
92
+ function promptText(message, defaultValue, options) {
93
+ return new Promise((resolve5) => {
94
+ const rl = createReadline(options);
95
+ const suffix = defaultValue !== void 0 ? ` (${defaultValue})` : "";
96
+ rl.question(` ? ${message}${suffix}: `, (answer) => {
97
+ rl.close();
98
+ const trimmed = answer.trim();
99
+ resolve5(trimmed || defaultValue || "");
100
+ });
101
+ });
102
+ }
103
+ function promptSelect(message, choices, options) {
104
+ return new Promise((resolve5) => {
105
+ const rl = createReadline(options);
106
+ const out = options?.output ?? process.stdout;
107
+ out.write(` ? ${message}
108
+ `);
109
+ for (let i = 0; i < choices.length; i++) {
110
+ const choice = choices[i];
111
+ if (choice) {
112
+ out.write(` ${i + 1}) ${choice.label}
113
+ `);
114
+ }
115
+ }
116
+ const ask = () => {
117
+ rl.question(" > ", (answer) => {
118
+ const index = Number.parseInt(answer.trim(), 10) - 1;
119
+ const selected = choices[index];
120
+ if (selected) {
121
+ rl.close();
122
+ resolve5(selected.value);
123
+ } else {
124
+ out.write(` Please enter a number between 1 and ${choices.length}
125
+ `);
126
+ ask();
127
+ }
128
+ });
129
+ };
130
+ ask();
131
+ });
132
+ }
133
+ function promptConfirm(message, defaultValue = false, options) {
134
+ return new Promise((resolve5) => {
135
+ const rl = createReadline(options);
136
+ const suffix = defaultValue ? "Y/n" : "y/N";
137
+ const ask = () => {
138
+ rl.question(` ? ${message} (${suffix}): `, (answer) => {
139
+ const normalized = answer.trim().toLowerCase();
140
+ if (normalized.length === 0) {
141
+ rl.close();
142
+ resolve5(defaultValue);
143
+ return;
144
+ }
145
+ if (normalized === "y" || normalized === "yes") {
146
+ rl.close();
147
+ resolve5(true);
148
+ return;
149
+ }
150
+ if (normalized === "n" || normalized === "no") {
151
+ rl.close();
152
+ resolve5(false);
153
+ return;
154
+ }
155
+ ;
156
+ (options?.output ?? process.stdout).write(" Please answer with y or n\n");
157
+ ask();
158
+ });
159
+ };
160
+ ask();
161
+ });
162
+ }
163
+ function createReadline(options) {
164
+ return (0, import_node_readline.createInterface)({
165
+ input: options?.input ?? process.stdin,
166
+ output: options?.output ?? process.stdout
167
+ });
168
+ }
169
+
170
+ // src/prompts/prompt-client.ts
171
+ var PromptCancelledError = class extends Error {
172
+ constructor(message = "Prompt cancelled by user") {
173
+ super(message);
174
+ this.name = "PromptCancelledError";
175
+ }
176
+ };
177
+ var ReadlinePromptClient = class {
178
+ async text(message, defaultValue) {
179
+ return promptText(message, defaultValue);
180
+ }
181
+ async select(message, options) {
182
+ return promptSelect(
183
+ message,
184
+ options.filter((option) => option.disabled !== true).map((option) => ({ label: option.label, value: option.value }))
185
+ );
186
+ }
187
+ async confirm(message, defaultValue = false) {
188
+ return promptConfirm(message, defaultValue);
189
+ }
190
+ intro(message) {
191
+ void message;
192
+ }
193
+ outro(message) {
194
+ void message;
195
+ }
196
+ };
197
+ function createPromptClient() {
198
+ const canUseInteractiveClack = typeof process !== "undefined" && process.stdin.isTTY && process.stdout.isTTY;
199
+ if (canUseInteractiveClack) {
200
+ return new ClackPromptClient();
201
+ }
202
+ return new ReadlinePromptClient();
203
+ }
204
+ var ClackPromptClient = class {
205
+ async text(message, defaultValue) {
206
+ const result = await (0, import_prompts.text)({
207
+ message,
208
+ placeholder: defaultValue,
209
+ defaultValue
210
+ });
211
+ if ((0, import_prompts.isCancel)(result)) {
212
+ (0, import_prompts.cancel)("Operation cancelled.");
213
+ throw new PromptCancelledError();
214
+ }
215
+ const value = result.trim();
216
+ if (value.length > 0) return value;
217
+ return defaultValue ?? "";
218
+ }
219
+ async select(message, options) {
220
+ const mappedOptions = options.map((option) => ({
221
+ label: option.label,
222
+ value: option.value,
223
+ hint: option.hint,
224
+ disabled: option.disabled
225
+ }));
226
+ const result = await (0, import_prompts.select)({
227
+ message,
228
+ options: mappedOptions
229
+ });
230
+ if ((0, import_prompts.isCancel)(result)) {
231
+ (0, import_prompts.cancel)("Operation cancelled.");
232
+ throw new PromptCancelledError();
233
+ }
234
+ return result;
235
+ }
236
+ async confirm(message, defaultValue = false) {
237
+ const result = await (0, import_prompts.confirm)({
238
+ message,
239
+ initialValue: defaultValue
240
+ });
241
+ if ((0, import_prompts.isCancel)(result)) {
242
+ (0, import_prompts.cancel)("Operation cancelled.");
243
+ throw new PromptCancelledError();
244
+ }
245
+ return result;
246
+ }
247
+ intro(message) {
248
+ (0, import_prompts.intro)(message);
249
+ }
250
+ outro(message) {
251
+ (0, import_prompts.outro)(message);
252
+ }
253
+ };
254
+
255
+ // src/types.ts
256
+ var PACKAGE_MANAGERS = ["pnpm", "npm", "yarn", "bun"];
257
+ var TEMPLATES = [
258
+ "react-tailwind-sync",
259
+ "react-tailwind",
260
+ "react-sync",
261
+ "react-basic",
262
+ "vue-sync",
263
+ "vue-basic",
264
+ "vue-tailwind-sync",
265
+ "vue-tailwind",
266
+ "svelte-sync",
267
+ "svelte-basic",
268
+ "svelte-tailwind-sync",
269
+ "svelte-tailwind",
270
+ "tauri-react"
271
+ ];
272
+
273
+ // src/utils/fs-helpers.ts
274
+ var import_promises = require("fs/promises");
275
+ var import_node_path = require("path");
276
+ async function directoryExists(path) {
277
+ try {
278
+ await (0, import_promises.access)(path);
279
+ return true;
280
+ } catch {
281
+ return false;
282
+ }
283
+ }
284
+
285
+ // src/utils/logger.ts
286
+ var RESET = "\x1B[0m";
287
+ var BOLD = "\x1B[1m";
288
+ var DIM = "\x1B[2m";
289
+ var GREEN = "\x1B[32m";
290
+ var YELLOW = "\x1B[33m";
291
+ var RED = "\x1B[31m";
292
+ var CYAN = "\x1B[36m";
293
+ function createLogger(options) {
294
+ const colorDisabled = options?.noColor === true || process.env.NO_COLOR !== void 0 || !process.stdout.isTTY;
295
+ function color(code, text) {
296
+ return colorDisabled ? text : `${code}${text}${RESET}`;
297
+ }
298
+ return {
299
+ info(message) {
300
+ console.log(color(CYAN, message));
301
+ },
302
+ success(message) {
303
+ console.log(color(GREEN, ` \u2713 ${message}`));
304
+ },
305
+ warn(message) {
306
+ console.warn(color(YELLOW, ` \u26A0 ${message}`));
307
+ },
308
+ error(message) {
309
+ console.error(color(RED, ` \u2717 ${message}`));
310
+ },
311
+ step(message) {
312
+ console.log(color(DIM, ` ${message}`));
313
+ },
314
+ blank() {
315
+ console.log();
316
+ },
317
+ banner() {
318
+ console.log();
319
+ console.log(
320
+ color(BOLD + CYAN, " Kora.js") + color(DIM, ", the offline-first application framework")
321
+ );
322
+ console.log();
323
+ }
324
+ };
325
+ }
326
+
327
+ // src/utils/package-manager.ts
328
+ var import_node_child_process = require("child_process");
329
+ function detectPackageManager() {
330
+ const userAgent = process.env.npm_config_user_agent;
331
+ if (!userAgent) return "npm";
332
+ if (userAgent.startsWith("pnpm/")) return "pnpm";
333
+ if (userAgent.startsWith("yarn/")) return "yarn";
334
+ if (userAgent.startsWith("bun/")) return "bun";
335
+ return "npm";
336
+ }
337
+ function getInstallCommand(pm) {
338
+ return pm === "yarn" ? "yarn" : `${pm} install`;
339
+ }
340
+ function getRunDevCommand(pm) {
341
+ if (pm === "npm") return "npm run dev";
342
+ return `${pm} dev`;
343
+ }
344
+
345
+ // src/commands/create/environment-detection.ts
346
+ var import_promises2 = require("fs/promises");
347
+ var import_node_path2 = require("path");
348
+ function detectEditorFromEnvironment(env = process.env) {
349
+ const termProgram = String(env.TERM_PROGRAM ?? "").toLowerCase();
350
+ const editorValue = `${String(env.EDITOR ?? "")} ${String(env.VISUAL ?? "")}`.toLowerCase();
351
+ if (termProgram.includes("cursor") || env.CURSOR_TRACE_ID !== void 0 || env.CURSOR_SESSION_ID !== void 0 || editorValue.includes("cursor")) {
352
+ return { editor: "cursor", source: "env" };
353
+ }
354
+ if (termProgram.includes("windsurf") || env.WINDSURF_SESSION_ID !== void 0 || editorValue.includes("windsurf")) {
355
+ return { editor: "windsurf", source: "env" };
356
+ }
357
+ if (termProgram.includes("vscode") || env.VSCODE_GIT_IPC_HANDLE !== void 0 || env.VSCODE_IPC_HOOK !== void 0 || env.VSCODE_PID !== void 0 || editorValue.includes("code")) {
358
+ return { editor: "vscode", source: "env" };
359
+ }
360
+ if (termProgram.includes("zed") || env.ZED_TERM !== void 0 || editorValue.includes("zed")) {
361
+ return { editor: "zed", source: "env" };
362
+ }
363
+ return { editor: "unknown", source: "none" };
364
+ }
365
+ async function detectGitContext(startDir) {
366
+ const root = await findNearestAncestorWithEntry(startDir, ".git");
367
+ return {
368
+ hasRepository: root !== null,
369
+ repositoryRoot: root
370
+ };
371
+ }
372
+ async function detectMonorepoContext(startDir) {
373
+ let current = (0, import_node_path2.resolve)(startDir);
374
+ for (; ; ) {
375
+ if (await fileExists((0, import_node_path2.join)(current, "pnpm-workspace.yaml"))) {
376
+ return { isMonorepo: true, root: current, kind: "pnpm-workspace" };
377
+ }
378
+ if (await fileExists((0, import_node_path2.join)(current, "turbo.json"))) {
379
+ return { isMonorepo: true, root: current, kind: "turborepo" };
380
+ }
381
+ const packageJsonPath = (0, import_node_path2.join)(current, "package.json");
382
+ if (await fileExists(packageJsonPath)) {
383
+ try {
384
+ const packageJsonRaw = await (0, import_promises2.readFile)(packageJsonPath, "utf-8");
385
+ const parsed = JSON.parse(packageJsonRaw);
386
+ if (Array.isArray(parsed.workspaces) || isNpmWorkspaceObject(parsed.workspaces)) {
387
+ return { isMonorepo: true, root: current, kind: "npm-workspaces" };
388
+ }
389
+ } catch {
390
+ }
391
+ }
392
+ const parent = (0, import_node_path2.dirname)(current);
393
+ if (parent === current) {
394
+ return { isMonorepo: false, root: null, kind: "none" };
395
+ }
396
+ current = parent;
397
+ }
398
+ }
399
+ async function applyEditorWorkspacePreset(params) {
400
+ const { targetDir, editor } = params;
401
+ if (editor !== "vscode" && editor !== "cursor" && editor !== "windsurf") {
402
+ return { applied: false, filePath: null };
403
+ }
404
+ const vscodeDir = (0, import_node_path2.join)(targetDir, ".vscode");
405
+ const extensionsPath = (0, import_node_path2.join)(vscodeDir, "extensions.json");
406
+ await (0, import_promises2.mkdir)(vscodeDir, { recursive: true });
407
+ const recommendations = ["korajs.kora-devtools"];
408
+ const existing = await readJsonObject(extensionsPath);
409
+ const existingRecommendations = Array.isArray(existing?.recommendations) ? existing.recommendations.filter((item) => typeof item === "string") : [];
410
+ const mergedRecommendations = dedupeStrings([...existingRecommendations, ...recommendations]);
411
+ const next = {
412
+ recommendations: mergedRecommendations
413
+ };
414
+ await (0, import_promises2.writeFile)(extensionsPath, `${JSON.stringify(next, null, 2)}
415
+ `, "utf-8");
416
+ return { applied: true, filePath: extensionsPath };
417
+ }
418
+ function resolveMonorepoTargetDirectory(monorepoRoot, projectName) {
419
+ return (0, import_node_path2.join)(monorepoRoot, "packages", projectName);
420
+ }
421
+ function dedupeStrings(values) {
422
+ return Array.from(new Set(values));
423
+ }
424
+ async function readJsonObject(path) {
425
+ try {
426
+ const content = await (0, import_promises2.readFile)(path, "utf-8");
427
+ const parsed = JSON.parse(content);
428
+ if (typeof parsed === "object" && parsed !== null) {
429
+ return parsed;
430
+ }
431
+ return null;
432
+ } catch {
433
+ return null;
434
+ }
435
+ }
436
+ function isNpmWorkspaceObject(value) {
437
+ if (typeof value !== "object" || value === null) return false;
438
+ const record = value;
439
+ return Array.isArray(record.packages);
440
+ }
441
+ async function fileExists(path) {
442
+ try {
443
+ await (0, import_promises2.access)(path);
444
+ return true;
445
+ } catch {
446
+ return false;
447
+ }
448
+ }
449
+ async function findNearestAncestorWithEntry(startDir, entryName) {
450
+ let current = (0, import_node_path2.resolve)(startDir);
451
+ for (; ; ) {
452
+ const candidate = (0, import_node_path2.join)(current, entryName);
453
+ try {
454
+ await (0, import_promises2.stat)(candidate);
455
+ return current;
456
+ } catch {
457
+ }
458
+ const parent = (0, import_node_path2.dirname)(current);
459
+ if (parent === current) {
460
+ return null;
461
+ }
462
+ current = parent;
463
+ }
464
+ }
465
+
466
+ // src/commands/create/options.ts
467
+ function determineTemplateFromSelections(input) {
468
+ if (input.platform === "desktop-tauri") return "tauri-react";
469
+ const shouldSync = input.sync && input.db !== "none";
470
+ if (input.framework === "vue") {
471
+ if (input.tailwind && shouldSync) return "vue-tailwind-sync";
472
+ if (input.tailwind && !shouldSync) return "vue-tailwind";
473
+ return shouldSync ? "vue-sync" : "vue-basic";
474
+ }
475
+ if (input.framework === "svelte") {
476
+ if (input.tailwind && shouldSync) return "svelte-tailwind-sync";
477
+ if (input.tailwind && !shouldSync) return "svelte-tailwind";
478
+ return shouldSync ? "svelte-sync" : "svelte-basic";
479
+ }
480
+ if (input.framework === "solid") {
481
+ throw new Error("Solid templates are not available yet. Use react, vue, or svelte.");
482
+ }
483
+ if (input.tailwind && shouldSync) return "react-tailwind-sync";
484
+ if (input.tailwind && !shouldSync) return "react-tailwind";
485
+ if (!input.tailwind && shouldSync) return "react-sync";
486
+ return "react-basic";
487
+ }
488
+ function isPlatformValue(value) {
489
+ return value === "web" || value === "desktop-tauri";
490
+ }
491
+ function isFrameworkValue(value) {
492
+ return value === "react" || value === "vue" || value === "svelte" || value === "solid";
493
+ }
494
+ function isAuthValue(value) {
495
+ return value === "none" || value === "email-password" || value === "oauth";
496
+ }
497
+ function isDatabaseValue(value) {
498
+ return value === "none" || value === "sqlite" || value === "postgres";
499
+ }
500
+ function isDatabaseProviderValue(value) {
501
+ return value === "none" || value === "local" || value === "supabase" || value === "neon" || value === "railway" || value === "vercel-postgres" || value === "custom";
502
+ }
503
+ function isSupportedWebFramework(framework) {
504
+ return framework === "react" || framework === "vue" || framework === "svelte";
505
+ }
506
+
507
+ // src/commands/create/pnpm-workspace.ts
508
+ var import_promises3 = require("fs/promises");
509
+ var import_node_path3 = require("path");
510
+ async function writePnpmWorkspaceSettings(targetDir) {
511
+ const manifest = JSON.parse(await (0, import_promises3.readFile)((0, import_node_path3.join)(targetDir, "package.json"), "utf-8"));
512
+ const listed = manifest.pnpm?.onlyBuiltDependencies;
513
+ const allowed = Array.isArray(listed) ? [...new Set(listed.filter((name) => typeof name === "string"))].sort() : [];
514
+ await (0, import_promises3.writeFile)((0, import_node_path3.join)(targetDir, "pnpm-workspace.yaml"), renderPnpmWorkspace(allowed), "utf-8");
515
+ return allowed;
516
+ }
517
+ function renderPnpmWorkspace(allowed) {
518
+ const quote = (name) => `'${name.replace(/'/g, "''")}'`;
519
+ const lines = [
520
+ "# pnpm settings for this app. Dependencies listed here may run their install",
521
+ "# (build) scripts: pnpm 10 reads onlyBuiltDependencies, pnpm 11+ reads allowBuilds.",
522
+ "packages:",
523
+ " - '.'"
524
+ ];
525
+ if (allowed.length > 0) {
526
+ lines.push("onlyBuiltDependencies:", ...allowed.map((name) => ` - ${quote(name)}`));
527
+ lines.push("allowBuilds:", ...allowed.map((name) => ` ${quote(name)}: true`));
528
+ }
529
+ return `${lines.join("\n")}
530
+ `;
531
+ }
532
+
533
+ // src/commands/create/preferences-flow.ts
534
+ async function resolveCreatePreferencesFlow(params) {
535
+ const { flags, prompts, store } = params;
536
+ const stored = store.getCreatePreferences();
537
+ const base = getCreatePreferencesOrDefault(store);
538
+ const hasExplicitFlags = hasExplicitPreferenceFlags(flags);
539
+ const canOfferStored = !flags.useDefaults && !hasExplicitFlags && stored !== null && promptSupportsRichOptions();
540
+ let effective = { ...base };
541
+ let usedStoredPreferences = false;
542
+ if (flags.useDefaults) {
543
+ effective = getDefaultCreatePreferences();
544
+ } else if (canOfferStored && stored !== null) {
545
+ const reuseStored = await prompts.select("Welcome back! Choose setup mode:", [
546
+ { label: formatStoredPreferenceLabel(stored), value: "reuse" },
547
+ { label: "Customize", value: "customize" }
548
+ ]);
549
+ if (reuseStored === "reuse") {
550
+ effective = { ...stored };
551
+ usedStoredPreferences = true;
552
+ }
553
+ }
554
+ if (flags.platform !== void 0) {
555
+ if (!isPlatformValue(flags.platform)) {
556
+ throw new Error(
557
+ `Invalid --platform value "${flags.platform}". Expected one of: web, desktop-tauri.`
558
+ );
559
+ }
560
+ effective.platform = flags.platform;
561
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
562
+ effective.platform = await prompts.select("Platform:", [
563
+ { label: "Web (browser)", value: "web" },
564
+ { label: "Desktop (Tauri \u2014 native SQLite)", value: "desktop-tauri" }
565
+ ]);
566
+ }
567
+ const isTauri = effective.platform === "desktop-tauri";
568
+ if (isTauri) {
569
+ effective.framework = "react";
570
+ effective.tailwind = false;
571
+ effective.auth = "none";
572
+ if (flags.sync !== void 0) {
573
+ effective.sync = flags.sync;
574
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
575
+ effective.sync = await prompts.confirm("Enable multi-device sync?", true);
576
+ }
577
+ if (flags.db !== void 0) {
578
+ if (!isDatabaseValue(flags.db)) {
579
+ throw new Error(
580
+ `Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`
581
+ );
582
+ }
583
+ effective.db = flags.db;
584
+ } else if (!effective.sync) {
585
+ effective.db = "none";
586
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
587
+ effective.db = await prompts.select("Sync server database:", [
588
+ { label: "SQLite (zero-config; local, LAN, small teams)", value: "sqlite" },
589
+ { label: "PostgreSQL (production-scale)", value: "postgres" }
590
+ ]);
591
+ }
592
+ if (effective.db === "none") {
593
+ effective.sync = false;
594
+ }
595
+ if (effective.db !== "postgres") {
596
+ effective.dbProvider = "none";
597
+ } else if (flags.dbProvider !== void 0) {
598
+ if (!isDatabaseProviderValue(flags.dbProvider)) {
599
+ throw new Error(
600
+ `Invalid --db-provider value "${flags.dbProvider}". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`
601
+ );
602
+ }
603
+ effective.dbProvider = flags.dbProvider;
604
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
605
+ effective.dbProvider = await prompts.select("Database provider:", [
606
+ { label: "Local Postgres", value: "local" },
607
+ { label: "Supabase", value: "supabase" },
608
+ { label: "Neon", value: "neon" },
609
+ { label: "Railway", value: "railway" },
610
+ { label: "Vercel Postgres", value: "vercel-postgres" },
611
+ { label: "Custom connection string", value: "custom" }
612
+ ]);
613
+ }
614
+ } else {
615
+ if (flags.framework !== void 0) {
616
+ if (!isFrameworkValue(flags.framework)) {
617
+ throw new Error(
618
+ `Invalid --framework value "${flags.framework}". Expected one of: react, vue, svelte, solid.`
619
+ );
620
+ }
621
+ effective.framework = flags.framework;
622
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
623
+ effective.framework = await prompts.select("UI framework:", [
624
+ { label: "React", value: "react" },
625
+ { label: "Vue 3", value: "vue" },
626
+ { label: "Svelte 5", value: "svelte" },
627
+ { label: "Solid (coming soon)", value: "solid", disabled: true }
628
+ ]);
629
+ }
630
+ if (flags.auth !== void 0) {
631
+ if (!isAuthValue(flags.auth)) {
632
+ throw new Error(
633
+ `Invalid --auth value "${flags.auth}". Expected one of: none, email-password, oauth.`
634
+ );
635
+ }
636
+ effective.auth = flags.auth;
637
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
638
+ effective.auth = await prompts.select("Authentication:", [
639
+ { label: "None", value: "none" },
640
+ { label: "Email + Password (coming soon)", value: "email-password", disabled: true },
641
+ { label: "OAuth (coming soon)", value: "oauth", disabled: true }
642
+ ]);
643
+ }
644
+ if (flags.tailwind !== void 0) {
645
+ effective.tailwind = flags.tailwind;
646
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
647
+ effective.tailwind = await prompts.confirm("Use Tailwind CSS?", true);
648
+ }
649
+ if (flags.sync !== void 0) {
650
+ effective.sync = flags.sync;
651
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
652
+ effective.sync = await prompts.confirm("Enable multi-device sync?", true);
653
+ }
654
+ if (flags.db !== void 0) {
655
+ if (!isDatabaseValue(flags.db)) {
656
+ throw new Error(
657
+ `Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`
658
+ );
659
+ }
660
+ effective.db = flags.db;
661
+ } else if (!effective.sync) {
662
+ effective.db = "none";
663
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
664
+ effective.db = await prompts.select("Server-side database:", [
665
+ { label: "SQLite (zero-config)", value: "sqlite" },
666
+ { label: "PostgreSQL (production-scale)", value: "postgres" }
667
+ ]);
668
+ }
669
+ if (effective.db !== "postgres") {
670
+ effective.dbProvider = "none";
671
+ } else if (flags.dbProvider !== void 0) {
672
+ if (!isDatabaseProviderValue(flags.dbProvider)) {
673
+ throw new Error(
674
+ `Invalid --db-provider value "${flags.dbProvider}". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`
675
+ );
676
+ }
677
+ effective.dbProvider = flags.dbProvider;
678
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
679
+ effective.dbProvider = await prompts.select("Database provider:", [
680
+ { label: "Local Postgres", value: "local" },
681
+ { label: "Supabase", value: "supabase" },
682
+ { label: "Neon", value: "neon" },
683
+ { label: "Railway", value: "railway" },
684
+ { label: "Vercel Postgres", value: "vercel-postgres" },
685
+ { label: "Custom connection string", value: "custom" }
686
+ ]);
687
+ }
688
+ }
689
+ const template = determineTemplateFromSelections({
690
+ platform: effective.platform,
691
+ framework: effective.framework,
692
+ tailwind: effective.tailwind,
693
+ sync: effective.sync,
694
+ db: effective.db
695
+ });
696
+ return {
697
+ platform: effective.platform,
698
+ framework: effective.framework,
699
+ auth: effective.auth,
700
+ db: effective.db,
701
+ dbProvider: effective.dbProvider,
702
+ tailwind: effective.tailwind,
703
+ sync: effective.sync,
704
+ template,
705
+ usedStoredPreferences
706
+ };
707
+ }
708
+ function shouldSavePreferences(flags) {
709
+ return !flags.useDefaults;
710
+ }
711
+ function saveResolvedPreferences(store, resolution) {
712
+ store.saveCreatePreferences({
713
+ platform: resolution.platform,
714
+ framework: resolution.framework,
715
+ tailwind: resolution.tailwind,
716
+ sync: resolution.sync,
717
+ db: resolution.db,
718
+ dbProvider: resolution.dbProvider,
719
+ auth: resolution.auth,
720
+ packageManager: resolution.packageManager
721
+ });
722
+ }
723
+ function hasExplicitPreferenceFlags(flags) {
724
+ return flags.platform !== void 0 || flags.framework !== void 0 || flags.auth !== void 0 || flags.db !== void 0 || flags.dbProvider !== void 0 || flags.tailwind !== void 0 || flags.sync !== void 0;
725
+ }
726
+ function promptSupportsRichOptions() {
727
+ return typeof process !== "undefined" && process.stdin.isTTY && process.stdout.isTTY;
728
+ }
729
+ function formatStoredPreferenceLabel(preferences) {
730
+ if (preferences.platform === "desktop-tauri") {
731
+ return `Use previous settings (tauri-desktop + ${preferences.packageManager})`;
732
+ }
733
+ const syncLabel = preferences.sync ? `sync/${preferences.db}` : "local-only";
734
+ const styleLabel = preferences.tailwind ? "tailwind" : "css";
735
+ return `Use previous settings (${preferences.framework} + ${styleLabel} + ${syncLabel} + ${preferences.packageManager})`;
736
+ }
737
+
738
+ // src/commands/create/project-name.ts
739
+ var import_validate_npm_package_name = __toESM(require("validate-npm-package-name"), 1);
740
+ function validateProjectName(name) {
741
+ const trimmedName = name.trim();
742
+ if (trimmedName.length === 0) {
743
+ return {
744
+ valid: false,
745
+ issues: ["Project name cannot be empty."]
746
+ };
747
+ }
748
+ const validation = (0, import_validate_npm_package_name.default)(trimmedName);
749
+ const issues = [...validation.errors ?? [], ...validation.warnings ?? []];
750
+ if (!validation.validForNewPackages && issues.length === 0) {
751
+ return {
752
+ valid: false,
753
+ issues: ["Project name is not a valid npm package name."]
754
+ };
755
+ }
756
+ return {
757
+ valid: validation.validForNewPackages,
758
+ issues
759
+ };
760
+ }
761
+
762
+ // src/commands/create/sync-provider-preset.ts
763
+ var import_promises4 = require("fs/promises");
764
+ var import_node_path4 = require("path");
765
+ async function applySyncProviderPreset(options) {
766
+ if (!isSyncTemplate(options.template)) {
767
+ return;
768
+ }
769
+ if (options.db !== "postgres") {
770
+ return;
771
+ }
772
+ const providerName = getProviderDisplayName(options.dbProvider);
773
+ const providerConnectionString = getProviderConnectionStringExample(options.dbProvider);
774
+ const envPath = (0, import_node_path4.join)(options.targetDir, ".env.example");
775
+ const readmePath = (0, import_node_path4.join)(options.targetDir, "README.md");
776
+ const existingReadme = await (0, import_promises4.readFile)(readmePath, "utf-8");
777
+ const existingEnv = await (0, import_promises4.readFile)(envPath, "utf-8");
778
+ const trimmedReadme = existingReadme.trimEnd();
779
+ const trimmedEnv = existingEnv.trimEnd();
780
+ const envSuffix = [
781
+ "",
782
+ `# PostgreSQL provider preset: ${providerName}`,
783
+ `# Example: ${providerConnectionString}`
784
+ ].join("\n");
785
+ const readmeSuffix = [
786
+ "",
787
+ "## PostgreSQL Provider Preset",
788
+ "",
789
+ `Selected DB provider: ${options.dbProvider}`,
790
+ "",
791
+ "This scaffold keeps one sync server entrypoint. When `DATABASE_URL` is set, `server.ts` uses PostgreSQL. When it is empty, the same server uses SQLite at `KORA_SERVER_DB`.",
792
+ "",
793
+ "The generated server uses `createPostgresServerStore` automatically when `DATABASE_URL` is present.",
794
+ ""
795
+ ].join("\n");
796
+ const readmeTemplate = `${trimmedReadme}${readmeSuffix}`;
797
+ await (0, import_promises4.writeFile)(envPath, `${trimmedEnv}${envSuffix}
798
+ `, "utf-8");
799
+ await (0, import_promises4.writeFile)(readmePath, readmeTemplate, "utf-8");
800
+ }
801
+ function isSyncTemplate(template) {
802
+ return template === "react-sync" || template === "react-tailwind-sync" || template === "vue-sync" || template === "vue-tailwind-sync" || template === "svelte-sync" || template === "svelte-tailwind-sync" || template === "tauri-react";
803
+ }
804
+ function getProviderDisplayName(provider) {
805
+ switch (provider) {
806
+ case "supabase":
807
+ return "Supabase";
808
+ case "neon":
809
+ return "Neon";
810
+ case "railway":
811
+ return "Railway";
812
+ case "vercel-postgres":
813
+ return "Vercel Postgres";
814
+ case "custom":
815
+ return "Custom";
816
+ case "local":
817
+ return "Local Postgres";
818
+ case "none":
819
+ return "PostgreSQL";
820
+ }
821
+ }
822
+ function getProviderConnectionStringExample(provider) {
823
+ switch (provider) {
824
+ case "supabase":
825
+ return "postgresql://postgres:<password>@db.<project-ref>.supabase.co:5432/postgres?sslmode=require";
826
+ case "neon":
827
+ return "postgresql://<user>:<password>@<branch>.<project>.neon.tech/neondb?sslmode=require";
828
+ case "railway":
829
+ return "postgresql://postgres:<password>@<host>.railway.app:<port>/railway?sslmode=require";
830
+ case "vercel-postgres":
831
+ return "postgresql://<user>:<password>@<host>.pooler.vercel-storage.com:5432/verceldb?sslmode=require";
832
+ case "custom":
833
+ return "postgresql://<user>:<password>@<host>:5432/<database>";
834
+ case "local":
835
+ return "postgresql://postgres:postgres@localhost:5432/kora";
836
+ case "none":
837
+ return "postgresql://postgres:postgres@localhost:5432/kora";
838
+ }
839
+ }
840
+
841
+ // src/templates/composer.ts
842
+ var import_node_fs = require("fs");
843
+ var import_promises5 = require("fs/promises");
844
+ var import_node_path5 = require("path");
845
+ var import_node_url = require("url");
846
+
847
+ // src/templates/tauri-version.ts
848
+ var KORA_TAURI_TEMPLATE_VERSION = "0.4.3-beta.13";
849
+
850
+ // src/templates/composer.ts
851
+ var import_meta = {};
852
+ function substituteVariables(template, context) {
853
+ return template.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
854
+ const value = context[key];
855
+ return value !== void 0 ? value : `{{${key}}}`;
856
+ });
857
+ }
858
+ function getTemplatePath(templateName) {
859
+ let dir = (0, import_node_path5.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
860
+ for (let i = 0; i < 7; i++) {
861
+ const candidate = (0, import_node_path5.resolve)(dir, "templates", templateName);
862
+ if ((0, import_node_fs.existsSync)(candidate)) {
863
+ return candidate;
864
+ }
865
+ dir = (0, import_node_path5.dirname)(dir);
866
+ }
867
+ const currentDir = (0, import_node_path5.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
868
+ return (0, import_node_path5.resolve)(currentDir, "..", "..", "..", "templates", templateName);
869
+ }
870
+ function createCompatibilityLayerPlan(templateName) {
871
+ const baseLayer = { category: "base", name: "base", sourceTemplate: "react-basic" };
872
+ const uiLayer = { category: "ui", name: "react", sourceTemplate: null };
873
+ const authLayer = { category: "auth", name: "none", sourceTemplate: null };
874
+ switch (templateName) {
875
+ case "react-basic":
876
+ return {
877
+ compatibilityTarget: templateName,
878
+ layers: [
879
+ baseLayer,
880
+ uiLayer,
881
+ { category: "style", name: "plain", sourceTemplate: null },
882
+ { category: "sync", name: "disabled", sourceTemplate: null },
883
+ { category: "db", name: "none", sourceTemplate: null },
884
+ authLayer
885
+ ]
886
+ };
887
+ case "react-tailwind":
888
+ return {
889
+ compatibilityTarget: templateName,
890
+ layers: [
891
+ baseLayer,
892
+ uiLayer,
893
+ { category: "style", name: "tailwind", sourceTemplate: "react-tailwind" },
894
+ { category: "sync", name: "disabled", sourceTemplate: null },
895
+ { category: "db", name: "none", sourceTemplate: null },
896
+ authLayer
897
+ ]
898
+ };
899
+ case "react-sync":
900
+ return {
901
+ compatibilityTarget: templateName,
902
+ layers: [
903
+ baseLayer,
904
+ uiLayer,
905
+ { category: "style", name: "plain", sourceTemplate: null },
906
+ { category: "sync", name: "enabled", sourceTemplate: "react-sync" },
907
+ { category: "db", name: "sqlite", sourceTemplate: null },
908
+ authLayer
909
+ ]
910
+ };
911
+ case "react-tailwind-sync":
912
+ return {
913
+ compatibilityTarget: templateName,
914
+ layers: [
915
+ baseLayer,
916
+ uiLayer,
917
+ { category: "style", name: "tailwind", sourceTemplate: "react-tailwind" },
918
+ { category: "sync", name: "enabled", sourceTemplate: "react-tailwind-sync" },
919
+ { category: "db", name: "sqlite", sourceTemplate: null },
920
+ authLayer
921
+ ]
922
+ };
923
+ case "tauri-react":
924
+ return {
925
+ compatibilityTarget: templateName,
926
+ layers: [
927
+ { category: "base", name: "tauri", sourceTemplate: "tauri-react" },
928
+ uiLayer,
929
+ { category: "style", name: "plain", sourceTemplate: null },
930
+ { category: "sync", name: "enabled", sourceTemplate: null },
931
+ { category: "db", name: "tauri-sqlite", sourceTemplate: null },
932
+ authLayer
933
+ ]
934
+ };
935
+ case "vue-sync":
936
+ return {
937
+ compatibilityTarget: templateName,
938
+ layers: [{ category: "base", name: "vue-sync", sourceTemplate: "vue-sync" }]
939
+ };
940
+ case "vue-basic":
941
+ return {
942
+ compatibilityTarget: templateName,
943
+ layers: [{ category: "base", name: "vue-basic", sourceTemplate: "vue-basic" }]
944
+ };
945
+ case "svelte-sync":
946
+ return {
947
+ compatibilityTarget: templateName,
948
+ layers: [{ category: "base", name: "svelte-sync", sourceTemplate: "svelte-sync" }]
949
+ };
950
+ case "svelte-basic":
951
+ return {
952
+ compatibilityTarget: templateName,
953
+ layers: [{ category: "base", name: "svelte-basic", sourceTemplate: "svelte-basic" }]
954
+ };
955
+ case "vue-tailwind-sync":
956
+ return {
957
+ compatibilityTarget: templateName,
958
+ layers: [
959
+ { category: "base", name: "vue-tailwind-sync", sourceTemplate: "vue-tailwind-sync" }
960
+ ]
961
+ };
962
+ case "vue-tailwind":
963
+ return {
964
+ compatibilityTarget: templateName,
965
+ layers: [{ category: "base", name: "vue-tailwind", sourceTemplate: "vue-tailwind" }]
966
+ };
967
+ case "svelte-tailwind-sync":
968
+ return {
969
+ compatibilityTarget: templateName,
970
+ layers: [
971
+ {
972
+ category: "base",
973
+ name: "svelte-tailwind-sync",
974
+ sourceTemplate: "svelte-tailwind-sync"
975
+ }
976
+ ]
977
+ };
978
+ case "svelte-tailwind":
979
+ return {
980
+ compatibilityTarget: templateName,
981
+ layers: [{ category: "base", name: "svelte-tailwind", sourceTemplate: "svelte-tailwind" }]
982
+ };
983
+ }
984
+ }
985
+ async function composeTemplateLayers(plan, targetDir, context) {
986
+ const vars = {
987
+ projectName: context.projectName,
988
+ packageManager: context.packageManager,
989
+ koraVersion: context.koraVersion,
990
+ tauriVersion: context.tauriVersion ?? KORA_TAURI_TEMPLATE_VERSION,
991
+ dbProvider: context.dbProvider ?? "none"
992
+ };
993
+ for (const layer of plan.layers) {
994
+ if (layer.sourceTemplate === null) {
995
+ continue;
996
+ }
997
+ const sourceDir = getTemplatePath(layer.sourceTemplate);
998
+ await copyDirectory(sourceDir, targetDir, vars);
999
+ }
1000
+ }
1001
+ async function copyDirectory(src, dest, vars) {
1002
+ await (0, import_promises5.mkdir)(dest, { recursive: true });
1003
+ const entries = await (0, import_promises5.readdir)(src);
1004
+ for (const entry of entries) {
1005
+ const srcPath = (0, import_node_path5.join)(src, entry);
1006
+ const srcStat = await (0, import_promises5.stat)(srcPath);
1007
+ if (srcStat.isDirectory()) {
1008
+ await copyDirectory(srcPath, (0, import_node_path5.join)(dest, entry), vars);
1009
+ continue;
1010
+ }
1011
+ if (entry.endsWith(".hbs")) {
1012
+ const content = await (0, import_promises5.readFile)(srcPath, "utf-8");
1013
+ const outputName = entry.slice(0, -4);
1014
+ await (0, import_promises5.writeFile)((0, import_node_path5.join)(dest, outputName), substituteVariables(content, vars), "utf-8");
1015
+ continue;
1016
+ }
1017
+ await (0, import_promises5.copyFile)(srcPath, (0, import_node_path5.join)(dest, entry));
1018
+ }
1019
+ }
1020
+
1021
+ // src/commands/create/template-engine.ts
1022
+ async function scaffoldTemplate(templateName, targetDir, context) {
1023
+ const plan = createCompatibilityLayerPlan(templateName);
1024
+ await composeTemplateLayers(plan, targetDir, context);
1025
+ }
1026
+
1027
+ // src/commands/create/create-command.ts
1028
+ var import_meta2 = {};
1029
+ var createCommand = (0, import_citty.defineCommand)({
1030
+ meta: {
1031
+ name: "create",
1032
+ description: "Create a new Kora application"
1033
+ },
1034
+ args: {
1035
+ name: {
1036
+ type: "positional",
1037
+ description: "Project directory name",
1038
+ required: false
1039
+ },
1040
+ platform: {
1041
+ type: "string",
1042
+ description: "Target platform (web, desktop-tauri)"
1043
+ },
1044
+ template: {
1045
+ type: "string",
1046
+ description: "Project template (react-tailwind-sync, react-sync, vue-sync, svelte-sync, tauri-react, ...)"
1047
+ },
1048
+ pm: {
1049
+ type: "string",
1050
+ description: "Package manager (pnpm, npm, yarn, bun)"
1051
+ },
1052
+ framework: {
1053
+ type: "string",
1054
+ description: "UI framework (react, vue, svelte, solid)"
1055
+ },
1056
+ db: {
1057
+ type: "string",
1058
+ description: "Database backend for sync templates (sqlite, postgres)"
1059
+ },
1060
+ "db-provider": {
1061
+ type: "string",
1062
+ description: "Database provider for postgres (local, supabase, neon, railway, vercel-postgres, custom)"
1063
+ },
1064
+ auth: {
1065
+ type: "string",
1066
+ description: "Authentication mode (none, email-password, oauth)"
1067
+ },
1068
+ "skip-install": {
1069
+ type: "boolean",
1070
+ description: "Skip installing dependencies",
1071
+ default: false
1072
+ },
1073
+ yes: {
1074
+ type: "boolean",
1075
+ alias: "y",
1076
+ description: "Accept all defaults (react-tailwind-sync + detected package manager)",
1077
+ default: false
1078
+ },
1079
+ tailwind: {
1080
+ type: "boolean",
1081
+ description: "Use Tailwind CSS (use --no-tailwind to skip)"
1082
+ },
1083
+ sync: {
1084
+ type: "boolean",
1085
+ description: "Include sync server (use --no-sync to skip)"
1086
+ }
1087
+ },
1088
+ async run({ args }) {
1089
+ const logger = createLogger();
1090
+ const prompts = createPromptClient();
1091
+ const preferenceStore = new PreferenceStore();
1092
+ logger.banner();
1093
+ try {
1094
+ const useDefaults = args.yes === true;
1095
+ if (!useDefaults) {
1096
+ prompts.intro("Kora.js \u2014 Offline-first application framework");
1097
+ }
1098
+ const projectName = args.name || (useDefaults ? "my-kora-app" : await prompts.text("Project name", "my-kora-app"));
1099
+ if (!projectName) {
1100
+ logger.error("Project name is required");
1101
+ process.exitCode = 1;
1102
+ return;
1103
+ }
1104
+ const nameValidation = validateProjectName(projectName);
1105
+ if (!nameValidation.valid) {
1106
+ logger.error("Invalid project name.");
1107
+ for (const issue of nameValidation.issues) {
1108
+ logger.step(`- ${issue}`);
1109
+ }
1110
+ if (!useDefaults) {
1111
+ prompts.outro("Project creation aborted.");
1112
+ }
1113
+ process.exitCode = 1;
1114
+ return;
1115
+ }
1116
+ const preferenceFlags = {
1117
+ platform: typeof args.platform === "string" ? args.platform : void 0,
1118
+ framework: typeof args.framework === "string" ? args.framework : void 0,
1119
+ auth: typeof args.auth === "string" ? args.auth : void 0,
1120
+ db: typeof args.db === "string" ? args.db : void 0,
1121
+ dbProvider: typeof args["db-provider"] === "string" ? args["db-provider"] : void 0,
1122
+ tailwind: args.tailwind,
1123
+ sync: args.sync,
1124
+ useDefaults
1125
+ };
1126
+ const selection = await resolveCreatePreferencesFlow({
1127
+ flags: preferenceFlags,
1128
+ prompts,
1129
+ store: preferenceStore
1130
+ });
1131
+ if (!isSupportedWebFramework(selection.framework)) {
1132
+ logger.error(
1133
+ `Framework "${selection.framework}" is not available yet. Use react, vue, or svelte.`
1134
+ );
1135
+ if (!useDefaults) {
1136
+ prompts.outro("Project creation aborted.");
1137
+ }
1138
+ process.exitCode = 1;
1139
+ return;
1140
+ }
1141
+ if (selection.auth !== "none") {
1142
+ logger.error(`Auth mode "${selection.auth}" is not available yet. Use "none".`);
1143
+ if (!useDefaults) {
1144
+ prompts.outro("Project creation aborted.");
1145
+ }
1146
+ process.exitCode = 1;
1147
+ return;
1148
+ }
1149
+ const template = args.template && isValidTemplate(args.template) ? args.template : selection.template;
1150
+ let pm;
1151
+ if (args.pm && isValidPackageManager(args.pm)) {
1152
+ pm = args.pm;
1153
+ } else if (useDefaults) {
1154
+ pm = detectPackageManager();
1155
+ } else if (selection.usedStoredPreferences) {
1156
+ pm = preferenceStore.getCreatePreferences()?.packageManager ?? detectPackageManager();
1157
+ } else {
1158
+ const detected = detectPackageManager();
1159
+ pm = await prompts.select(
1160
+ "Package manager:",
1161
+ PACKAGE_MANAGERS.map((p) => ({
1162
+ label: p === detected ? `${p} (detected)` : p,
1163
+ value: p
1164
+ }))
1165
+ );
1166
+ }
1167
+ const editorDetection = detectEditorFromEnvironment();
1168
+ const gitContext = await detectGitContext(process.cwd());
1169
+ const monorepoContext = await detectMonorepoContext(process.cwd());
1170
+ let targetDir = (0, import_node_path6.resolve)(process.cwd(), projectName);
1171
+ if (!useDefaults && monorepoContext.isMonorepo && monorepoContext.root !== null) {
1172
+ const useWorkspaceTarget = await prompts.confirm(
1173
+ `Detected ${formatMonorepoKind(monorepoContext.kind)} at ${monorepoContext.root}. Create app under packages/${projectName}?`,
1174
+ true
1175
+ );
1176
+ if (useWorkspaceTarget) {
1177
+ targetDir = resolveMonorepoTargetDirectory(monorepoContext.root, projectName);
1178
+ }
1179
+ }
1180
+ if (await directoryExists(targetDir)) {
1181
+ throw new ProjectExistsError(projectName);
1182
+ }
1183
+ const koraVersion = resolveKoraVersion();
1184
+ logger.step(`Creating ${projectName} with ${template} template...`);
1185
+ await scaffoldTemplate(template, targetDir, {
1186
+ projectName,
1187
+ packageManager: pm,
1188
+ koraVersion,
1189
+ dbProvider: selection.dbProvider
1190
+ });
1191
+ await applySyncProviderPreset({
1192
+ targetDir,
1193
+ template,
1194
+ db: selection.db,
1195
+ dbProvider: selection.dbProvider
1196
+ });
1197
+ if (pm === "pnpm") {
1198
+ await writePnpmWorkspaceSettings(targetDir);
1199
+ }
1200
+ if (!useDefaults && editorDetection.editor !== "unknown") {
1201
+ const shouldApplyEditorPreset = await prompts.confirm(
1202
+ `Detected ${formatEditor(editorDetection.editor)}. Add workspace recommendations for ${formatEditor(editorDetection.editor)}?`,
1203
+ true
1204
+ );
1205
+ if (shouldApplyEditorPreset) {
1206
+ const appliedPreset = await applyEditorWorkspacePreset({
1207
+ targetDir,
1208
+ editor: editorDetection.editor
1209
+ });
1210
+ if (appliedPreset.applied) {
1211
+ logger.step(
1212
+ `Added editor recommendations at ${relativeToTarget(targetDir, appliedPreset.filePath)}`
1213
+ );
1214
+ }
1215
+ }
1216
+ }
1217
+ if (selection.db === "postgres" && isSyncTemplate2(template)) {
1218
+ logger.info(
1219
+ `Applied PostgreSQL sync preset (${formatDbProviderForLog(selection.dbProvider)}). Update DATABASE_URL in .env.example before running the sync server.`
1220
+ );
1221
+ }
1222
+ if (gitContext.hasRepository) {
1223
+ logger.step(
1224
+ `Detected existing git repository at ${gitContext.repositoryRoot}. Skipping git initialization.`
1225
+ );
1226
+ }
1227
+ logger.success("Project scaffolded");
1228
+ if (shouldSavePreferences(preferenceFlags)) {
1229
+ saveResolvedPreferences(preferenceStore, {
1230
+ platform: selection.platform,
1231
+ framework: selection.framework,
1232
+ auth: selection.auth,
1233
+ db: selection.db,
1234
+ dbProvider: selection.dbProvider,
1235
+ tailwind: selection.tailwind,
1236
+ sync: selection.sync,
1237
+ packageManager: pm
1238
+ });
1239
+ }
1240
+ if (!args["skip-install"]) {
1241
+ logger.step("Installing dependencies...");
1242
+ try {
1243
+ (0, import_node_child_process2.execSync)(getInstallCommand(pm), { cwd: targetDir, stdio: "inherit" });
1244
+ logger.success("Dependencies installed");
1245
+ } catch {
1246
+ logger.warn("Failed to install dependencies. Run install manually.");
1247
+ }
1248
+ }
1249
+ logger.blank();
1250
+ logger.info("Done! Next steps:");
1251
+ logger.blank();
1252
+ logger.step(` cd ${targetDir}`);
1253
+ logger.step(` ${getRunDevCommand(pm)}`);
1254
+ logger.blank();
1255
+ if (!useDefaults) {
1256
+ prompts.outro("Project ready. Happy building with Kora!");
1257
+ }
1258
+ } catch (error) {
1259
+ if (error instanceof PromptCancelledError) {
1260
+ process.exitCode = 1;
1261
+ return;
1262
+ }
1263
+ if (error instanceof Error && error.message.startsWith("Invalid --")) {
1264
+ logger.error(error.message);
1265
+ if (!args.yes) {
1266
+ prompts.outro("Project creation aborted.");
1267
+ }
1268
+ process.exitCode = 1;
1269
+ return;
1270
+ }
1271
+ throw error;
1272
+ }
1273
+ }
1274
+ });
1275
+ function isValidTemplate(value) {
1276
+ return TEMPLATES.includes(value);
1277
+ }
1278
+ function isValidPackageManager(value) {
1279
+ return PACKAGE_MANAGERS.includes(value);
1280
+ }
1281
+ function isSyncTemplate2(template) {
1282
+ return template === "react-sync" || template === "react-tailwind-sync" || template === "vue-sync" || template === "vue-tailwind-sync" || template === "svelte-sync" || template === "svelte-tailwind-sync" || template === "tauri-react";
1283
+ }
1284
+ function formatDbProviderForLog(dbProvider) {
1285
+ switch (dbProvider) {
1286
+ case "supabase":
1287
+ return "Supabase";
1288
+ case "neon":
1289
+ return "Neon";
1290
+ case "railway":
1291
+ return "Railway";
1292
+ case "vercel-postgres":
1293
+ return "Vercel Postgres";
1294
+ case "custom":
1295
+ return "Custom";
1296
+ case "local":
1297
+ return "Local Postgres";
1298
+ case "none":
1299
+ return "PostgreSQL";
1300
+ default:
1301
+ return dbProvider;
1302
+ }
1303
+ }
1304
+ function formatEditor(editor) {
1305
+ switch (editor) {
1306
+ case "vscode":
1307
+ return "VS Code";
1308
+ case "cursor":
1309
+ return "Cursor";
1310
+ case "windsurf":
1311
+ return "Windsurf";
1312
+ case "zed":
1313
+ return "Zed";
1314
+ default:
1315
+ return editor;
1316
+ }
1317
+ }
1318
+ function formatMonorepoKind(kind) {
1319
+ switch (kind) {
1320
+ case "pnpm-workspace":
1321
+ return "pnpm workspace";
1322
+ case "npm-workspaces":
1323
+ return "npm workspace";
1324
+ case "turborepo":
1325
+ return "Turborepo";
1326
+ default:
1327
+ return "monorepo";
1328
+ }
1329
+ }
1330
+ function relativeToTarget(targetDir, filePath) {
1331
+ if (filePath === null) return ".";
1332
+ const normalizedTarget = targetDir.endsWith("/") ? targetDir : `${targetDir}/`;
1333
+ if (filePath.startsWith(normalizedTarget)) {
1334
+ return filePath.slice(normalizedTarget.length);
1335
+ }
1336
+ if (filePath === targetDir) {
1337
+ return ".";
1338
+ }
1339
+ return filePath;
1340
+ }
1341
+ function resolveKoraVersion() {
1342
+ try {
1343
+ let dir = (0, import_node_path6.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
1344
+ for (let i = 0; i < 5; i++) {
1345
+ const pkgPath = (0, import_node_path6.resolve)(dir, "package.json");
1346
+ if ((0, import_node_fs2.existsSync)(pkgPath)) {
1347
+ const pkg = JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf-8"));
1348
+ if (pkg.name === "@korajs/cli") {
1349
+ return deriveKoraTemplateVersion(pkg.version);
1350
+ }
1351
+ }
1352
+ dir = (0, import_node_path6.dirname)(dir);
1353
+ }
1354
+ return "latest";
1355
+ } catch {
1356
+ return "latest";
1357
+ }
1358
+ }
1359
+ function deriveKoraTemplateVersion(version) {
1360
+ if (version === "0.0.0") return "latest";
1361
+ if (version.includes("-")) return version;
1362
+ const parts = version.split(".");
1363
+ return `^${parts[0]}.${parts[1]}.0`;
1364
+ }
1365
+
1366
+ // src/create.ts
1367
+ (0, import_citty2.runMain)(createCommand);
1368
+ //# sourceMappingURL=create.cjs.map