stackkit 0.3.5 → 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.
- package/README.md +50 -42
- package/dist/cli/add.js +122 -56
- package/dist/cli/create.d.ts +2 -0
- package/dist/cli/create.js +271 -95
- package/dist/cli/doctor.js +1 -0
- package/dist/cli/list.d.ts +1 -1
- package/dist/cli/list.js +6 -4
- package/dist/index.js +234 -191
- package/dist/lib/constants.d.ts +4 -0
- package/dist/lib/constants.js +4 -0
- package/dist/lib/discovery/module-discovery.d.ts +4 -0
- package/dist/lib/discovery/module-discovery.js +56 -0
- package/dist/lib/generation/code-generator.d.ts +11 -2
- package/dist/lib/generation/code-generator.js +42 -3
- package/dist/lib/generation/generator-utils.js +3 -1
- package/dist/lib/pm/package-manager.js +16 -13
- package/dist/lib/ui/logger.js +3 -2
- package/dist/lib/utils/path-resolver.d.ts +2 -0
- package/dist/lib/utils/path-resolver.js +8 -0
- package/dist/meta.json +8312 -0
- package/modules/auth/better-auth/files/{shared → express}/config/env.ts +48 -50
- package/modules/auth/better-auth/files/express/middlewares/authorize.ts +20 -1
- package/modules/auth/better-auth/files/express/modules/auth.controller.ts +349 -0
- package/modules/auth/better-auth/files/express/modules/{auth/auth.route.ts → auth.route.ts} +9 -4
- package/modules/auth/better-auth/files/express/modules/auth.service.ts +664 -0
- package/modules/auth/better-auth/files/express/modules/{auth/auth.type.ts → auth.type.ts} +22 -9
- package/modules/auth/better-auth/files/{shared/mongoose/auth/helper.ts → express/mongo-modules/auth.helper.ts} +11 -1
- package/modules/auth/better-auth/files/express/types/express.d.ts +11 -0
- package/modules/auth/better-auth/files/nextjs/api-route.ts +74 -0
- package/modules/auth/better-auth/files/nextjs/dashboard/pages/(user)/page.tsx +6 -0
- package/modules/auth/better-auth/files/nextjs/dashboard/pages/admin/page.tsx +6 -0
- package/modules/auth/better-auth/files/nextjs/dashboard/pages/layout.tsx +48 -0
- package/modules/auth/better-auth/files/nextjs/dashboard/pages/my-profile/page.tsx +5 -0
- package/modules/auth/better-auth/files/nextjs/features/services/auth.service.ts +102 -0
- package/modules/auth/better-auth/files/nextjs/layout/layout.tsx +13 -0
- package/modules/auth/better-auth/files/nextjs/lib/axios/http.ts +158 -0
- package/modules/auth/better-auth/files/nextjs/lib/env.ts +35 -0
- package/modules/auth/better-auth/files/nextjs/lib/utils/auth.ts +75 -0
- package/modules/auth/better-auth/files/nextjs/lib/utils/cookie.ts +29 -0
- package/modules/auth/better-auth/files/nextjs/lib/utils/jwt.ts +28 -0
- package/modules/auth/better-auth/files/nextjs/lib/utils/token.ts +49 -0
- package/modules/auth/better-auth/files/nextjs/pages/forgot-password/page.tsx +5 -0
- package/modules/auth/better-auth/files/nextjs/pages/layout.tsx +11 -0
- package/modules/auth/better-auth/files/nextjs/pages/login/page.tsx +9 -0
- package/modules/auth/better-auth/files/nextjs/pages/register/page.tsx +5 -0
- package/modules/auth/better-auth/files/nextjs/pages/reset-password/page.tsx +10 -0
- package/modules/auth/better-auth/files/nextjs/pages/verify-email/page.tsx +10 -0
- package/modules/auth/better-auth/files/nextjs/proxy.ts +154 -42
- package/modules/auth/better-auth/files/nextjs/theme/providers/theme-provider.tsx +11 -0
- package/modules/auth/better-auth/files/nextjs/types/api.types.ts +18 -0
- package/modules/auth/better-auth/files/react/components/protected-route.tsx +39 -0
- package/modules/auth/better-auth/files/react/components/route-guards.tsx +13 -0
- package/modules/auth/better-auth/files/react/dashboard/admin/pages/overview.tsx +3 -0
- package/modules/auth/better-auth/files/react/dashboard/pages/overview.tsx +3 -0
- package/modules/auth/better-auth/files/react/features/pages/forgot-password.tsx +5 -0
- package/modules/auth/better-auth/files/react/features/pages/login.tsx +5 -0
- package/modules/auth/better-auth/files/react/features/pages/my-profile.tsx +5 -0
- package/modules/auth/better-auth/files/react/features/pages/oauth-callback.tsx +59 -0
- package/modules/auth/better-auth/files/react/features/pages/register.tsx +5 -0
- package/modules/auth/better-auth/files/react/features/pages/reset-password.tsx +10 -0
- package/modules/auth/better-auth/files/react/features/pages/verify-email.tsx +10 -0
- package/modules/auth/better-auth/files/react/layout/dashboard-layout.tsx +54 -0
- package/modules/auth/better-auth/files/react/lib/axios/http.ts +68 -0
- package/modules/auth/better-auth/files/react/lib/env.ts +25 -0
- package/modules/auth/better-auth/files/react/router.tsx +73 -0
- package/modules/auth/better-auth/files/react/theme/components/providers/theme-provider-context.ts +13 -0
- package/modules/auth/better-auth/files/react/theme/components/providers/theme-provider.tsx +51 -0
- package/modules/auth/better-auth/files/react/theme/hooks/use-theme.ts +8 -0
- package/modules/auth/better-auth/files/shared/features/components/change-password-dialog.tsx +113 -0
- package/modules/auth/better-auth/files/shared/features/components/forgot-password-form.tsx +84 -0
- package/modules/auth/better-auth/files/shared/features/components/login-form.tsx +134 -0
- package/modules/auth/better-auth/files/shared/features/components/my-profile.tsx +147 -0
- package/modules/auth/better-auth/files/shared/features/components/profile-form.tsx +205 -0
- package/modules/auth/better-auth/files/shared/features/components/register-form.tsx +100 -0
- package/modules/auth/better-auth/files/shared/features/components/reset-password-form.tsx +111 -0
- package/modules/auth/better-auth/files/shared/features/components/social-login-buttons.tsx +47 -0
- package/modules/auth/better-auth/files/shared/features/components/user-profile-menu.tsx +106 -0
- package/modules/auth/better-auth/files/shared/features/components/verify-email-form.tsx +110 -0
- package/modules/auth/better-auth/files/shared/features/queries/auth.mutations.tsx +312 -0
- package/modules/auth/better-auth/files/shared/features/queries/auth.querie.ts +19 -0
- package/modules/auth/better-auth/files/shared/features/services/auth.api.ts +81 -0
- package/modules/auth/better-auth/files/shared/features/types/auth.type.ts +47 -0
- package/modules/auth/better-auth/files/shared/features/validators/change-password.validator.ts +18 -0
- package/modules/auth/better-auth/files/shared/features/validators/forgot.validator.ts +7 -0
- package/modules/auth/better-auth/files/shared/features/validators/login.validator.ts +14 -0
- package/modules/auth/better-auth/files/shared/features/validators/profile.validator.ts +8 -0
- package/modules/auth/better-auth/files/shared/features/validators/register.validator.ts +9 -0
- package/modules/auth/better-auth/files/shared/features/validators/reset.validator.ts +9 -0
- package/modules/auth/better-auth/files/shared/features/validators/verify.validator.ts +8 -0
- package/modules/auth/better-auth/files/shared/lib/auth-client.ts +2 -1
- package/modules/auth/better-auth/files/shared/lib/auth.ts +5 -19
- package/modules/auth/better-auth/files/shared/lib/constant/dashboard.ts +90 -0
- package/modules/auth/better-auth/files/shared/theme/mode-toggle.tsx +30 -0
- package/modules/auth/better-auth/files/shared/ui/shadcn/components/dashboard/dashboard-header.tsx +94 -0
- package/modules/auth/better-auth/files/shared/ui/shadcn/components/dashboard/dashboard-sidebar.tsx +255 -0
- package/modules/auth/better-auth/files/shared/ui/shadcn/components/footer.tsx +35 -0
- package/modules/auth/better-auth/files/shared/ui/shadcn/components/navbar.tsx +145 -0
- package/modules/auth/better-auth/files/shared/ui/shadcn/form-field/input-field.tsx +440 -0
- package/modules/auth/better-auth/files/shared/utils/email.ts +2 -17
- package/modules/auth/better-auth/generator.json +172 -51
- package/modules/auth/better-auth/module.json +2 -2
- package/modules/components/files/shared/hooks/use-file-upload.ts +412 -0
- package/modules/components/files/shared/lib/utils/url-helpers.ts +110 -0
- package/modules/components/files/shared/shadcn/dashboard/data-table-column-selector.tsx +52 -0
- package/modules/components/files/shared/shadcn/dashboard/data-table-footer.tsx +156 -0
- package/modules/components/files/shared/shadcn/dashboard/data-table.tsx +405 -0
- package/modules/components/files/shared/shadcn/global/form-field/input-field.tsx +440 -0
- package/modules/components/files/shared/shadcn/global/form-field/media-uploader-field.tsx +745 -0
- package/modules/components/files/shared/shadcn/global/form-field/multi-select-field.tsx +207 -0
- package/modules/components/files/shared/shadcn/global/form-field/select-field.tsx +247 -0
- package/modules/components/files/shared/shadcn/global/form-field/textarea-field.tsx +277 -0
- package/modules/components/files/shared/shadcn/global/form-field/tiptap-editor-field.tsx +35 -0
- package/modules/components/files/shared/shadcn/global/no-results.tsx +41 -0
- package/modules/components/files/shared/shadcn/tiptap-editor/editor-menu-bar.tsx +217 -0
- package/modules/components/files/shared/shadcn/tiptap-editor/tiptap-editor.tsx +104 -0
- package/modules/components/files/shared/url/load-more.tsx +93 -0
- package/modules/components/files/shared/url/search-bar.tsx +131 -0
- package/modules/components/files/shared/url/sort-select.tsx +118 -0
- package/modules/components/files/shared/url/url-tabs.tsx +77 -0
- package/modules/components/generator.json +109 -0
- package/modules/components/module.json +11 -0
- package/modules/database/mongoose/generator.json +3 -14
- package/modules/database/mongoose/module.json +2 -2
- package/modules/database/prisma/generator.json +6 -12
- package/modules/database/prisma/module.json +2 -2
- package/modules/storage/cloudinary/files/express/config/env.ts +65 -0
- package/modules/storage/cloudinary/files/express/config/media.ts +103 -0
- package/modules/storage/cloudinary/files/express/modules/media/media.controller.ts +59 -0
- package/modules/storage/cloudinary/files/express/modules/media/media.route.ts +29 -0
- package/modules/storage/cloudinary/files/express/modules/media/media.service.ts +113 -0
- package/modules/storage/cloudinary/files/express/modules/media/media.type.ts +32 -0
- package/modules/storage/cloudinary/generator.json +34 -0
- package/modules/storage/cloudinary/module.json +11 -0
- package/modules/ui/shadcn/generator.json +21 -0
- package/modules/ui/shadcn/module.json +11 -0
- package/package.json +24 -26
- package/templates/express/README.md +11 -16
- package/templates/express/src/config/env.ts +7 -5
- package/templates/nextjs/README.md +13 -18
- package/templates/nextjs/app/favicon.ico +0 -0
- package/templates/nextjs/app/layout.tsx +6 -4
- package/templates/nextjs/components/providers/query-provider.tsx +3 -0
- package/templates/nextjs/env.example +3 -1
- package/templates/nextjs/lib/axios/http.ts +23 -0
- package/templates/nextjs/lib/env.ts +7 -5
- package/templates/nextjs/package.json +2 -1
- package/templates/nextjs/template.json +1 -2
- package/templates/react/README.md +9 -14
- package/templates/react/index.html +1 -1
- package/templates/react/package.json +1 -1
- package/templates/react/src/assets/favicon.ico +0 -0
- package/templates/react/src/components/providers/query-provider.tsx +38 -0
- package/templates/react/src/{shared/components → components}/seo.tsx +4 -8
- package/templates/react/src/lib/axios/http.ts +24 -0
- package/templates/react/src/main.tsx +8 -11
- package/templates/react/src/{features/about/pages → pages}/about.tsx +1 -1
- package/templates/react/src/{features/home/pages → pages}/home.tsx +1 -1
- package/templates/react/src/router.tsx +6 -6
- package/templates/react/src/vite-env.d.ts +2 -1
- package/templates/react/template.json +0 -1
- package/templates/react/tsconfig.app.json +6 -0
- package/templates/react/tsconfig.json +7 -1
- package/templates/react/vite.config.ts +12 -0
- package/modules/auth/authjs/files/nextjs/api/auth/[...nextauth]/route.ts +0 -3
- package/modules/auth/authjs/files/nextjs/proxy.ts +0 -1
- package/modules/auth/authjs/files/shared/lib/auth.ts +0 -119
- package/modules/auth/authjs/files/shared/prisma/schema.prisma +0 -61
- package/modules/auth/authjs/generator.json +0 -64
- package/modules/auth/authjs/module.json +0 -13
- package/modules/auth/better-auth/files/express/modules/auth/auth.controller.ts +0 -264
- package/modules/auth/better-auth/files/express/modules/auth/auth.service.ts +0 -549
- package/modules/auth/better-auth/files/express/templates/google-redirect.ejs +0 -24
- package/modules/auth/better-auth/files/nextjs/api/auth/[...all]/route.ts +0 -4
- package/modules/auth/better-auth/files/nextjs/lib/auth/auth-guards.ts +0 -31
- package/modules/auth/better-auth/files/nextjs/templates/email-otp.tsx +0 -74
- package/templates/nextjs/lib/api/http.ts +0 -40
- package/templates/react/public/vite.svg +0 -1
- package/templates/react/src/app/layouts/dashboard-layout.tsx +0 -8
- package/templates/react/src/app/layouts/public-layout.tsx +0 -5
- package/templates/react/src/app/providers.tsx +0 -20
- package/templates/react/src/app/router.tsx +0 -21
- package/templates/react/src/assets/react.svg +0 -1
- package/templates/react/src/shared/api/http.ts +0 -39
- package/templates/react/src/shared/components/loading.tsx +0 -8
- package/templates/react/src/shared/lib/query-client.ts +0 -12
- package/templates/react/src/utils/storage.ts +0 -35
- package/templates/react/src/utils/utils.ts +0 -3
- /package/modules/auth/better-auth/files/{shared/mongoose/auth/constants.ts → express/mongo-modules/auth.constants.ts} +0 -0
- /package/templates/nextjs/app/{page.tsx → (public)/(root)/page.tsx} +0 -0
- /package/templates/react/src/{shared/components → components}/error-boundary.tsx +0 -0
- /package/templates/react/src/{shared/components → components}/layout.tsx +0 -0
- /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
|
-
##
|
|
5
|
+
## Usage
|
|
6
6
|
|
|
7
|
-
No installation required
|
|
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
|
-
|
|
17
|
+
Scaffold a new project:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
# Interactive
|
|
20
|
+
# Interactive — follow the prompts
|
|
21
21
|
npx stackkit@latest create my-app
|
|
22
22
|
|
|
23
|
-
# With
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
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
|
|
102
|
+
# Express API with MongoDB
|
|
103
|
+
npx stackkit@latest create my-api \
|
|
104
|
+
--framework express \
|
|
105
|
+
--database mongoose
|
|
100
106
|
|
|
101
|
-
# React
|
|
102
|
-
npx stackkit@latest create my-spa
|
|
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
|
-
-
|
|
108
|
-
-
|
|
109
|
-
-
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const
|
|
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
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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: "
|
|
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: "
|
|
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
|
}
|
package/dist/cli/create.d.ts
CHANGED