stackkit 0.3.4 → 0.3.6

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 (203) hide show
  1. package/README.md +50 -42
  2. package/dist/cli/add.js +122 -56
  3. package/dist/cli/create.d.ts +2 -0
  4. package/dist/cli/create.js +271 -95
  5. package/dist/cli/doctor.js +1 -0
  6. package/dist/cli/list.d.ts +1 -1
  7. package/dist/cli/list.js +6 -4
  8. package/dist/index.js +234 -191
  9. package/dist/lib/constants.d.ts +4 -0
  10. package/dist/lib/constants.js +4 -0
  11. package/dist/lib/discovery/module-discovery.d.ts +4 -0
  12. package/dist/lib/discovery/module-discovery.js +56 -0
  13. package/dist/lib/generation/code-generator.d.ts +11 -2
  14. package/dist/lib/generation/code-generator.js +42 -3
  15. package/dist/lib/generation/generator-utils.js +3 -1
  16. package/dist/lib/pm/package-manager.js +16 -13
  17. package/dist/lib/ui/logger.js +3 -2
  18. package/dist/lib/utils/path-resolver.d.ts +2 -0
  19. package/dist/lib/utils/path-resolver.js +8 -0
  20. package/dist/meta.json +8312 -0
  21. package/modules/auth/better-auth/files/{shared → express}/config/env.ts +48 -52
  22. package/modules/auth/better-auth/files/express/middlewares/authorize.ts +20 -1
  23. package/modules/auth/better-auth/files/express/modules/auth.controller.ts +349 -0
  24. package/modules/auth/better-auth/files/express/modules/{auth/auth.route.ts → auth.route.ts} +12 -7
  25. package/modules/auth/better-auth/files/express/modules/auth.service.ts +664 -0
  26. package/modules/auth/better-auth/files/express/modules/{auth/auth.type.ts → auth.type.ts} +22 -9
  27. package/modules/auth/better-auth/files/{shared/mongoose/auth/constants.ts → express/mongo-modules/auth.constants.ts} +0 -1
  28. package/modules/auth/better-auth/files/{shared/mongoose/auth/helper.ts → express/mongo-modules/auth.helper.ts} +11 -1
  29. package/modules/auth/better-auth/files/express/types/express.d.ts +11 -0
  30. package/modules/auth/better-auth/files/nextjs/api-route.ts +74 -0
  31. package/modules/auth/better-auth/files/nextjs/dashboard/pages/(user)/page.tsx +6 -0
  32. package/modules/auth/better-auth/files/nextjs/dashboard/pages/admin/page.tsx +6 -0
  33. package/modules/auth/better-auth/files/nextjs/dashboard/pages/layout.tsx +48 -0
  34. package/modules/auth/better-auth/files/nextjs/dashboard/pages/my-profile/page.tsx +5 -0
  35. package/modules/auth/better-auth/files/nextjs/features/services/auth.service.ts +102 -0
  36. package/modules/auth/better-auth/files/nextjs/layout/layout.tsx +13 -0
  37. package/modules/auth/better-auth/files/nextjs/lib/axios/http.ts +158 -0
  38. package/modules/auth/better-auth/files/nextjs/lib/env.ts +35 -0
  39. package/modules/auth/better-auth/files/nextjs/lib/utils/auth.ts +75 -0
  40. package/modules/auth/better-auth/files/nextjs/lib/utils/cookie.ts +29 -0
  41. package/modules/auth/better-auth/files/nextjs/lib/utils/jwt.ts +28 -0
  42. package/modules/auth/better-auth/files/nextjs/lib/utils/token.ts +49 -0
  43. package/modules/auth/better-auth/files/nextjs/pages/forgot-password/page.tsx +5 -0
  44. package/modules/auth/better-auth/files/nextjs/pages/layout.tsx +11 -0
  45. package/modules/auth/better-auth/files/nextjs/pages/login/page.tsx +9 -0
  46. package/modules/auth/better-auth/files/nextjs/pages/register/page.tsx +5 -0
  47. package/modules/auth/better-auth/files/nextjs/pages/reset-password/page.tsx +10 -0
  48. package/modules/auth/better-auth/files/nextjs/pages/verify-email/page.tsx +10 -0
  49. package/modules/auth/better-auth/files/nextjs/proxy.ts +157 -22
  50. package/modules/auth/better-auth/files/nextjs/theme/providers/theme-provider.tsx +11 -0
  51. package/modules/auth/better-auth/files/nextjs/types/api.types.ts +18 -0
  52. package/modules/auth/better-auth/files/react/components/protected-route.tsx +39 -0
  53. package/modules/auth/better-auth/files/react/components/route-guards.tsx +13 -0
  54. package/modules/auth/better-auth/files/react/dashboard/admin/pages/overview.tsx +3 -0
  55. package/modules/auth/better-auth/files/react/dashboard/pages/overview.tsx +3 -0
  56. package/modules/auth/better-auth/files/react/features/pages/forgot-password.tsx +5 -0
  57. package/modules/auth/better-auth/files/react/features/pages/login.tsx +5 -0
  58. package/modules/auth/better-auth/files/react/features/pages/my-profile.tsx +5 -0
  59. package/modules/auth/better-auth/files/react/features/pages/oauth-callback.tsx +59 -0
  60. package/modules/auth/better-auth/files/react/features/pages/register.tsx +5 -0
  61. package/modules/auth/better-auth/files/react/features/pages/reset-password.tsx +10 -0
  62. package/modules/auth/better-auth/files/react/features/pages/verify-email.tsx +10 -0
  63. package/modules/auth/better-auth/files/react/layout/dashboard-layout.tsx +54 -0
  64. package/modules/auth/better-auth/files/react/lib/axios/http.ts +68 -0
  65. package/modules/auth/better-auth/files/react/lib/env.ts +25 -0
  66. package/modules/auth/better-auth/files/react/router.tsx +73 -0
  67. package/modules/auth/better-auth/files/react/theme/components/providers/theme-provider-context.ts +13 -0
  68. package/modules/auth/better-auth/files/react/theme/components/providers/theme-provider.tsx +51 -0
  69. package/modules/auth/better-auth/files/react/theme/hooks/use-theme.ts +8 -0
  70. package/modules/auth/better-auth/files/shared/features/components/change-password-dialog.tsx +113 -0
  71. package/modules/auth/better-auth/files/shared/features/components/forgot-password-form.tsx +84 -0
  72. package/modules/auth/better-auth/files/shared/features/components/login-form.tsx +134 -0
  73. package/modules/auth/better-auth/files/shared/features/components/my-profile.tsx +147 -0
  74. package/modules/auth/better-auth/files/shared/features/components/profile-form.tsx +205 -0
  75. package/modules/auth/better-auth/files/shared/features/components/register-form.tsx +100 -0
  76. package/modules/auth/better-auth/files/shared/features/components/reset-password-form.tsx +111 -0
  77. package/modules/auth/better-auth/files/shared/features/components/social-login-buttons.tsx +47 -0
  78. package/modules/auth/better-auth/files/shared/features/components/user-profile-menu.tsx +106 -0
  79. package/modules/auth/better-auth/files/shared/features/components/verify-email-form.tsx +110 -0
  80. package/modules/auth/better-auth/files/shared/features/queries/auth.mutations.tsx +312 -0
  81. package/modules/auth/better-auth/files/shared/features/queries/auth.querie.ts +19 -0
  82. package/modules/auth/better-auth/files/shared/features/services/auth.api.ts +81 -0
  83. package/modules/auth/better-auth/files/shared/features/types/auth.type.ts +47 -0
  84. package/modules/auth/better-auth/files/shared/features/validators/change-password.validator.ts +18 -0
  85. package/modules/auth/better-auth/files/shared/features/validators/forgot.validator.ts +7 -0
  86. package/modules/auth/better-auth/files/shared/features/validators/login.validator.ts +14 -0
  87. package/modules/auth/better-auth/files/shared/features/validators/profile.validator.ts +8 -0
  88. package/modules/auth/better-auth/files/shared/features/validators/register.validator.ts +9 -0
  89. package/modules/auth/better-auth/files/shared/features/validators/reset.validator.ts +9 -0
  90. package/modules/auth/better-auth/files/shared/features/validators/verify.validator.ts +8 -0
  91. package/modules/auth/better-auth/files/shared/lib/auth-client.ts +2 -1
  92. package/modules/auth/better-auth/files/shared/lib/auth.ts +10 -29
  93. package/modules/auth/better-auth/files/shared/lib/constant/dashboard.ts +90 -0
  94. package/modules/auth/better-auth/files/shared/prisma/enums.prisma +0 -1
  95. package/modules/auth/better-auth/files/shared/theme/mode-toggle.tsx +30 -0
  96. package/modules/auth/better-auth/files/shared/ui/shadcn/components/dashboard/dashboard-header.tsx +94 -0
  97. package/modules/auth/better-auth/files/shared/ui/shadcn/components/dashboard/dashboard-sidebar.tsx +255 -0
  98. package/modules/auth/better-auth/files/shared/ui/shadcn/components/footer.tsx +35 -0
  99. package/modules/auth/better-auth/files/shared/ui/shadcn/components/navbar.tsx +145 -0
  100. package/modules/auth/better-auth/files/shared/ui/shadcn/form-field/input-field.tsx +440 -0
  101. package/modules/auth/better-auth/files/shared/utils/email.ts +20 -18
  102. package/modules/auth/better-auth/generator.json +174 -53
  103. package/modules/auth/better-auth/module.json +2 -2
  104. package/modules/components/files/shared/hooks/use-file-upload.ts +412 -0
  105. package/modules/components/files/shared/lib/utils/url-helpers.ts +110 -0
  106. package/modules/components/files/shared/shadcn/dashboard/data-table-column-selector.tsx +52 -0
  107. package/modules/components/files/shared/shadcn/dashboard/data-table-footer.tsx +156 -0
  108. package/modules/components/files/shared/shadcn/dashboard/data-table.tsx +405 -0
  109. package/modules/components/files/shared/shadcn/global/form-field/input-field.tsx +440 -0
  110. package/modules/components/files/shared/shadcn/global/form-field/media-uploader-field.tsx +745 -0
  111. package/modules/components/files/shared/shadcn/global/form-field/multi-select-field.tsx +207 -0
  112. package/modules/components/files/shared/shadcn/global/form-field/select-field.tsx +247 -0
  113. package/modules/components/files/shared/shadcn/global/form-field/textarea-field.tsx +277 -0
  114. package/modules/components/files/shared/shadcn/global/form-field/tiptap-editor-field.tsx +35 -0
  115. package/modules/components/files/shared/shadcn/global/no-results.tsx +41 -0
  116. package/modules/components/files/shared/shadcn/tiptap-editor/editor-menu-bar.tsx +217 -0
  117. package/modules/components/files/shared/shadcn/tiptap-editor/tiptap-editor.tsx +104 -0
  118. package/modules/components/files/shared/url/load-more.tsx +93 -0
  119. package/modules/components/files/shared/url/search-bar.tsx +131 -0
  120. package/modules/components/files/shared/url/sort-select.tsx +118 -0
  121. package/modules/components/files/shared/url/url-tabs.tsx +77 -0
  122. package/modules/components/generator.json +109 -0
  123. package/modules/components/module.json +11 -0
  124. package/modules/database/mongoose/generator.json +3 -14
  125. package/modules/database/mongoose/module.json +2 -2
  126. package/modules/database/prisma/generator.json +6 -12
  127. package/modules/database/prisma/module.json +2 -2
  128. package/modules/storage/cloudinary/files/express/config/env.ts +65 -0
  129. package/modules/storage/cloudinary/files/express/config/media.ts +103 -0
  130. package/modules/storage/cloudinary/files/express/modules/media/media.controller.ts +59 -0
  131. package/modules/storage/cloudinary/files/express/modules/media/media.route.ts +29 -0
  132. package/modules/storage/cloudinary/files/express/modules/media/media.service.ts +113 -0
  133. package/modules/storage/cloudinary/files/express/modules/media/media.type.ts +32 -0
  134. package/modules/storage/cloudinary/generator.json +34 -0
  135. package/modules/storage/cloudinary/module.json +11 -0
  136. package/modules/ui/shadcn/generator.json +21 -0
  137. package/modules/ui/shadcn/module.json +11 -0
  138. package/package.json +24 -26
  139. package/templates/express/README.md +11 -16
  140. package/templates/express/src/config/env.ts +7 -5
  141. package/templates/nextjs/README.md +13 -18
  142. package/templates/nextjs/app/favicon.ico +0 -0
  143. package/templates/nextjs/app/layout.tsx +6 -4
  144. package/templates/nextjs/components/providers/query-provider.tsx +3 -0
  145. package/templates/nextjs/env.example +3 -1
  146. package/templates/nextjs/lib/axios/http.ts +23 -0
  147. package/templates/nextjs/lib/env.ts +7 -5
  148. package/templates/nextjs/package.json +2 -1
  149. package/templates/nextjs/template.json +1 -2
  150. package/templates/react/README.md +9 -14
  151. package/templates/react/index.html +1 -1
  152. package/templates/react/package.json +1 -1
  153. package/templates/react/src/assets/favicon.ico +0 -0
  154. package/templates/react/src/components/providers/query-provider.tsx +38 -0
  155. package/templates/react/src/{shared/components → components}/seo.tsx +4 -8
  156. package/templates/react/src/lib/axios/http.ts +24 -0
  157. package/templates/react/src/main.tsx +8 -11
  158. package/templates/react/src/{features/about/pages → pages}/about.tsx +1 -1
  159. package/templates/react/src/{features/home/pages → pages}/home.tsx +1 -1
  160. package/templates/react/src/router.tsx +6 -6
  161. package/templates/react/src/vite-env.d.ts +2 -1
  162. package/templates/react/template.json +0 -1
  163. package/templates/react/tsconfig.app.json +6 -0
  164. package/templates/react/tsconfig.json +7 -1
  165. package/templates/react/vite.config.ts +12 -0
  166. package/modules/auth/authjs/files/nextjs/api/auth/[...nextauth]/route.ts +0 -3
  167. package/modules/auth/authjs/files/nextjs/proxy.ts +0 -1
  168. package/modules/auth/authjs/files/shared/lib/auth.ts +0 -119
  169. package/modules/auth/authjs/files/shared/prisma/schema.prisma +0 -61
  170. package/modules/auth/authjs/generator.json +0 -64
  171. package/modules/auth/authjs/module.json +0 -13
  172. package/modules/auth/better-auth/files/express/modules/auth/auth.controller.ts +0 -264
  173. package/modules/auth/better-auth/files/express/modules/auth/auth.service.ts +0 -537
  174. package/modules/auth/better-auth/files/express/templates/google-redirect.ejs +0 -24
  175. package/modules/auth/better-auth/files/nextjs/api/auth/[...all]/route.ts +0 -4
  176. package/modules/auth/better-auth/files/nextjs/lib/auth/auth-guards.ts +0 -41
  177. package/modules/auth/better-auth/files/nextjs/templates/email-otp.tsx +0 -74
  178. package/templates/express/node_modules/.bin/acorn +0 -17
  179. package/templates/express/node_modules/.bin/eslint +0 -17
  180. package/templates/express/node_modules/.bin/tsc +0 -17
  181. package/templates/express/node_modules/.bin/tsserver +0 -17
  182. package/templates/express/node_modules/.bin/tsx +0 -17
  183. package/templates/nextjs/lib/api/http.ts +0 -40
  184. package/templates/nextjs/next-env.d.ts +0 -6
  185. package/templates/react/dist/assets/index-D4AHT4dU.js +0 -193
  186. package/templates/react/dist/assets/index-rpwj5ZOX.css +0 -1
  187. package/templates/react/dist/index.html +0 -14
  188. package/templates/react/dist/vite.svg +0 -1
  189. package/templates/react/public/vite.svg +0 -1
  190. package/templates/react/src/app/layouts/dashboard-layout.tsx +0 -8
  191. package/templates/react/src/app/layouts/public-layout.tsx +0 -5
  192. package/templates/react/src/app/providers.tsx +0 -20
  193. package/templates/react/src/app/router.tsx +0 -21
  194. package/templates/react/src/assets/react.svg +0 -1
  195. package/templates/react/src/shared/api/http.ts +0 -39
  196. package/templates/react/src/shared/components/loading.tsx +0 -8
  197. package/templates/react/src/shared/lib/query-client.ts +0 -12
  198. package/templates/react/src/utils/storage.ts +0 -35
  199. package/templates/react/src/utils/utils.ts +0 -3
  200. /package/templates/nextjs/app/{page.tsx → (public)/(root)/page.tsx} +0 -0
  201. /package/templates/react/src/{shared/components → components}/error-boundary.tsx +0 -0
  202. /package/templates/react/src/{shared/components → components}/layout.tsx +0 -0
  203. /package/templates/react/src/{shared/pages → pages}/not-found.tsx +0 -0
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Production-ready full-stack project generator.
4
4
 
5
- ## Installation
5
+ ## Usage
6
6
 
7
- No installation required. Use npx to get the latest version:
7
+ No installation required:
8
8
 
9
9
  ```bash
10
10
  npx stackkit@latest <command>
@@ -14,40 +14,43 @@ npx stackkit@latest <command>
14
14
 
15
15
  ### create
16
16
 
17
- Generate a new project:
17
+ Scaffold a new project:
18
18
 
19
19
  ```bash
20
- # Interactive mode
20
+ # Interactive — follow the prompts
21
21
  npx stackkit@latest create my-app
22
22
 
23
- # With options
23
+ # With flags — skip the prompts
24
24
  npx stackkit@latest create my-app \
25
25
  --framework nextjs \
26
26
  --database prisma-postgresql \
27
- --auth better-auth \
28
- --language typescript
27
+ --auth better-auth
29
28
  ```
30
29
 
31
30
  **Options:**
32
31
 
33
- - `--framework, -f` - nextjs, express, react
34
- - `--database, -d` - prisma-postgresql, prisma-mysql, prisma-sqlite, prisma-mongodb, mongoose, none
35
- - `--auth, -a` - better-auth, authjs, none
36
- - `--language, -l` - typescript, javascript
37
- - `--package-manager, -p` - pnpm, npm, yarn, bun
38
- - `--yes, -y` - Use defaults
39
- - `--skip-install` - Don't install dependencies
40
- - `--no-git` - Don't initialize git
32
+ | Flag | Values |
33
+ | ----------------------- | ------------------------------------------------------------------------------------------ |
34
+ | `--framework, -f` | `nextjs`, `express`, `react` |
35
+ | `--database, -d` | `prisma-postgresql`, `prisma-mysql`, `prisma-sqlite`, `prisma-mongodb`, `mongoose`, `none` |
36
+ | `--auth, -a` | `better-auth`, `none` |
37
+ | `--ui, -u` | `shadcn` |
38
+ | `--storage-provider` | `cloudinary` |
39
+ | `--language, -l` | `typescript`, `javascript` |
40
+ | `--package-manager, -p` | `pnpm`, `npm`, `yarn`, `bun` |
41
+ | `--yes, -y` | Use defaults, skip prompts |
42
+ | `--skip-install` | Skip dependency installation |
43
+ | `--no-git` | Skip git initialization |
41
44
 
42
45
  ### add
43
46
 
44
- Add features to existing project:
47
+ Add a module to an existing project:
45
48
 
46
49
  ```bash
47
50
  npx stackkit@latest add
48
51
  ```
49
52
 
50
- Interactively select and install modules.
53
+ Interactively select and install modules (database, auth, ui, storage, components).
51
54
 
52
55
  ### doctor
53
56
 
@@ -61,52 +64,57 @@ npx stackkit@latest doctor --verbose
61
64
 
62
65
  # JSON output (for CI/CD)
63
66
  npx stackkit@latest doctor --json
67
+
68
+ # Treat warnings as errors
69
+ npx stackkit@latest doctor --strict
64
70
  ```
65
71
 
66
72
  ### list
67
73
 
68
- Show available options:
74
+ Show available frameworks and modules:
69
75
 
70
76
  ```bash
71
77
  npx stackkit@latest list
78
+ npx stackkit@latest list --frameworks
79
+ npx stackkit@latest list --modules
72
80
  ```
73
81
 
74
- ## Supported Technologies
75
-
76
- **Frameworks:**
77
-
78
- - Next.js (App Router)
79
- - Express (TypeScript API)
80
- - React (Vite SPA)
81
-
82
- **Databases:**
83
-
84
- - Prisma (PostgreSQL, MySQL, SQLite, MongoDB)
85
- - Mongoose (MongoDB)
82
+ ## Supported stack
86
83
 
87
- **Authentication:**
88
-
89
- - Better Auth (All frameworks)
90
- - Auth.js (Next.js only)
84
+ | Category | Options |
85
+ | -------------- | -------------------------------------------------------- |
86
+ | Frameworks | Next.js (App Router), Express (TypeScript), React (Vite) |
87
+ | Databases | Prisma (PostgreSQL, MySQL, SQLite, MongoDB), Mongoose |
88
+ | Authentication | Better Auth (all frameworks) |
89
+ | UI | Shadcn UI (Next.js, React) |
90
+ | Storage | Cloudinary (Express) |
91
+ | Components | TiptapEditor, DataTable, SearchBar, FilterBar, and more |
91
92
 
92
93
  ## Examples
93
94
 
94
95
  ```bash
95
96
  # Full-stack Next.js
96
- npx stackkit@latest create my-app --framework nextjs --database prisma-postgresql --auth better-auth
97
+ npx stackkit@latest create my-app \
98
+ --framework nextjs \
99
+ --database prisma-postgresql \
100
+ --auth better-auth
97
101
 
98
- # Express API
99
- npx stackkit@latest create my-api --framework express --database mongoose
102
+ # Express API with MongoDB
103
+ npx stackkit@latest create my-api \
104
+ --framework express \
105
+ --database mongoose
100
106
 
101
- # React frontend
102
- npx stackkit@latest create my-spa --framework react --auth better-auth
107
+ # React SPA with auth
108
+ npx stackkit@latest create my-spa \
109
+ --framework react \
110
+ --auth better-auth
103
111
  ```
104
112
 
105
113
  ## Links
106
114
 
107
- - **Documentation**: https://stackkit.tariqul.dev
108
- - **GitHub**: https://github.com/tariqul420/stackkit
109
- - **Issues**: https://github.com/tariqul420/stackkit/issues
115
+ - [Documentation](https://stackkit.tariqul.dev)
116
+ - [GitHub](https://github.com/tariqul420/stackkit)
117
+ - [Issues](https://github.com/tariqul420/stackkit/issues)
110
118
 
111
119
  ## License
112
120
 
package/dist/cli/add.js CHANGED
@@ -7,8 +7,8 @@ exports.addCommand = addCommand;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const child_process_1 = require("child_process");
9
9
  const fs_extra_1 = __importDefault(require("fs-extra"));
10
- const inquirer_1 = __importDefault(require("inquirer"));
11
10
  const path_1 = __importDefault(require("path"));
11
+ const prompts_1 = __importDefault(require("prompts"));
12
12
  const module_discovery_1 = require("../lib/discovery/module-discovery");
13
13
  const shared_1 = require("../lib/discovery/shared");
14
14
  const env_editor_1 = require("../lib/env/env-editor");
@@ -122,26 +122,33 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
122
122
  if (compatibleAuths.length > 0) {
123
123
  categories.push({ name: "Auth", value: "auth" });
124
124
  }
125
- const answers = await inquirer_1.default.prompt([
126
- {
127
- type: "list",
128
- name: "category",
129
- message: "What would you like to add?",
130
- choices: categories,
131
- },
132
- ]);
133
- const category = answers.category;
125
+ if (["react", "nextjs"].includes(projectInfo?.framework || defaultFramework)) {
126
+ const fw = projectInfo?.framework || defaultFramework;
127
+ const availableComponents = (discovered.components || []).filter((c) => !c.supportedFrameworks || c.supportedFrameworks.includes(fw));
128
+ if (availableComponents.length > 0) {
129
+ categories.push({ name: "Components", value: "components" });
130
+ }
131
+ }
132
+ const categoryResp = await (0, prompts_1.default)({
133
+ type: "select",
134
+ name: "category",
135
+ message: "What would you like to add?",
136
+ choices: categories.map((c) => ({ title: c.name, value: c.value })),
137
+ });
138
+ const category = categoryResp.category;
134
139
  if (category === "database") {
135
140
  const dbChoices = (0, module_discovery_1.getDatabaseChoices)(discovered.databases || [], projectInfo?.framework || defaultFramework);
136
- const dbAnswers = await inquirer_1.default.prompt([
137
- {
138
- type: "list",
139
- name: "database",
140
- message: "Select database:",
141
- choices: dbChoices,
142
- },
143
- ]);
144
- const selectedDb = dbAnswers.database;
141
+ const dbChoicesNormalized = dbChoices.map((c) => ({
142
+ title: c.name || c.title || String(c.value ?? ""),
143
+ value: c.value ?? String(c.title ?? ""),
144
+ }));
145
+ const dbResp = await (0, prompts_1.default)({
146
+ type: "select",
147
+ name: "database",
148
+ message: "Select database:",
149
+ choices: dbChoicesNormalized,
150
+ });
151
+ const selectedDb = dbResp.database;
145
152
  if (selectedDb.startsWith("prisma-")) {
146
153
  const provider = selectedDb.split("-")[1];
147
154
  return {
@@ -166,15 +173,17 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
166
173
  if (!projectInfo?.hasDatabase) {
167
174
  logger_1.logger.warn("No database detected in the project. Authentication requires a database.");
168
175
  const dbChoices = (0, module_discovery_1.getDatabaseChoices)(discovered.databases || [], projectInfo?.framework || defaultFramework);
169
- const dbAnswer = await inquirer_1.default.prompt([
170
- {
171
- type: "list",
172
- name: "database",
173
- message: "Select a database to add before authentication:",
174
- choices: dbChoices,
175
- },
176
- ]);
177
- const selectedDb = dbAnswer.database;
176
+ const dbChoicesNormalized2 = dbChoices.map((c) => ({
177
+ title: c.name || c.title || String(c.value ?? ""),
178
+ value: c.value ?? String(c.title ?? ""),
179
+ }));
180
+ const dbAnswerResp = await (0, prompts_1.default)({
181
+ type: "select",
182
+ name: "database",
183
+ message: "Select a database to add before authentication:",
184
+ choices: dbChoicesNormalized2,
185
+ });
186
+ const selectedDb = dbAnswerResp.database;
178
187
  if (!selectedDb || selectedDb === "none") {
179
188
  logger_1.logger.info("Cancelled — authentication requires a database");
180
189
  process.exit(0);
@@ -207,15 +216,21 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
207
216
  }
208
217
  const dbString = projectInfo?.hasPrisma ? "prisma" : "none";
209
218
  const authChoices = (0, module_discovery_1.getCompatibleAuthOptions)(discovered.auth || [], projectInfo?.framework || defaultFramework, dbString);
210
- const authAnswers = await inquirer_1.default.prompt([
211
- {
212
- type: "list",
213
- name: "auth",
214
- message: "Select authentication:",
215
- choices: authChoices,
216
- },
217
- ]);
218
- const selectedAuth = authAnswers.auth;
219
+ const authChoicesNormalized = authChoices.map((c) => ({
220
+ title: c.name
221
+ ? c.description
222
+ ? `${c.name} — ${c.description}`
223
+ : c.name
224
+ : String(c.value ?? ""),
225
+ value: c.value ?? String(c.name ?? ""),
226
+ }));
227
+ const authResp = await (0, prompts_1.default)({
228
+ type: "select",
229
+ name: "auth",
230
+ message: "Select authentication:",
231
+ choices: authChoicesNormalized,
232
+ });
233
+ const selectedAuth = authResp.auth;
219
234
  if (selectedAuth === "none") {
220
235
  logger_1.logger.info("Cancelled");
221
236
  process.exit(0);
@@ -240,6 +255,35 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
240
255
  }
241
256
  return result;
242
257
  }
258
+ else if (category === "components") {
259
+ const fw = projectInfo?.framework || defaultFramework;
260
+ const compMeta = (discovered.components || []).find((c) => !c.supportedFrameworks || c.supportedFrameworks.includes(fw));
261
+ if (!compMeta) {
262
+ logger_1.logger.info("No components available for this framework");
263
+ process.exit(0);
264
+ }
265
+ const compResp = await (0, prompts_1.default)({
266
+ type: "confirm",
267
+ name: "add",
268
+ message: `Add ${compMeta.displayName || compMeta.name}?${compMeta.description ? ` (${compMeta.description})` : ""}`,
269
+ initial: true,
270
+ });
271
+ if (compResp.add === false) {
272
+ logger_1.logger.info("No components selected");
273
+ process.exit(0);
274
+ }
275
+ const meta = await loadModuleMetadata(modulesDir, "components", "components");
276
+ if (!meta) {
277
+ logger_1.logger.error("Failed to load components module metadata");
278
+ process.exit(1);
279
+ }
280
+ return {
281
+ module: "components",
282
+ provider: "components",
283
+ displayName: meta.displayName || "Components",
284
+ metadata: meta,
285
+ };
286
+ }
243
287
  throw new Error("Invalid selection");
244
288
  }
245
289
  async function addModuleToProject(projectRoot, projectInfo, config, options) {
@@ -247,14 +291,12 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
247
291
  const selectedProvider = config.provider;
248
292
  if (config.module === "auth" && projectInfo.hasAuth && !options?.force) {
249
293
  logger_1.logger.warn("Auth library already detected in this project");
250
- const { proceed } = await inquirer_1.default.prompt([
251
- {
252
- type: "confirm",
253
- name: "proceed",
254
- message: "Continue anyway? (use --force to skip this prompt)",
255
- default: false,
256
- },
257
- ]);
294
+ const { proceed } = await (0, prompts_1.default)({
295
+ type: "confirm",
296
+ name: "proceed",
297
+ message: "Continue anyway? (use --force to skip this prompt)",
298
+ initial: false,
299
+ });
258
300
  if (!proceed) {
259
301
  logger_1.logger.info("Cancelled");
260
302
  return;
@@ -262,14 +304,12 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
262
304
  }
263
305
  if (config.module === "database" && projectInfo.hasDatabase && !options?.force) {
264
306
  logger_1.logger.warn("Database library already detected in this project");
265
- const { proceed } = await inquirer_1.default.prompt([
266
- {
267
- type: "confirm",
268
- name: "proceed",
269
- message: "Continue anyway? (use --force to skip this prompt)",
270
- default: false,
271
- },
272
- ]);
307
+ const { proceed } = await (0, prompts_1.default)({
308
+ type: "confirm",
309
+ name: "proceed",
310
+ message: "Continue anyway? (use --force to skip this prompt)",
311
+ initial: false,
312
+ });
273
313
  if (!proceed) {
274
314
  logger_1.logger.info("Cancelled");
275
315
  return;
@@ -287,7 +327,8 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
287
327
  const moduleName = path_1.default.basename(moduleBasePath);
288
328
  const available = gen.getAvailableGenerators();
289
329
  const alreadyRegistered = (config.module === "database" && available.databases.includes(moduleName)) ||
290
- (config.module === "auth" && available.auths.includes(moduleName));
330
+ (config.module === "auth" && available.auths.includes(moduleName)) ||
331
+ (config.module === "components" && available.components.length > 0);
291
332
  if (!alreadyRegistered) {
292
333
  const ops = [];
293
334
  if (Array.isArray(moduleMetadata.patches)) {
@@ -346,6 +387,9 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
346
387
  if (config.module === "auth" && config.provider) {
347
388
  selectedModules.auth = config.provider;
348
389
  }
390
+ else if (config.module === "components") {
391
+ selectedModules.components = true;
392
+ }
349
393
  const postInstall = await gen.applyToProject(selectedModules, [], projectRoot);
350
394
  if (!options?.dryRun && options?.install !== false) {
351
395
  const installSpinner = logger_1.logger.startSpinner("Installing dependencies...");
@@ -367,7 +411,7 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
367
411
  const postInstallSpinner = logger_1.logger.startSpinner("Running post-install commands...");
368
412
  try {
369
413
  for (const command of postInstall) {
370
- (0, child_process_1.execSync)(command, { cwd: projectRoot, stdio: "pipe" });
414
+ (0, child_process_1.execSync)(command, { cwd: projectRoot, stdio: "inherit" });
371
415
  }
372
416
  postInstallSpinner.succeed("Post-install commands completed");
373
417
  }
@@ -447,7 +491,7 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
447
491
  const postInstallSpinner = logger_1.logger.startSpinner("Running post-install commands...");
448
492
  try {
449
493
  for (const command of moduleMetadata.postInstall) {
450
- (0, child_process_1.execSync)(command, { cwd: projectRoot, stdio: "pipe" });
494
+ (0, child_process_1.execSync)(command, { cwd: projectRoot, stdio: "inherit" });
451
495
  }
452
496
  postInstallSpinner.succeed("Post-install commands completed");
453
497
  }
@@ -533,6 +577,17 @@ async function loadModuleMetadata(modulesDir, moduleName, provider) {
533
577
  }
534
578
  }
535
579
  }
580
+ // Check flat module (e.g., modules/components/module.json)
581
+ const flatMetaPath = path_1.default.join(categoryPath, "module.json");
582
+ if (await fs_extra_1.default.pathExists(flatMetaPath)) {
583
+ const metadata = await fs_extra_1.default.readJSON(flatMetaPath);
584
+ if (provider && category === provider) {
585
+ return metadata;
586
+ }
587
+ if (!provider && (metadata.category === moduleName || category === moduleName)) {
588
+ return metadata;
589
+ }
590
+ }
536
591
  }
537
592
  return null;
538
593
  }
@@ -605,6 +660,17 @@ async function findModulePath(modulesDir, moduleName, provider) {
605
660
  }
606
661
  }
607
662
  }
663
+ // Check flat module (e.g., modules/components/)
664
+ const flatMetaPath = path_1.default.join(categoryPath, "module.json");
665
+ if (await fs_extra_1.default.pathExists(flatMetaPath)) {
666
+ const metadata = await fs_extra_1.default.readJSON(flatMetaPath);
667
+ if (provider && category === provider) {
668
+ return categoryPath;
669
+ }
670
+ if (!provider && metadata.name === moduleName) {
671
+ return categoryPath;
672
+ }
673
+ }
608
674
  }
609
675
  return null;
610
676
  }
@@ -17,6 +17,8 @@ interface CliOptions {
17
17
  noGit?: boolean;
18
18
  yes?: boolean;
19
19
  y?: boolean;
20
+ ui?: string;
21
+ storageProvider?: string;
20
22
  }
21
23
  export declare function createProject(projectName?: string, options?: CliOptions): Promise<void>;
22
24
  export {};