create-arkos 2.0.0-next.15 → 2.0.0-next.17
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 +177 -149
- package/dist/utils/project-config-inquirer.js +45 -31
- package/dist/utils/project-config-inquirer.js.map +1 -1
- package/dist/utils/template-compiler.js +3 -4
- package/dist/utils/template-compiler.js.map +1 -1
- package/package.json +1 -1
- package/templates/basic/.env.hbs +1 -5
- package/templates/basic/README.md.hbs +2 -4
- package/templates/basic/arkos.config.ts.hbs +4 -14
- package/templates/basic/package.json.hbs +8 -7
- package/templates/basic/prisma/schema/__tests__/user-role.prisma.hbs.test.ts +1 -1
- package/templates/basic/prisma/schema/__tests__/user.prisma.hbs.test.ts +2 -2
- package/templates/basic/prisma/schema/user.prisma.hbs +1 -1
- package/templates/basic/src/modules/auth-permission/dtos/create-auth-permission.dto.ts.hbs +1 -5
- package/templates/basic/src/modules/auth-permission/dtos/update-auth-permission.dto.ts.hbs +6 -4
- package/templates/basic/src/modules/auth-role/dtos/create-auth-role.dto.ts.hbs +2 -7
- package/templates/basic/src/modules/auth-role/dtos/update-auth-role.dto.ts.hbs +1 -5
- package/templates/basic/src/utils/validation/api-actions.ts.hbs +1 -1
package/README.md
CHANGED
|
@@ -1,237 +1,265 @@
|
|
|
1
|
-
|
|
1
|
+

|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
](https://badge.socket.dev/npm/package/arkos)
|
|
6
|
+

|
|
7
|
+

|
|
7
8
|

|
|
9
|
+

|
|
8
10
|
|
|
9
11
|
</div>
|
|
10
12
|
|
|
11
13
|
<div align="center">
|
|
12
|
-
<h2>
|
|
13
|
-
<p>
|
|
14
|
+
<h2>The Express & Prisma RESTful Framework</h2>
|
|
15
|
+
<p>A tool for backend developers and teams who ship software with complex business logic under tight deadlines</p>
|
|
14
16
|
</div>
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
## Why create-arkos?
|
|
19
|
-
|
|
20
|
-
Skip the hours of boilerplate setup. Get a production-ready API with authentication, validation, and auto-generated docs in **under 5 minutes**.
|
|
18
|
+
<div align="center">
|
|
21
19
|
|
|
22
|
-
**
|
|
20
|
+
**[Installation](https://www.arkosjs.com/docs/getting-started/installation)** •
|
|
21
|
+
**[Documentation](https://arkosjs.com/docs)** •
|
|
22
|
+
**[Website](https://arkosjs.com)** •
|
|
23
|
+
**[Tutorial](https://arkosjs.com/learn)** •
|
|
24
|
+
**[GitHub](https://github.com/uanela/arkos)** •
|
|
25
|
+
**[Blog](https://www.arkosjs.com/blog)** •
|
|
26
|
+
**[Npm](https://www.npmjs.com/package/arkos)**
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
- Prototyping APIs that need to scale later
|
|
26
|
-
- Teams who want consistent project structure from day one
|
|
28
|
+
</div>
|
|
27
29
|
|
|
28
30
|
## Quick Start
|
|
29
31
|
|
|
30
32
|
```bash
|
|
31
|
-
# Using pnpm (recommended)
|
|
32
|
-
pnpm create arkos@latest my-project
|
|
33
|
-
|
|
34
|
-
# Using npm
|
|
35
33
|
npm create arkos@latest my-project
|
|
36
|
-
|
|
37
|
-
# Using yarn
|
|
38
|
-
yarn create arkos@latest my-project
|
|
39
34
|
```
|
|
40
35
|
|
|
41
|
-
|
|
36
|
+
Your new project already has JWT auth, customizable CRUD routes, Swagger docs at `/api/docs`, file uploads, validation, and a full security middleware stack. Understand the generated [Project Structure](https://www.arkosjs.com/docs/getting-started/project-structure).
|
|
42
37
|
|
|
43
|
-
##
|
|
38
|
+
## Your Entry Point
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
✅ **Input validation** (Zod or class-validator)
|
|
50
|
-
✅ **TypeScript support** (optional)
|
|
51
|
-
✅ **Best practices** and security middleware
|
|
40
|
+
```typescript
|
|
41
|
+
// src/app.ts
|
|
42
|
+
import arkos from "arkos";
|
|
43
|
+
import postRouter from "@/src/modules/post/post.router"; // custom router
|
|
52
44
|
|
|
53
|
-
|
|
45
|
+
const app = arkos();
|
|
54
46
|
|
|
55
|
-
|
|
47
|
+
app.use(postRouter);
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
? What is the name of your project? my-arkos-project
|
|
59
|
-
? Would you like to use TypeScript? Yes
|
|
60
|
-
? What db provider will be used for Prisma? mongodb
|
|
61
|
-
? Would you like to set up Validation? Yes
|
|
62
|
-
? Choose validation library: zod
|
|
63
|
-
? Would you like to set up Authentication? Yes
|
|
64
|
-
? Choose authentication type: dynamic
|
|
65
|
-
? Would you like to use authentication with Multiple Roles? Yes
|
|
66
|
-
? Choose default username field for login: email
|
|
49
|
+
app.listen();
|
|
67
50
|
```
|
|
68
51
|
|
|
69
|
-
|
|
52
|
+
Arkos replaces the Express `app` — but it _is_ Express under the hood. You can still use `app.use()`, custom middleware, and raw Express code wherever you need it.
|
|
70
53
|
|
|
71
|
-
|
|
54
|
+
## Automatic CRUD: One Model, Full REST Endpoints
|
|
72
55
|
|
|
73
|
-
|
|
74
|
-
- MongoDB
|
|
75
|
-
- MySQL
|
|
76
|
-
- SQLite (great for prototyping)
|
|
77
|
-
- SQL Server
|
|
78
|
-
- CockroachDB
|
|
56
|
+
**Define The Prisma model:**
|
|
79
57
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
58
|
+
```prisma
|
|
59
|
+
model Post {
|
|
60
|
+
id String @id @default(uuid())
|
|
61
|
+
title String
|
|
62
|
+
content String
|
|
63
|
+
authorId String
|
|
64
|
+
author User @relation(fields: [authorId], references: [id])
|
|
65
|
+
createdAt DateTime @default(now())
|
|
66
|
+
updatedAt DateTime @updatedAt
|
|
67
|
+
}
|
|
68
|
+
```
|
|
84
69
|
|
|
85
|
-
**
|
|
70
|
+
**Get a full REST API — instantly:**
|
|
86
71
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
72
|
+
```
|
|
73
|
+
POST /api/posts Create a post
|
|
74
|
+
GET /api/posts List all posts
|
|
75
|
+
GET /api/posts/:id Get a post
|
|
76
|
+
PATCH /api/posts/:id Update a post
|
|
77
|
+
DELETE /api/posts/:id Delete a post
|
|
78
|
+
```
|
|
90
79
|
|
|
91
|
-
|
|
80
|
+
Authenticated, validated, and documented. Zero boilerplate.
|
|
92
81
|
|
|
93
|
-
|
|
94
|
-
# 1. Create your project
|
|
95
|
-
pnpm create arkos@latest my-project
|
|
82
|
+
## Creating a Router Beyond Express
|
|
96
83
|
|
|
97
|
-
|
|
98
|
-
|
|
84
|
+
```typescript
|
|
85
|
+
// src/modules/post/post.router.ts
|
|
86
|
+
import { ArkosRouter } from "arkos";
|
|
87
|
+
import CreatePostSchema from "@/src/modules/post/schemas/create-post.schema";
|
|
88
|
+
import postService from "@/src/modules/post/post.service";
|
|
89
|
+
import postPolicy from "@/src/modules/post/post.policy"; // Authorization component
|
|
99
90
|
|
|
100
|
-
|
|
101
|
-
# Edit .env with your DATABASE_URL
|
|
91
|
+
const postRouter = ArkosRouter({ prefix: "/api/posts" });
|
|
102
92
|
|
|
103
|
-
|
|
104
|
-
|
|
93
|
+
postRouter.post(
|
|
94
|
+
{
|
|
95
|
+
path: "/", // auto registered into openapi
|
|
96
|
+
authentication: postPolicy.Create, // Authentication and authorization with RBAC
|
|
97
|
+
validation: { body: CreatePostSchema }, // auto documented into openapi requestBody
|
|
98
|
+
},
|
|
99
|
+
async (req, res) => {
|
|
100
|
+
const post = await postService.createOne(req.body); // no error handling need, arkos already handles it
|
|
101
|
+
res.json({ data: post });
|
|
102
|
+
}
|
|
103
|
+
);
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
npm run dev
|
|
105
|
+
export default postRouter;
|
|
108
106
|
```
|
|
109
107
|
|
|
110
|
-
|
|
108
|
+
See more about the enhanced express-based router (ArkosRouter) at [ArkosRouter Guide](https://www.arkosjs.com/docs/core-concepts/components/routers).
|
|
111
109
|
|
|
112
|
-
|
|
113
|
-
- Health check at `/api/health`
|
|
114
|
-
- Authentication endpoints ready to use
|
|
110
|
+
## Define Permissions Once, Guard Everywhere
|
|
115
111
|
|
|
116
|
-
|
|
112
|
+
```typescript
|
|
113
|
+
// src/modules/post/post.policy.ts
|
|
114
|
+
import { ArkosPolicy } from "arkos";
|
|
117
115
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
│ │ └── prisma/
|
|
125
|
-
│ │ └── index.ts # Prisma client
|
|
126
|
-
│ ├── app.ts # Main application
|
|
127
|
-
│ ├── arkos.config.ts # Framework configuration
|
|
128
|
-
│ └── server.ts # Server entry point
|
|
129
|
-
├── .env # Environment variables
|
|
130
|
-
├── .gitignore
|
|
131
|
-
├── package.json
|
|
132
|
-
└── tsconfig.json # TypeScript config (if selected)
|
|
116
|
+
const postPolicy: ArkosPolicy<"post"> = ArkosPolicy("post");
|
|
117
|
+
|
|
118
|
+
postPolicy.rule("Create", ["Writer", "Admin"]);
|
|
119
|
+
postPolicy.rule("View", ["Writer", "Admin", "User"]);
|
|
120
|
+
|
|
121
|
+
export default postPolicy;
|
|
133
122
|
```
|
|
134
123
|
|
|
135
|
-
|
|
124
|
+
Define who can do what, once, per resource. Arkos enforces it across every route that references the policy — no scattered middleware, no repeated role checks.
|
|
136
125
|
|
|
137
|
-
|
|
126
|
+
**Customize CRUD Routes just like normal router:**
|
|
138
127
|
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
|
|
128
|
+
```typescript
|
|
129
|
+
// src/modules/post/post.router.ts
|
|
130
|
+
import { ArkosRouter, RouteHook } from "arkos";
|
|
131
|
+
import postPolicy from "@/src/modules/post/post.policy";
|
|
132
|
+
import UpdatePostSchema from "@/src/modules/post/post.schema";
|
|
142
133
|
|
|
143
|
-
|
|
144
|
-
|
|
134
|
+
export const hook: RouteHook<"prisma"> = {
|
|
135
|
+
findMany: { authentication: false }, // Making GET /api/posts public
|
|
136
|
+
createOne: { authentication: postPolicy.Create },
|
|
137
|
+
updateOne: {
|
|
138
|
+
authentication: postPolicy.Update,
|
|
139
|
+
validation: { body: UpdatePostSchema },
|
|
140
|
+
},
|
|
141
|
+
deleteOne: { authentication: postPolicy.Delete },
|
|
142
|
+
};
|
|
145
143
|
|
|
146
|
-
|
|
147
|
-
DATABASE_URL="mysql://username:password@localhost:3306/mydb"
|
|
144
|
+
const postRouter = ArkosRouter({ prefix: "/api/posts" });
|
|
148
145
|
|
|
149
|
-
|
|
150
|
-
DATABASE_URL="file:./dev.db"
|
|
146
|
+
export default postRouter;
|
|
151
147
|
```
|
|
152
148
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
### Dynamic Authentication (Recommended)
|
|
149
|
+
Your auto-generated CRUD routes accept the same config as any ArkosRouter route — authentication, validation, rate limiting, all in one place.
|
|
156
150
|
|
|
157
|
-
|
|
151
|
+
**Add business logic exactly where you need it:**
|
|
158
152
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
153
|
+
```typescript
|
|
154
|
+
// src/modules/post/post.interceptor.ts
|
|
155
|
+
import { ArkosRequest, ArkosResponse, ArkosNextFunction } from "arkos";
|
|
156
|
+
import { BadRequestError } from "arkos/error-handler";
|
|
163
157
|
|
|
164
|
-
|
|
158
|
+
export const beforeCreateOne = [
|
|
159
|
+
async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {
|
|
160
|
+
if (req.body.title.length < 5)
|
|
161
|
+
throw new BadRequestError("Title is too short", "TitleTooShort");
|
|
165
162
|
|
|
166
|
-
|
|
163
|
+
req.body.slug = req.body.title.toLowerCase().replace(/\s/g, "-");
|
|
164
|
+
req.body.authorId = req.user.id;
|
|
165
|
+
next();
|
|
166
|
+
},
|
|
167
|
+
];
|
|
168
|
+
```
|
|
167
169
|
|
|
168
|
-
|
|
169
|
-
- Faster setup
|
|
170
|
-
- Easy to understand and modify
|
|
170
|
+
Name the file, export the hook, and Arkos picks it up automatically. No registration needed.
|
|
171
171
|
|
|
172
|
-
##
|
|
172
|
+
## What You Stop Building From Scratch
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
| What you'd normally write | What Arkos gives you |
|
|
175
|
+
| ---------------------------------------- | --------------------------------- |
|
|
176
|
+
| JWT setup, refresh tokens, bcrypt | ✅ Built-in auth system |
|
|
177
|
+
| 5 route handlers per Prisma model | ✅ Auto-generated CRUD |
|
|
178
|
+
| Zod/CV schemas per endpoint | ✅ Auto generate from your models |
|
|
179
|
+
| Swagger config + schema upkeep | ✅ Auto-generated OpenAPI docs |
|
|
180
|
+
| Multer setup + file type validation | ✅ File upload system |
|
|
181
|
+
| Rate limiting, CORS, Helmet, compression | ✅ Pre-configured security stack |
|
|
182
|
+
| **Total setup time** | **~5 minutes vs ~8–12 hours** |
|
|
175
183
|
|
|
176
|
-
|
|
177
|
-
2. **Run migrations** with `npx prisma db push`
|
|
178
|
-
3. **Start coding** - Arkos handles the CRUD operations automatically
|
|
179
|
-
4. **Add custom logic** with interceptors when needed
|
|
184
|
+
## Documentation
|
|
180
185
|
|
|
181
|
-
|
|
182
|
-
# Generate CRUD for a new model
|
|
183
|
-
arkos generate posts -m Post
|
|
186
|
+
For comprehensive guides, API reference, and examples, visit our [official documentation](https://arkosjs.com/docs).
|
|
184
187
|
|
|
185
|
-
|
|
186
|
-
npm run dev
|
|
188
|
+
**Quick Links:**
|
|
187
189
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
190
|
+
- [Getting Started Guide](https://arkosjs.com/docs)
|
|
191
|
+
- [Authentication Setup](https://arkosjs.com/docs/core-concepts/authentication/setup)
|
|
192
|
+
- [Using Interceptors](https://arkosjs.com/docs/core-concepts/components/interceptors)
|
|
193
|
+
- [File Uploads](https://arkosjs.com/docs/guides/file-handling/file-uploads/setup)
|
|
194
|
+
- [Validation](https://arkosjs.com/docs/guides/validation/setup)
|
|
195
|
+
- [Email Service](https://arkosjs.com/docs/guides/email-service)
|
|
191
196
|
|
|
192
|
-
##
|
|
197
|
+
## Getting Nightly Updates
|
|
193
198
|
|
|
194
|
-
|
|
199
|
+
You can get the latest features we're testing before releasing them:
|
|
195
200
|
|
|
196
201
|
```bash
|
|
197
|
-
pnpm create arkos@
|
|
202
|
+
pnpm create arkos@next my-project
|
|
198
203
|
```
|
|
199
204
|
|
|
200
|
-
##
|
|
205
|
+
## Built With
|
|
201
206
|
|
|
202
|
-
|
|
203
|
-
- npm, yarn, or pnpm
|
|
207
|
+
Arkos.js is built on top of industry-leading tools:
|
|
204
208
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
- **
|
|
208
|
-
- **Main Framework:** [github.com/uanela/arkos](https://github.com/uanela/arkos)
|
|
209
|
-
- **Community:** [Join our WhatsApp group](https://chat.whatsapp.com/EJ8cjb9hxau0EcOnI4fdpD)
|
|
210
|
-
- **Examples:** [arkosjs.com/docs/examples](https://arkosjs.com/docs/examples)
|
|
209
|
+
- **[Express](https://expressjs.com/)** - Fast, unopinionated, minimalist web framework for Node.js
|
|
210
|
+
- **[Prisma](https://www.prisma.io/)** - Next-generation ORM for Node.js and TypeScript
|
|
211
|
+
- **[Node.js](https://nodejs.org/)** - JavaScript runtime built on Chrome's V8 engine
|
|
211
212
|
|
|
212
|
-
## Support
|
|
213
|
+
## Support & Contributing
|
|
213
214
|
|
|
215
|
+
- **Documentation:** [arkosjs.com/docs](https://arkosjs.com/docs)
|
|
214
216
|
- **Bug Reports:** [GitHub Issues](https://github.com/uanela/arkos/issues)
|
|
215
217
|
- **Feature Requests:** Open a GitHub issue
|
|
216
|
-
- **
|
|
218
|
+
- **Contact:** [uanelaluiswayne@gmail.com](mailto:uanelaluiswayne@gmail.com)
|
|
217
219
|
|
|
218
|
-
|
|
220
|
+
Contributions are welcome! We appreciate all contributions, from bug fixes to new features.
|
|
221
|
+
|
|
222
|
+
## What Developers Say
|
|
223
|
+
|
|
224
|
+
> "Arkos.js changed how I work on the backend: with a Prisma model I already get CRUD routes, auth, and validation out-of-the-box — I saved a lot of time and could focus on business logic."
|
|
225
|
+
>
|
|
226
|
+
> **— Gelson Matavela, Founder / Grupo Vergui**
|
|
227
|
+
|
|
228
|
+
> "It removes boilerplate and provides a clean structure to build products. Built-in auth is powerful and ready. Automatic CRUD and docs save time, while interceptors allow flexible business logic."
|
|
229
|
+
>
|
|
230
|
+
> **— Augusto Domingos, Tech Lead / DSAI For Moz**
|
|
219
231
|
|
|
220
|
-
|
|
232
|
+
> "With Arkos.js, I can build backends in just a few minutes. It removes the boilerplate and lets me focus entirely on the core logic. Fast, simple, and incredibly productive."
|
|
233
|
+
>
|
|
234
|
+
> **— Niuro Langa, Software Developer / SparkTech**
|
|
221
235
|
|
|
222
|
-
|
|
236
|
+
[See more testimonials →](https://arkosjs.com)
|
|
237
|
+
|
|
238
|
+
## Philosophy
|
|
239
|
+
|
|
240
|
+
Arkos sits between minimal frameworks like Express/Fastify and opinionated ones like NestJS/AdonisJS. It doesn't ask you to learn a new paradigm — it enhances the one most Node.js developers already use, by automating everything that's standardized and staying out of the way everywhere else.
|
|
241
|
+
|
|
242
|
+
Inspired by how Django and Laravel work in their ecosystems: batteries included, nothing forced on you.
|
|
243
|
+
|
|
244
|
+
> The name "Arkos" comes from the Greek word **ἀρχή** _(Arkhē)_, meaning "beginning" or "foundation".
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
223
249
|
|
|
224
250
|
<div align="center">
|
|
225
251
|
|
|
252
|
+
**[Installation](https://www.arkosjs.com/docs/getting-started/installation)** •
|
|
226
253
|
**[Documentation](https://arkosjs.com/docs)** •
|
|
227
254
|
**[Website](https://arkosjs.com)** •
|
|
255
|
+
**[Tutorial](https://arkosjs.com/learn)** •
|
|
228
256
|
**[GitHub](https://github.com/uanela/arkos)** •
|
|
229
|
-
**[
|
|
257
|
+
**[Blog](https://www.arkosjs.com/blog)** •
|
|
258
|
+
**[Npm](https://www.npmjs.com/package/arkos)**
|
|
230
259
|
|
|
231
260
|
Built with ❤️ by [Uanela Como](https://github.com/uanela) and contributors
|
|
232
261
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
_From the Greek "ἀρχή" (Arkhē) - meaning "beginning" - your foundation for Express and Prisma backend development_
|
|
262
|
+
_The name "Arkos" comes from the Greek word "ἀρχή" (Arkhē), meaning "beginning" or "foundation", reflecting our goal of providing a solid foundation for backend development._
|
|
236
263
|
|
|
237
264
|
</div>
|
|
265
|
+
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import inquirer from "inquirer";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
+
import { detectPackageManagerFromUserAgent } from "./helpers/npm.helpers.js";
|
|
4
5
|
class ProjectConfigInquirer {
|
|
5
6
|
config;
|
|
6
7
|
constructor() {
|
|
7
|
-
this.config = {
|
|
8
|
+
this.config = {
|
|
9
|
+
packageManager: detectPackageManagerFromUserAgent(),
|
|
10
|
+
};
|
|
8
11
|
}
|
|
9
12
|
async run() {
|
|
10
13
|
await this.promptProjectName();
|
|
@@ -21,9 +24,6 @@ class ProjectConfigInquirer {
|
|
|
21
24
|
this.config.projectPath = path.resolve(process.cwd(), this.config.projectName);
|
|
22
25
|
if (process?.argv?.includes?.("--advanced"))
|
|
23
26
|
this.config.advanced = true;
|
|
24
|
-
if (this.config.prisma.defaultDatabaseUrl)
|
|
25
|
-
this.config.prisma.defaultDatabaseUrl =
|
|
26
|
-
this.config.prisma.defaultDatabaseUrl.replaceAll("{{projectName}}", this.config.projectName);
|
|
27
27
|
return this.config;
|
|
28
28
|
}
|
|
29
29
|
async promptProjectName() {
|
|
@@ -80,7 +80,7 @@ class ProjectConfigInquirer {
|
|
|
80
80
|
type: "confirm",
|
|
81
81
|
name: "typescript",
|
|
82
82
|
message: `Would you like to use ${chalk.cyan("TypeScript")}?`,
|
|
83
|
-
default:
|
|
83
|
+
default: false,
|
|
84
84
|
},
|
|
85
85
|
]);
|
|
86
86
|
this.config.typescript = typescript;
|
|
@@ -98,69 +98,82 @@ class ProjectConfigInquirer {
|
|
|
98
98
|
"sqlite",
|
|
99
99
|
"sqlserver",
|
|
100
100
|
"cockroachdb",
|
|
101
|
-
"none",
|
|
102
101
|
],
|
|
103
102
|
},
|
|
104
103
|
]);
|
|
105
104
|
let idDatabaseType;
|
|
106
|
-
let
|
|
105
|
+
let defaultDBurl;
|
|
107
106
|
switch (prismaProvider) {
|
|
108
107
|
case "mongodb":
|
|
109
108
|
idDatabaseType = '@id @default(auto()) @map("_id") @db.ObjectId';
|
|
110
|
-
|
|
109
|
+
defaultDBurl = `mongodb://localhost:27017/${this.config.projectName}`;
|
|
111
110
|
break;
|
|
112
111
|
case "sqlite":
|
|
113
112
|
idDatabaseType = "@id @default(cuid())";
|
|
114
|
-
|
|
113
|
+
defaultDBurl = "file:../../file.db";
|
|
115
114
|
break;
|
|
116
115
|
case "mysql":
|
|
117
116
|
idDatabaseType = "@id @default(uuid())";
|
|
118
|
-
|
|
117
|
+
defaultDBurl = `mysql://username:password@localhost:3306/${this.config.projectName}`;
|
|
119
118
|
break;
|
|
120
119
|
case "postgresql":
|
|
121
120
|
idDatabaseType = "@id @default(uuid())";
|
|
122
|
-
|
|
121
|
+
defaultDBurl = `postgresql://username:password@localhost:5432/${this.config.projectName}`;
|
|
123
122
|
break;
|
|
124
123
|
case "sqlserver":
|
|
125
124
|
idDatabaseType = "@id @default(uuid())";
|
|
126
|
-
|
|
125
|
+
defaultDBurl = `sqlserver://localhost:1433;database=${this.config.projectName};username=sa;password=password;encrypt=DANGER_PLAINTEXT`;
|
|
127
126
|
break;
|
|
128
127
|
case "cockroachdb":
|
|
129
128
|
idDatabaseType = "@id @default(uuid())";
|
|
130
|
-
|
|
129
|
+
defaultDBurl = `postgresql://username:password@localhost:26257/${this.config.projectName}?sslmode=require`;
|
|
131
130
|
break;
|
|
132
131
|
default:
|
|
133
132
|
idDatabaseType = "@id @default(uuid())";
|
|
134
|
-
|
|
133
|
+
defaultDBurl = `postgresql://username:password@localhost:5432/${this.config.projectName}`;
|
|
135
134
|
}
|
|
136
135
|
this.config.prisma = {
|
|
137
136
|
provider: prismaProvider,
|
|
138
|
-
idDatabaseType,
|
|
139
|
-
|
|
137
|
+
idDatabaseType: idDatabaseType,
|
|
138
|
+
defaultDBurl: defaultDBurl,
|
|
140
139
|
};
|
|
141
140
|
}
|
|
142
141
|
async promptValidation() {
|
|
143
|
-
const
|
|
144
|
-
? ["zod", "class-validator", "none"]
|
|
145
|
-
: ["zod", "none"];
|
|
146
|
-
const { validationType } = await inquirer.prompt([
|
|
142
|
+
const { useValidation } = await inquirer.prompt([
|
|
147
143
|
{
|
|
148
|
-
type: "
|
|
149
|
-
name: "
|
|
150
|
-
message: `
|
|
151
|
-
|
|
152
|
-
default: "zod",
|
|
144
|
+
type: "confirm",
|
|
145
|
+
name: "useValidation",
|
|
146
|
+
message: `Would you like to set up ${chalk.cyan("Validation")}?`,
|
|
147
|
+
default: true,
|
|
153
148
|
},
|
|
154
149
|
]);
|
|
155
|
-
if (
|
|
150
|
+
if (useValidation) {
|
|
151
|
+
let validationTypeResponse = { validationType: "zod" };
|
|
152
|
+
if (this.config.typescript)
|
|
153
|
+
validationTypeResponse = await inquirer.prompt([
|
|
154
|
+
{
|
|
155
|
+
type: "list",
|
|
156
|
+
name: "validationType",
|
|
157
|
+
message: "Choose validation library:",
|
|
158
|
+
choices: ["zod", "class-validator"],
|
|
159
|
+
},
|
|
160
|
+
]);
|
|
161
|
+
else {
|
|
162
|
+
console.info(chalk.bold(`${chalk.greenBright("?")} Validation library set to zod (class-validator is not supported on JavaScript):`), chalk.cyan("zod"));
|
|
163
|
+
}
|
|
156
164
|
this.config.validation = {
|
|
157
|
-
type: validationType,
|
|
165
|
+
type: validationTypeResponse.validationType,
|
|
158
166
|
};
|
|
159
167
|
}
|
|
168
|
+
else if (!this.config.typescript) {
|
|
169
|
+
}
|
|
160
170
|
}
|
|
161
171
|
async promptAuthentication() {
|
|
162
172
|
if (this.config.prisma.provider === "none") {
|
|
163
|
-
console.info(
|
|
173
|
+
console.info(`${chalk.green("! ")}${chalk.bold("Skipping authentication setup as it requires prisma.")}`);
|
|
174
|
+
this.config.authentication = {
|
|
175
|
+
type: "none",
|
|
176
|
+
};
|
|
164
177
|
return;
|
|
165
178
|
}
|
|
166
179
|
const { authenticationType } = await inquirer.prompt([
|
|
@@ -196,8 +209,9 @@ class ProjectConfigInquirer {
|
|
|
196
209
|
usernameField,
|
|
197
210
|
multipleRoles: false,
|
|
198
211
|
};
|
|
199
|
-
if (authenticationType !== "static"
|
|
200
|
-
|
|
212
|
+
if (authenticationType !== "static" ||
|
|
213
|
+
(authenticationType == "static" &&
|
|
214
|
+
this.config.prisma.provider !== "sqlite")) {
|
|
201
215
|
const { multipleRoles } = await inquirer.prompt([
|
|
202
216
|
{
|
|
203
217
|
type: "confirm",
|
|
@@ -212,7 +226,7 @@ class ProjectConfigInquirer {
|
|
|
212
226
|
};
|
|
213
227
|
}
|
|
214
228
|
else if (this.config.prisma.provider === "sqlite") {
|
|
215
|
-
console.info(
|
|
229
|
+
console.info(`${chalk.green("! ")}${chalk.bold("Skipping multiple roles option because it is not supported with sqlite prisma provider and static authentication mode.")}`);
|
|
216
230
|
}
|
|
217
231
|
}
|
|
218
232
|
async promptStrictRouting() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-config-inquirer.js","sourceRoot":"","sources":["../../src/utils/project-config-inquirer.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"path\";\nimport inquirer from \"inquirer\";\nimport chalk from \"chalk\";\n\nexport interface ProjectConfig {\n projectName: string;\n argProjectName?: string;\n typescript: boolean;\n validation?: {\n type?: \"zod\" | \"class-validator\";\n };\n authentication?: {\n type?: \"static\" | \"dynamic\" | \"none\";\n usernameField?: string;\n multipleRoles: boolean;\n };\n prisma: {\n provider:\n | \"postgresql\"\n | \"mysql\"\n | \"sqlite\"\n | \"sqlserver\"\n | \"cockroachdb\"\n | \"mongodb\"\n | \"none\";\n idDatabaseType: string;\n defaultDatabaseUrl: string;\n };\n projectPath: string;\n routing?: {\n strict?: boolean;\n };\n advanced?: boolean;\n}\n\nclass ProjectConfigInquirer {\n private config: ProjectConfig;\n\n constructor() {\n this.config = {} as ProjectConfig;\n }\n\n async run() {\n await this.promptProjectName();\n await this.promptTypescript();\n await this.promptPrismaProvider();\n await this.promptValidation();\n await this.promptAuthentication();\n await this.promptStrictRouting();\n\n if (this.config.projectName === \".\") {\n this.config.projectName = path.basename(process.cwd());\n this.config.projectPath = path.resolve(process.cwd());\n } else\n this.config.projectPath = path.resolve(\n process.cwd(),\n this.config.projectName\n );\n\n if (process?.argv?.includes?.(\"--advanced\")) this.config.advanced = true;\n if (this.config.prisma.defaultDatabaseUrl)\n this.config.prisma.defaultDatabaseUrl =\n this.config.prisma.defaultDatabaseUrl.replaceAll(\n \"{{projectName}}\",\n this.config.projectName\n );\n\n return this.config;\n }\n\n private async promptProjectName() {\n let projectName = process?.argv?.[2];\n this.config.argProjectName = process?.argv?.[2];\n\n if (!projectName) {\n const result = await inquirer.prompt([\n {\n type: \"input\",\n name: \"projectName\",\n message: \"What is the name of your project?\",\n default: \"my-arkos-project\",\n validate: this.validateProjectName,\n },\n ]);\n projectName = result.projectName;\n } else {\n const validation = this.validateProjectName(projectName);\n if (validation !== true) {\n console.error(chalk.red(`\\nError: ${validation}`));\n process.exit(1);\n }\n }\n\n this.config.projectName = projectName;\n }\n\n private validateProjectName(input: string): boolean | string {\n if (input === \".\") return true;\n\n if (!input || input.length === 0) {\n return \"Project name cannot be empty\";\n }\n\n if (!/^[a-zA-Z0-9_-]+$/.test(input)) {\n return \"Project name can only contain letters, numbers, hyphens, and underscores\";\n }\n\n if (!/^[a-zA-Z0-9]/.test(input)) {\n return \"Project name must start with a letter or number\";\n }\n\n if (!/[a-zA-Z0-9]$/.test(input)) {\n return \"Project name must end with a letter or number\";\n }\n\n if (input.length > 50) {\n return \"Project name must be 50 characters or less\";\n }\n\n const reservedNames = [\"node_modules\"];\n if (reservedNames.includes(input.toLowerCase())) {\n return \"Project name cannot be a reserved name\";\n }\n\n return true;\n }\n\n private async promptTypescript() {\n const { typescript } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"typescript\",\n message: `Would you like to use ${chalk.cyan(\"TypeScript\")}?`,\n default: true,\n },\n ]);\n this.config.typescript = typescript;\n }\n\n private async promptPrismaProvider() {\n const { prismaProvider } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"prismaProvider\",\n message: `What db provider will be used for ${chalk.cyan(\"Prisma\")}?`,\n choices: [\n \"postgresql\",\n \"mongodb\",\n \"mysql\",\n \"sqlite\",\n \"sqlserver\",\n \"cockroachdb\",\n \"none\",\n ],\n },\n ]);\n\n let idDatabaseType: string;\n let defaultDatabaseUrl: string;\n\n switch (prismaProvider) {\n case \"mongodb\":\n idDatabaseType = '@id @default(auto()) @map(\"_id\") @db.ObjectId';\n defaultDatabaseUrl = `mongodb://localhost:27017/{{projectName}}`;\n break;\n case \"sqlite\":\n idDatabaseType = \"@id @default(cuid())\";\n defaultDatabaseUrl = \"file:../../file.db\";\n break;\n case \"mysql\":\n idDatabaseType = \"@id @default(uuid())\";\n defaultDatabaseUrl = `mysql://username:password@localhost:3306/{{projectName}}`;\n break;\n case \"postgresql\":\n idDatabaseType = \"@id @default(uuid())\";\n defaultDatabaseUrl = `postgresql://username:password@localhost:5432/{{projectName}}`;\n break;\n case \"sqlserver\":\n idDatabaseType = \"@id @default(uuid())\";\n defaultDatabaseUrl = `sqlserver://localhost:1433;database={{projectName}};username=sa;password=password;encrypt=DANGER_PLAINTEXT`;\n break;\n case \"cockroachdb\":\n idDatabaseType = \"@id @default(uuid())\";\n defaultDatabaseUrl = `postgresql://username:password@localhost:26257/{{projectName}}?sslmode=require`;\n break;\n default:\n idDatabaseType = \"@id @default(uuid())\";\n defaultDatabaseUrl = `postgresql://username:password@localhost:5432/{{projectName}}`;\n }\n\n this.config.prisma = {\n provider: prismaProvider,\n idDatabaseType,\n defaultDatabaseUrl,\n };\n }\n\n private async promptValidation() {\n // For JS projects, class-validator is not supported — skip the choice\n const choices = this.config.typescript\n ? [\"zod\", \"class-validator\", \"none\"]\n : [\"zod\", \"none\"];\n\n const { validationType } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"validationType\",\n message: `Which ${chalk.cyan(\"Validation\")} library would you like to use?`,\n choices,\n default: \"zod\",\n },\n ]);\n\n if (validationType !== \"none\") {\n this.config.validation = {\n type: validationType as \"zod\" | \"class-validator\",\n };\n }\n // validation stays undefined when \"none\" is chosen — matches original behaviour\n }\n\n private async promptAuthentication() {\n if (this.config.prisma.provider === \"none\") {\n console.info(`Skipping authentication setup as it requires prisma.`);\n return;\n }\n\n const { authenticationType } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"authenticationType\",\n message: `Which ${chalk.cyan(\"Authentication\")} mode would you like to use?`,\n choices: [\"static\", \"dynamic\", \"none\"],\n default: \"static\",\n },\n ]);\n\n if (authenticationType === \"none\") {\n this.config.authentication = { type: \"none\", multipleRoles: false };\n return;\n }\n\n const { usernameField } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"usernameField\",\n message: \"Enter the Prisma field name to use as the login username:\",\n default: \"email\",\n validate: (input: string) => {\n if (!input || input.length === 0) return \"Field name cannot be empty\";\n if (!/^[a-z][a-zA-Z0-9]*$/.test(input))\n return \"Must be a valid Prisma field name (camelCase, starts with lowercase, letters and numbers only)\";\n return true;\n },\n },\n ]);\n\n this.config.authentication = {\n type: authenticationType as \"static\" | \"dynamic\",\n usernameField,\n multipleRoles: false,\n };\n\n if (\n authenticationType !== \"static\" &&\n this.config.prisma.provider !== \"sqlite\"\n ) {\n const { multipleRoles } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"multipleRoles\",\n default: true,\n message: `Would you like to use authentication with ${chalk.cyan(\"Multiple Roles\")}?`,\n },\n ]);\n\n this.config.authentication = {\n ...this.config.authentication,\n multipleRoles,\n };\n } else if (this.config.prisma.provider === \"sqlite\") {\n console.info(\n `Skipping multiple roles option because it is not supported with sqlite prisma provider and static authentication mode.`\n );\n }\n }\n\n private async promptStrictRouting() {\n const { strictRouting } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"strictRouting\",\n message: `Would you like to use ${chalk.cyan(\"Strict Routing\")}?`,\n default: false,\n },\n ]);\n this.config.routing = {\n strict: strictRouting,\n };\n }\n}\n\nconst projectConfigInquirer = new ProjectConfigInquirer();\n\nexport default projectConfigInquirer;\n"]}
|
|
1
|
+
{"version":3,"file":"project-config-inquirer.js","sourceRoot":"","sources":["../../src/utils/project-config-inquirer.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"path\";\nimport inquirer from \"inquirer\";\nimport chalk from \"chalk\";\nimport { detectPackageManagerFromUserAgent } from \"./helpers/npm.helpers\";\n\nexport interface ProjectConfig {\n projectName: string;\n argProjectName?: string;\n typescript: boolean;\n validation?: {\n type?: \"zod\" | \"class-validator\" | \"none\";\n };\n authentication?: {\n type?: \"static\" | \"dynamic\" | \"none\";\n usernameField?: \"username\" | \"email\" | \"custom\";\n multipleRoles?: boolean;\n };\n prisma: {\n provider:\n | \"postgresql\"\n | \"mysql\"\n | \"sqlite\"\n | \"sqlserver\"\n | \"cockroachdb\"\n | \"mongodb\"\n | \"none\";\n idDatabaseType: string;\n defaultDBurl: string;\n };\n projectPath: string;\n routing?: {\n strict?: boolean;\n };\n advanced?: boolean;\n entryPoint: \"src/app\" | \"src/server\";\n packageManager: string;\n}\n\nclass ProjectConfigInquirer {\n private config: ProjectConfig;\n\n constructor() {\n this.config = {\n packageManager: detectPackageManagerFromUserAgent(),\n } as ProjectConfig;\n }\n\n async run() {\n await this.promptProjectName();\n await this.promptTypescript();\n await this.promptPrismaProvider();\n await this.promptValidation();\n await this.promptAuthentication();\n await this.promptStrictRouting();\n\n if (this.config.projectName === \".\") {\n this.config.projectName = path.basename(process.cwd());\n this.config.projectPath = path.resolve(process.cwd());\n } else\n this.config.projectPath = path.resolve(\n process.cwd(),\n this.config.projectName\n );\n\n if (process?.argv?.includes?.(\"--advanced\")) this.config.advanced = true;\n\n return this.config;\n }\n\n private async promptProjectName() {\n let projectName = process?.argv?.[2];\n this.config.argProjectName = process?.argv?.[2];\n\n if (!projectName) {\n const result = await inquirer.prompt([\n {\n type: \"input\",\n name: \"projectName\",\n message: \"What is the name of your project?\",\n default: \"my-arkos-project\",\n validate: this.validateProjectName,\n },\n ]);\n projectName = result.projectName;\n } else {\n // Validate the project name from command line args\n const validation = this.validateProjectName(projectName);\n if (validation !== true) {\n console.error(chalk.red(`\\nError: ${validation}`));\n process.exit(1);\n }\n }\n\n this.config.projectName = projectName;\n }\n\n private validateProjectName(input: string): boolean | string {\n if (input === \".\") return true;\n\n if (!input || input.length === 0) {\n return \"Project name cannot be empty\";\n }\n\n if (!/^[a-zA-Z0-9_-]+$/.test(input)) {\n return \"Project name can only contain letters, numbers, hyphens, and underscores\";\n }\n\n if (!/^[a-zA-Z0-9]/.test(input)) {\n return \"Project name must start with a letter or number\";\n }\n\n if (!/[a-zA-Z0-9]$/.test(input)) {\n return \"Project name must end with a letter or number\";\n }\n\n if (input.length > 50) {\n return \"Project name must be 50 characters or less\";\n }\n\n const reservedNames = [\"node_modules\"];\n if (reservedNames.includes(input.toLowerCase())) {\n return \"Project name cannot be a reserved name\";\n }\n\n return true;\n }\n\n private async promptTypescript() {\n const { typescript } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"typescript\",\n message: `Would you like to use ${chalk.cyan(\"TypeScript\")}?`,\n default: false,\n },\n ]);\n this.config.typescript = typescript;\n }\n\n private async promptPrismaProvider() {\n const { prismaProvider } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"prismaProvider\",\n message: `What db provider will be used for ${chalk.cyan(\"Prisma\")}?`,\n choices: [\n \"postgresql\",\n \"mongodb\",\n \"mysql\",\n \"sqlite\",\n \"sqlserver\",\n \"cockroachdb\",\n ],\n },\n ]);\n\n // Set the correct idDatabaseType based on provider\n let idDatabaseType: string;\n let defaultDBurl: string;\n\n switch (prismaProvider) {\n case \"mongodb\":\n idDatabaseType = '@id @default(auto()) @map(\"_id\") @db.ObjectId';\n defaultDBurl = `mongodb://localhost:27017/${this.config.projectName}`;\n break;\n case \"sqlite\":\n idDatabaseType = \"@id @default(cuid())\";\n defaultDBurl = \"file:../../file.db\";\n break;\n case \"mysql\":\n idDatabaseType = \"@id @default(uuid())\";\n defaultDBurl = `mysql://username:password@localhost:3306/${this.config.projectName}`;\n break;\n case \"postgresql\":\n idDatabaseType = \"@id @default(uuid())\";\n defaultDBurl = `postgresql://username:password@localhost:5432/${this.config.projectName}`;\n break;\n case \"sqlserver\":\n idDatabaseType = \"@id @default(uuid())\";\n defaultDBurl = `sqlserver://localhost:1433;database=${this.config.projectName};username=sa;password=password;encrypt=DANGER_PLAINTEXT`;\n break;\n case \"cockroachdb\":\n idDatabaseType = \"@id @default(uuid())\";\n defaultDBurl = `postgresql://username:password@localhost:26257/${this.config.projectName}?sslmode=require`;\n break;\n default:\n idDatabaseType = \"@id @default(uuid())\";\n defaultDBurl = `postgresql://username:password@localhost:5432/${this.config.projectName}`;\n }\n\n this.config.prisma = {\n provider: prismaProvider,\n idDatabaseType: idDatabaseType,\n defaultDBurl: defaultDBurl,\n };\n }\n\n private async promptValidation() {\n const { useValidation } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"useValidation\",\n message: `Would you like to set up ${chalk.cyan(\"Validation\")}?`,\n default: true,\n },\n ]);\n\n if (useValidation) {\n let validationTypeResponse: {\n validationType: \"zod\" | \"class-validator\";\n } = { validationType: \"zod\" };\n\n if (this.config.typescript)\n validationTypeResponse = await inquirer.prompt([\n {\n type: \"list\",\n name: \"validationType\",\n message: \"Choose validation library:\",\n choices: [\"zod\", \"class-validator\"],\n },\n ]);\n else {\n console.info(\n chalk.bold(\n `${chalk.greenBright(\"?\")} Validation library set to zod (class-validator is not supported on JavaScript):`\n ),\n chalk.cyan(\"zod\")\n );\n }\n this.config.validation = {\n type: validationTypeResponse.validationType,\n };\n } else if (!this.config.typescript) {\n }\n }\n\n private async promptAuthentication() {\n if (this.config.prisma.provider === \"none\") {\n console.info(\n `${chalk.green(\"! \")}${chalk.bold(\"Skipping authentication setup as it requires prisma.\")}`\n );\n this.config.authentication = {\n type: \"none\",\n };\n return;\n }\n\n const { authenticationType } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"authenticationType\",\n message: `Which ${chalk.cyan(\"Authentication\")} mode would you like to use?`,\n choices: [\"static\", \"dynamic\", \"none\"],\n default: \"static\",\n },\n ]);\n\n if (authenticationType === \"none\") {\n this.config.authentication = { type: \"none\", multipleRoles: false };\n return;\n }\n\n const { usernameField } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"usernameField\",\n message: \"Enter the Prisma field name to use as the login username:\",\n default: \"email\",\n validate: (input: string) => {\n if (!input || input.length === 0) return \"Field name cannot be empty\";\n if (!/^[a-z][a-zA-Z0-9]*$/.test(input))\n return \"Must be a valid Prisma field name (camelCase, starts with lowercase, letters and numbers only)\";\n return true;\n },\n },\n ]);\n\n this.config.authentication = {\n type: authenticationType as \"static\" | \"dynamic\",\n usernameField,\n multipleRoles: false,\n };\n\n if (\n authenticationType !== \"static\" ||\n (authenticationType == \"static\" &&\n this.config.prisma.provider !== \"sqlite\")\n ) {\n const { multipleRoles } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"multipleRoles\",\n default: true,\n message: `Would you like to use authentication with ${chalk.cyan(\"Multiple Roles\")}?`,\n },\n ]);\n\n this.config.authentication = {\n ...this.config.authentication,\n multipleRoles,\n };\n } else if (this.config.prisma.provider === \"sqlite\") {\n console.info(\n `${chalk.green(\"! \")}${chalk.bold(\"Skipping multiple roles option because it is not supported with sqlite prisma provider and static authentication mode.\")}`\n );\n }\n }\n\n private async promptStrictRouting() {\n const { strictRouting } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"strictRouting\",\n message: `Would you like to use ${chalk.cyan(\"Strict Routing\")}?`,\n default: false,\n },\n ]);\n this.config.routing = {\n strict: strictRouting,\n };\n }\n}\n\nconst projectConfigInquirer = new ProjectConfigInquirer();\n\nexport default projectConfigInquirer;\n"]}
|
|
@@ -55,14 +55,13 @@ class TemplateCompiler {
|
|
|
55
55
|
"user.router.ts.hbs",
|
|
56
56
|
"user.policy.ts.hbs",
|
|
57
57
|
];
|
|
58
|
-
if (config.
|
|
59
|
-
|
|
60
|
-
if (!config.authentication?.type || config.authentication?.type === "none")
|
|
58
|
+
if (!config.authentication?.type ||
|
|
59
|
+
config.authentication?.type === "none")
|
|
61
60
|
files.push(...authSharedPrismaFiles, ...dynamicAuthPrismaFiles, ...sharedAuthDtoFiles, ...dynamicAuthDtoFiles, ...userModuleComponents, ...authModuleComponents, ...authPermissionModuleComponents, ...authRoleModuleComponents, ...userDtoFiles, "file-upload.policy.ts.hbs");
|
|
62
61
|
if (config.authentication?.type === "static")
|
|
63
62
|
files.push(...dynamicAuthPrismaFiles, ...dynamicAuthDtoFiles, ...authPermissionModuleComponents, ...authRoleModuleComponents);
|
|
64
63
|
if (!config.validation?.type)
|
|
65
|
-
files.push(...sharedAuthDtoFiles, ...dynamicAuthDtoFiles, ...userDtoFiles
|
|
64
|
+
files.push(...sharedAuthDtoFiles, ...dynamicAuthDtoFiles, ...userDtoFiles);
|
|
66
65
|
if (!config.typescript)
|
|
67
66
|
files.push(...["tsconfig.json.hbs"]);
|
|
68
67
|
if (config?.typescript)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-compiler.js","sourceRoot":"","sources":["../../src/utils/template-compiler.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,MAAM,gBAAgB;IACpB,KAAK,CAAC,iCAAiC,CAAC,MAAqB;QAC3D,OAAO,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC;IACjC,CAAC;IAED,gBAAgB,CAAC,MAAqB;QACpC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,qBAAqB,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAElD,MAAM,sBAAsB,GAAG;YAC7B,4BAA4B;YAC5B,sBAAsB;YACtB,sBAAsB;SACvB,CAAC;QAEF,MAAM,YAAY,GAAG;YACnB,wBAAwB;YACxB,wBAAwB;YACxB,uBAAuB;SACxB,CAAC;QAEF,MAAM,kBAAkB,GAAG;YACzB,kBAAkB;YAClB,mBAAmB;YACnB,4BAA4B;YAC5B,sBAAsB;SACvB,CAAC;QAEF,MAAM,mBAAmB,GAAG;YAC1B,mCAAmC;YACnC,mCAAmC;YACnC,kCAAkC;YAClC,6BAA6B;YAC7B,6BAA6B;YAC7B,4BAA4B;SAC7B,CAAC;QAEF,MAAM,oBAAoB,GAAG;YAC3B,wBAAwB;YACxB,oBAAoB;YACpB,oBAAoB;SACrB,CAAC;QAEF,MAAM,8BAA8B,GAAG;YACrC,+BAA+B;YAC/B,+BAA+B;YAC/B,mCAAmC;YACnC,gCAAgC;SACjC,CAAC;QAEF,MAAM,wBAAwB,GAAG;YAC/B,yBAAyB;YACzB,yBAAyB;YACzB,6BAA6B;YAC7B,0BAA0B;SAC3B,CAAC;QAEF,MAAM,oBAAoB,GAAG;YAC3B,wBAAwB;YACxB,qBAAqB;YACrB,oBAAoB;YACpB,oBAAoB;SACrB,CAAC;QAEF,
|
|
1
|
+
{"version":3,"file":"template-compiler.js","sourceRoot":"","sources":["../../src/utils/template-compiler.ts"],"names":[],"mappings":"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","sourcesContent":["import { ProjectConfig } from \"./project-config-inquirer\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport handlebars from \"handlebars\";\n\nclass TemplateCompiler {\n async canCompileAuthenticationTemplates(config: ProjectConfig) {\n return !!config.authentication;\n }\n\n filesToBeSkipped(config: ProjectConfig) {\n const files: string[] = [];\n const authSharedPrismaFiles = [\"user.prisma.hbs\"];\n\n const dynamicAuthPrismaFiles = [\n \"auth-permission.prisma.hbs\",\n \"auth-role.prisma.hbs\",\n \"user-role.prisma.hbs\",\n ];\n\n const userDtoFiles = [\n \"create-user.dto.ts.hbs\",\n \"update-user.dto.ts.hbs\",\n \"query-user.dto.ts.hbs\",\n ];\n\n const sharedAuthDtoFiles = [\n \"login.dto.ts.hbs\",\n \"signup.dto.ts.hbs\",\n \"update-password.dto.ts.hbs\",\n \"update-me.dto.ts.hbs\",\n ];\n\n const dynamicAuthDtoFiles = [\n \"create-auth-permission.dto.ts.hbs\",\n \"update-auth-permission.dto.ts.hbs\",\n \"query-auth-permission.dto.ts.hbs\",\n \"create-auth-role.dto.ts.hbs\",\n \"update-auth-role.dto.ts.hbs\",\n \"query-auth-role.dto.ts.hbs\",\n ];\n\n const authModuleComponents = [\n \"auth.route-hook.ts.hbs\",\n \"auth.policy.ts.hbs\",\n \"auth.router.ts.hbs\",\n ];\n\n const authPermissionModuleComponents = [\n \"auth-permission.router.ts.hbs\",\n \"auth-permission.policy.ts.hbs\",\n \"auth-permission.route-hook.ts.hbs\",\n \"auth-permission.service.ts.hbs\",\n ];\n\n const authRoleModuleComponents = [\n \"auth-role.router.ts.hbs\",\n \"auth-role.policy.ts.hbs\",\n \"auth-role.route-hook.ts.hbs\",\n \"auth-role.service.ts.hbs\",\n ];\n\n const userModuleComponents = [\n \"user.route-hook.ts.hbs\",\n \"user.service.ts.hbs\",\n \"user.router.ts.hbs\",\n \"user.policy.ts.hbs\",\n ];\n\n if (\n !config.authentication?.type ||\n config.authentication?.type === \"none\"\n )\n files.push(\n ...authSharedPrismaFiles,\n ...dynamicAuthPrismaFiles,\n ...sharedAuthDtoFiles,\n ...dynamicAuthDtoFiles,\n ...userModuleComponents,\n ...authModuleComponents,\n ...authPermissionModuleComponents,\n ...authRoleModuleComponents,\n ...userDtoFiles,\n \"file-upload.policy.ts.hbs\"\n );\n\n if (config.authentication?.type === \"static\")\n files.push(\n ...dynamicAuthPrismaFiles,\n ...dynamicAuthDtoFiles,\n ...authPermissionModuleComponents,\n ...authRoleModuleComponents\n );\n\n if (!config.validation?.type)\n files.push(\n ...sharedAuthDtoFiles,\n ...dynamicAuthDtoFiles,\n ...userDtoFiles\n );\n\n // Ignoring typescript related files when typescript false\n if (!config.typescript) files.push(...[\"tsconfig.json.hbs\"]);\n\n // Ignoring javascript related files when typescript true\n if (config?.typescript) files.push(...[\"jsconfig.json.hbs\"]);\n\n return files;\n }\n /**\n * Compiles the Arkos.js project with handlebars templates\n *\n * @param templatesDir {string} templates location\n * @param config {ProjectConfig} the project configuration\n * @returns void\n * */\n async compile(templatesDir: string, config: ProjectConfig) {\n const outputDir = config.projectPath;\n const isTypescript = config.typescript;\n const filesToBeSkipped = this.filesToBeSkipped(config);\n\n function processTemplates(dir: string, relativeDir = \"\") {\n fs.readdirSync(dir, { withFileTypes: true }).forEach(async (dirent) => {\n if (\n filesToBeSkipped.includes(dirent.name) ||\n dirent.name === \"__tests__\" ||\n dirent.name?.includes(\".test.ts\")\n )\n return;\n\n const fullPath = path.join(dir, dirent.name);\n const relativePath = path.join(relativeDir, dirent.name);\n\n if (dirent.isDirectory()) {\n processTemplates(fullPath, relativePath);\n } else if (dirent.name.endsWith(\".hbs\")) {\n const templatePath = fullPath;\n const template = handlebars.compile(\n fs.readFileSync(templatePath, \"utf8\")\n );\n\n let arkosCurrentVersion = \"{{arkosCurrentVersion}}\";\n\n const content = template({ ...config, arkosCurrentVersion });\n const ext = isTypescript ? \".ts\" : \".js\";\n\n let outputPath = path.join(\n outputDir,\n relativePath.replace(\".hbs\", \"\")\n );\n if (dirent.name.endsWith(\".ts.hbs\"))\n outputPath = path.join(\n outputDir,\n relativePath.replace(\".ts.hbs\", ext)\n );\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, content);\n }\n });\n }\n\n processTemplates(templatesDir);\n }\n}\n\nconst templateCompiler = new TemplateCompiler();\n\nexport default templateCompiler;\n"]}
|
package/package.json
CHANGED
package/templates/basic/.env.hbs
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
{{#if (neq prisma.provider "none")}}
|
|
2
1
|
# Database connection
|
|
3
|
-
DATABASE_URL={{prisma.
|
|
4
|
-
{{/if}}
|
|
2
|
+
DATABASE_URL={{prisma.defaultDBurl}}
|
|
5
3
|
|
|
6
|
-
{{#if (neq authentication.type "none")}}
|
|
7
4
|
# JWT secrets
|
|
8
5
|
# JWT_SECRET=
|
|
9
6
|
# JWT_EXPIRES_IN=30d
|
|
10
|
-
{{/if}}
|
|
11
7
|
|
|
12
8
|
# Server configuration
|
|
13
9
|
PORT=8000
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
This is
|
|
1
|
+
This is an [Arkos.js](https://arkosjs.com) project scaffolded with [`create-arkos`](https://arkosjs.com/docs/tooling/cli/overviewcreate-arkos).
|
|
2
2
|
|
|
3
3
|
## Getting Started
|
|
4
4
|
|
|
5
5
|
First, run the development server:
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
9
|
-
# or
|
|
10
|
-
npm run dev
|
|
8
|
+
{{packageManager}} run dev
|
|
11
9
|
```
|
|
12
10
|
|
|
13
11
|
- Visit [http://localhost:8000/api/docs](http://localhost:8000/api/docs) with your browser to see the swagger api documentation.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { defineConfig } from "arkos/config"
|
|
2
|
-
import prisma from "
|
|
2
|
+
import prisma from "@/src/utils/prisma"
|
|
3
3
|
|
|
4
4
|
const arkosConfig = defineConfig({
|
|
5
5
|
globalPrefix: "/api",
|
|
6
6
|
prisma: {
|
|
7
7
|
instance: prisma
|
|
8
8
|
},
|
|
9
|
-
{{#if
|
|
9
|
+
{{#if authentication.type}}
|
|
10
10
|
authentication: {
|
|
11
11
|
mode: '{{authentication.type}}',
|
|
12
12
|
login: {
|
|
@@ -31,19 +31,9 @@ const arkosConfig = defineConfig({
|
|
|
31
31
|
},
|
|
32
32
|
middlewares: {
|
|
33
33
|
cors: {
|
|
34
|
-
allowedOrigins: "*"
|
|
34
|
+
allowedOrigins: process.env.NODE_ENV !== "production" ? "*" : "your-production-url"
|
|
35
35
|
},
|
|
36
|
-
}
|
|
37
|
-
{{#if (eq prisma.provider "none")}}
|
|
38
|
-
warnings: {
|
|
39
|
-
suppress: {
|
|
40
|
-
prisma: {
|
|
41
|
-
noInstanceFound: true,
|
|
42
|
-
noSchemaFound: true,
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
{{/if}}
|
|
36
|
+
}
|
|
47
37
|
})
|
|
48
38
|
|
|
49
39
|
export default arkosConfig
|
|
@@ -17,16 +17,17 @@
|
|
|
17
17
|
"@types/express": "5.0.0",
|
|
18
18
|
{{/if}}
|
|
19
19
|
"tsx-strict": "0.7.0",
|
|
20
|
-
"tsx": "4.
|
|
21
|
-
"prisma": "6.19.
|
|
20
|
+
"tsx": "4.23.1"{{#if (neq prisma.provider "none")}},
|
|
21
|
+
"prisma": "6.19.3"
|
|
22
22
|
{{/if}}
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"arkos": "2.0.0-next.
|
|
26
|
-
"express": "4.22.
|
|
27
|
-
"@scalar/express-api-reference": "0.
|
|
25
|
+
"arkos": "2.0.0-next.17",
|
|
26
|
+
"express": "4.22.2",
|
|
27
|
+
"@scalar/express-api-reference": "0.10.2",
|
|
28
|
+
"@scalar/api-reference": "1.55.3"{{#if (or (neq prisma.provider "none") validation.type)}},{{/if}}
|
|
28
29
|
{{#if (neq prisma.provider "none")}}
|
|
29
|
-
"@prisma/client": "6.19.
|
|
30
|
+
"@prisma/client": "6.19.3"{{#if validation.type}},{{/if}}
|
|
30
31
|
{{/if}}
|
|
31
32
|
{{#if (eq validation.type "class-validator")}}
|
|
32
33
|
"reflect-metadata": "0.2.2",
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
"class-validator": "0.14.1"
|
|
35
36
|
{{/if}}
|
|
36
37
|
{{#if (eq validation.type "zod")}}
|
|
37
|
-
"zod": "3.
|
|
38
|
+
"zod": "3.25.76"
|
|
38
39
|
{{/if}}
|
|
39
40
|
}
|
|
40
41
|
}
|
|
@@ -65,10 +65,10 @@ describe("User model template rendering", () => {
|
|
|
65
65
|
expect(result3).toContain("roles UserRole[]");
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
it('should handle "
|
|
68
|
+
it('should handle "define later" authentication type', () => {
|
|
69
69
|
const context = {
|
|
70
70
|
authentication: {
|
|
71
|
-
type: "
|
|
71
|
+
type: "define later",
|
|
72
72
|
usernameField: "email",
|
|
73
73
|
},
|
|
74
74
|
prisma: {
|
|
@@ -37,11 +37,7 @@ export default class CreateAuthPermissionDto {
|
|
|
37
37
|
|
|
38
38
|
@ValidateNested()
|
|
39
39
|
@Type(() => RoleConnectDto)
|
|
40
|
-
role!: RoleConnectDto;
|
|
41
|
-
|
|
42
40
|
@IsOptional()
|
|
43
|
-
|
|
44
|
-
@Transform(({ value }) => value)
|
|
45
|
-
description?: string;
|
|
41
|
+
roles?: RoleConnectDto[];
|
|
46
42
|
}
|
|
47
43
|
{{/if}}
|
|
@@ -24,11 +24,13 @@ export default class UpdateAuthPermissionDto {
|
|
|
24
24
|
|
|
25
25
|
@IsOptional()
|
|
26
26
|
@IsString()
|
|
27
|
-
@Transform(({ value }) => value)
|
|
28
|
-
action?: string
|
|
27
|
+
@Transform(({ value }) => String(value))
|
|
28
|
+
action?: string
|
|
29
29
|
|
|
30
|
+
@ValidateNested({ each: true })
|
|
31
|
+
@IsArray()
|
|
32
|
+
@Type(() => RoleConnectDto)
|
|
30
33
|
@IsOptional()
|
|
31
|
-
|
|
32
|
-
description?: string;
|
|
34
|
+
roles?: RoleConnectDto[];
|
|
33
35
|
}
|
|
34
36
|
{{/if}}
|
|
@@ -29,13 +29,8 @@ class CreatePermissionForRoleDto {
|
|
|
29
29
|
resource!: string;
|
|
30
30
|
|
|
31
31
|
@IsString()
|
|
32
|
-
@Transform(({ value }) => value
|
|
33
|
-
action
|
|
34
|
-
|
|
35
|
-
@IsOptional()
|
|
36
|
-
@IsString()
|
|
37
|
-
@Transform(({ value }) => value)
|
|
38
|
-
description?: string;
|
|
32
|
+
@Transform(({ value }) => String(value))
|
|
33
|
+
action!: string;
|
|
39
34
|
}
|
|
40
35
|
|
|
41
36
|
export default class CreateAuthRoleDto {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Is worth mentioning that this will be addded into `arkos` as an util.
|
|
6
6
|
*
|
|
7
|
-
* @see {@link https://www.arkosjs.com/docs/
|
|
7
|
+
* @see {@link https://www.arkosjs.com/docs/advanced-guide/handling-relation-fields-in-prisma-body-requests#the-apiaction-property}
|
|
8
8
|
*/
|
|
9
9
|
const apiActions = ["connect", "disconnect", "delete", "update", "create"]{{#if typescript}} as const{{/if}};
|
|
10
10
|
|