create-warlock 2.6.1 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/templates/warlock/.env +39 -0
  3. package/templates/warlock/.env.example +35 -35
  4. package/templates/warlock/.gitattributes +1 -1
  5. package/templates/warlock/package.json +9 -7
  6. package/templates/warlock/src/app/main.ts +43 -12
  7. package/templates/warlock/src/app/posts/controllers/create-new-post.request.ts +26 -0
  8. package/templates/warlock/src/app/posts/controllers/get-all-posts.request.ts +17 -0
  9. package/templates/warlock/src/app/posts/controllers/get-post.request.ts +37 -0
  10. package/templates/warlock/src/app/posts/models/index.ts +1 -0
  11. package/templates/warlock/src/app/posts/models/post.model.ts +22 -0
  12. package/templates/warlock/src/app/posts/output/post.output.ts +13 -0
  13. package/templates/warlock/src/app/posts/routes.ts +12 -0
  14. package/templates/warlock/src/app/uploads/routes.ts +27 -27
  15. package/templates/warlock/src/app/users/controllers/auth/admin-login.ts +40 -40
  16. package/templates/warlock/src/app/users/controllers/auth/login.request.ts +28 -49
  17. package/templates/warlock/src/app/users/controllers/auth/logout.ts +10 -10
  18. package/templates/warlock/src/app/users/controllers/auth/register.request.ts +24 -0
  19. package/templates/warlock/src/app/users/controllers/auth/resend-activation-code.ts +45 -45
  20. package/templates/warlock/src/app/users/controllers/auth/reset-password.ts +43 -43
  21. package/templates/warlock/src/app/users/controllers/auth/verify-forget-password-code.ts +18 -18
  22. package/templates/warlock/src/app/users/controllers/profile/change-password.ts +31 -31
  23. package/templates/warlock/src/app/users/controllers/profile/my-profile.ts +10 -10
  24. package/templates/warlock/src/app/users/controllers/profile/update-profile.ts +25 -25
  25. package/templates/warlock/src/app/users/controllers/restful-users.ts +26 -26
  26. package/templates/warlock/src/app/users/events/attach-user-to-response.ts +18 -18
  27. package/templates/warlock/src/app/users/events/register-current-user-to-model-authors.ts +28 -28
  28. package/templates/warlock/src/app/users/events/update-authors.ts +19 -19
  29. package/templates/warlock/src/app/users/mail/send-forget-password-email.ts +20 -20
  30. package/templates/warlock/src/app/users/models/user/index.ts +1 -1
  31. package/templates/warlock/src/app/users/models/user/migrations/20-10-2024_07-59-54-user.migration.ts +15 -15
  32. package/templates/warlock/src/app/users/models/user/user.model.ts +59 -54
  33. package/templates/warlock/src/app/users/output/user.output.ts +12 -12
  34. package/templates/warlock/src/app/users/routes.ts +51 -51
  35. package/templates/warlock/src/app/users/utils/locales.ts +16 -16
  36. package/templates/warlock/src/app/utils/output.ts +18 -18
  37. package/templates/warlock/src/app/utils/router.ts +104 -104
  38. package/templates/warlock/src/config/database.ts +4 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-warlock",
3
- "version": "2.6.1",
3
+ "version": "2.7.0",
4
4
  "main": "./esm/index.js",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -0,0 +1,39 @@
1
+ # App Configurations
2
+ APP_NAME="gym-management"
3
+ LOCALE_CODE=en
4
+
5
+ TIMEZONE=UTC
6
+
7
+ # Http Configurations
8
+ HTTP_PORT=2030
9
+ HTTP_HOST=127.0.0.1
10
+ BASE_URL=http://${HOST}:${PORT}
11
+
12
+ # Database Configurations
13
+ DB_AUTH=admin
14
+ DB_PORT=27017
15
+ DB_HOST=127.0.0.1
16
+ DB_NAME=gym-management
17
+ DB_USERNAME=root
18
+ DB_PASSWORD=root
19
+
20
+ # Cache
21
+ CACHE_DRIVER=memory
22
+ ## Redis
23
+ REDIS_HOST=127.0.0.1
24
+ REDIS_PORT=6379
25
+ # or using redis url
26
+ #REDIS_URL=
27
+
28
+ # Mail
29
+ MAIL_HOST=
30
+ MAIL_PORT=465
31
+ MAIL_ENCRYPTION=ssl
32
+ MAIL_SECURE=true
33
+ MAIL_USERNAME=
34
+ MAIL_PASSWORD=
35
+ MAIL_FROM_NAME=${APP_NAME}
36
+ MAIL_FROM_ADDRESS=
37
+
38
+ # JWT Secret
39
+ JWT_SECRET=5Ulrs4caSEMqL5SwH41QdBOAC0NFCGnf
@@ -1,36 +1,36 @@
1
- # App Configurations
2
- APP_NAME="appName"
3
- LOCALE_CODE=en
4
-
5
- TIMEZONE=UTC
6
-
7
- # Http Configurations
8
- HTTP_PORT=1911
9
- HTTP_HOST=127.0.0.1
10
- BASE_URL=http://${HOST}:${PORT}
11
-
12
- # Database Configurations
13
- DB_AUTH=admin
14
- DB_PORT=27017
15
- DB_HOST=127.0.0.1
16
- DB_NAME=appName
17
- DB_USERNAME=root
18
- DB_PASSWORD=root
19
-
20
- # Cache
21
- CACHE_DRIVER=memory
22
- ## Redis
23
- REDIS_HOST=127.0.0.1
24
- REDIS_PORT=6379
25
- # or using redis url
26
- #REDIS_URL=
27
-
28
- # Mail
29
- MAIL_HOST=
30
- MAIL_PORT=465
31
- MAIL_ENCRYPTION=ssl
32
- MAIL_SECURE=true
33
- MAIL_USERNAME=
34
- MAIL_PASSWORD=
35
- MAIL_FROM_NAME=${APP_NAME}
1
+ # App Configurations
2
+ APP_NAME="appName"
3
+ LOCALE_CODE=en
4
+
5
+ TIMEZONE=UTC
6
+
7
+ # Http Configurations
8
+ HTTP_PORT=2030
9
+ HTTP_HOST=127.0.0.1
10
+ BASE_URL=http://${HOST}:${PORT}
11
+
12
+ # Database Configurations
13
+ DB_AUTH=admin
14
+ DB_PORT=27017
15
+ DB_HOST=127.0.0.1
16
+ DB_NAME=appName
17
+ DB_USERNAME=root
18
+ DB_PASSWORD=root
19
+
20
+ # Cache
21
+ CACHE_DRIVER=memory
22
+ ## Redis
23
+ REDIS_HOST=127.0.0.1
24
+ REDIS_PORT=6379
25
+ # or using redis url
26
+ #REDIS_URL=
27
+
28
+ # Mail
29
+ MAIL_HOST=
30
+ MAIL_PORT=465
31
+ MAIL_ENCRYPTION=ssl
32
+ MAIL_SECURE=true
33
+ MAIL_USERNAME=
34
+ MAIL_PASSWORD=
35
+ MAIL_FROM_NAME=${APP_NAME}
36
36
  MAIL_FROM_ADDRESS=
@@ -1 +1 @@
1
- * text=auto eol=lf
1
+ * text=auto eol=lf
@@ -3,7 +3,7 @@
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
5
  "scripts": {
6
- "start": "warlock dev",
6
+ "dev": "warlock dev",
7
7
  "build": "tsc && warlock build",
8
8
  "prod": "warlock start",
9
9
  "postman": "warlock postman",
@@ -17,7 +17,8 @@
17
17
  "lint": "npx eslint --fix ./src --max-warnings=0",
18
18
  "format": "npx prettier --write ./src/**/*.{js,jsx,ts,tsx,css,md,json} --config ./.prettierrc.json",
19
19
  "tsc": "npx tsc --noEmit",
20
- "prepare": "huskier-init && husky install"
20
+ "prepare": "huskier-init && husky install",
21
+ "lf": "find . -type d ( -name 'node_modules' -o -name '.git' ) -prune -o -type f -exec dos2unix {} ;"
21
22
  },
22
23
  "dependencies": {
23
24
  "@mongez/collection": "^1.2.0",
@@ -28,11 +29,12 @@
28
29
  "@mongez/dotenv": "^1.1.9",
29
30
  "@mongez/config": "^1.0.26",
30
31
  "@mongez/supportive-is": "^2.0.4",
31
- "@warlock.js/auth": "2.6.1",
32
- "@warlock.js/cache": "2.6.1",
33
- "@warlock.js/cascade": "2.6.1",
34
- "@warlock.js/core": "2.6.1",
35
- "@warlock.js/logger": "2.6.1",
32
+ "@warlock.js/auth": "2.7.0",
33
+ "@warlock.js/cache": "2.7.0",
34
+ "@warlock.js/cascade": "2.7.0",
35
+ "@warlock.js/core": "2.7.0",
36
+ "@warlock.js/logger": "2.7.0",
37
+ "@faker-js/faker": "^9.2.0",
36
38
  "dayjs": "^1.11.13"
37
39
  },
38
40
  "devDependencies": {
@@ -1,12 +1,43 @@
1
- // this file is called before any main file in the other modules
2
- // This will be called directly when the app starts
3
- import { onceConnected } from "@warlock.js/cascade";
4
-
5
- // This function will be called once the app is connected to the database
6
- // it will be called on app start
7
- // If the app is running in development mode, this function will be called
8
- // every time a file is changed
9
- // it could be useful to test some code or do small database modifications
10
- onceConnected(() => {
11
- //
12
- });
1
+ // this file is called before any main file in the other modules
2
+ // This will be called directly when the app starts
3
+ import { onceConnected } from "@warlock.js/cascade";
4
+ import { Post } from "./posts/models";
5
+ import { User } from "./users/models/user";
6
+
7
+ // This function will be called once the app is connected to the database
8
+ // it will be called on app start
9
+ // If the app is running in development mode, this function will be called
10
+ // every time a file is changed
11
+ // it could be useful to test some code or do small database modifications
12
+ onceConnected(async () => {
13
+ const user = await User.findOrCreate(
14
+ {
15
+ email: "hassanzohdy@gmail.com",
16
+ },
17
+ {
18
+ name: "Hasan Zohdy",
19
+ email: "hassanzohdy@gmail.com",
20
+ password: "123456",
21
+ },
22
+ );
23
+
24
+ await Post.create({
25
+ author: user,
26
+ title: "My first post",
27
+ content: "This is my first post",
28
+ });
29
+
30
+ await Post.create({
31
+ author: user,
32
+ title: "My second post",
33
+ content: "This is my second post",
34
+ });
35
+
36
+ await Post.create({
37
+ author: user,
38
+ title: "My third post",
39
+ content: "This is my third post",
40
+ });
41
+
42
+ console.log("Done");
43
+ });
@@ -0,0 +1,26 @@
1
+ import {
2
+ v,
3
+ type Request,
4
+ type RequestHandler,
5
+ type Response,
6
+ } from "@warlock.js/core";
7
+ import { Post } from "../models";
8
+
9
+ export const createNewPostRequest: RequestHandler = async (
10
+ request: Request,
11
+ response: Response,
12
+ ) => {
13
+ const post = await Post.create(request.validated());
14
+
15
+ return response.success({
16
+ message: "Post created successfully",
17
+ post,
18
+ });
19
+ };
20
+
21
+ createNewPostRequest.validation = {
22
+ schema: v.object({
23
+ title: v.string().required().minLength(4),
24
+ content: v.string().required(),
25
+ }),
26
+ };
@@ -0,0 +1,17 @@
1
+ import {
2
+ type Request,
3
+ type RequestHandler,
4
+ type Response,
5
+ } from "@warlock.js/core";
6
+ import { Post } from "../models";
7
+
8
+ export const getAllPostsRequest: RequestHandler = async (
9
+ request: Request,
10
+ response: Response,
11
+ ) => {
12
+ const posts = await Post.list();
13
+
14
+ return response.success({
15
+ posts,
16
+ });
17
+ };
@@ -0,0 +1,37 @@
1
+ import {
2
+ v,
3
+ type Request,
4
+ type RequestHandler,
5
+ type Response,
6
+ } from "@warlock.js/core";
7
+ import { Post } from "../models";
8
+
9
+ export const getPostRequest: RequestHandler = async (
10
+ request: Request,
11
+ response: Response,
12
+ ) => {
13
+ // 👇 look at the custom validation function
14
+ const post: Post = request.post;
15
+
16
+ return response.success({
17
+ post,
18
+ });
19
+ };
20
+
21
+ getPostRequest.validation = {
22
+ schema: v.object({
23
+ id: v.int().required(),
24
+ }),
25
+ validate: async (request: Request, response: Response) => {
26
+ const post = await Post.find(request.int("id"));
27
+
28
+ if (!post) {
29
+ return response.notFound({
30
+ error: "Post Not found",
31
+ });
32
+ }
33
+
34
+ // inject the post into the request object
35
+ request.post = post;
36
+ },
37
+ };
@@ -0,0 +1 @@
1
+ export * from "./post.model";
@@ -0,0 +1,22 @@
1
+ import { Model, type Casts } from "@warlock.js/cascade";
2
+ import { PostOutput } from "../output/post.output";
3
+
4
+ export class Post extends Model {
5
+ /**
6
+ * Collection name
7
+ */
8
+ public static collection = "posts";
9
+
10
+ /**
11
+ * Output
12
+ */
13
+ public static output = PostOutput;
14
+
15
+ /**
16
+ * Casts
17
+ */
18
+ protected casts: Casts = {
19
+ title: "string",
20
+ content: "string",
21
+ };
22
+ }
@@ -0,0 +1,13 @@
1
+ import { type FinalOutput, Output } from "@warlock.js/core";
2
+
3
+ export class PostOutput extends Output {
4
+ /**
5
+ * {@inheritdoc}
6
+ */
7
+ protected output: FinalOutput = {
8
+ id: "int",
9
+ title: "string",
10
+ content: "string",
11
+ createdAt: "date",
12
+ };
13
+ }
@@ -0,0 +1,12 @@
1
+ import { router } from "@warlock.js/core";
2
+ import { guarded } from "../utils/router";
3
+ import { createNewPostRequest } from "./controllers/create-new-post.request";
4
+ import { getAllPostsRequest } from "./controllers/get-all-posts.request";
5
+ import { getPostRequest } from "./controllers/get-post.request";
6
+
7
+ router.get("/posts", getAllPostsRequest);
8
+ router.get("/posts/:id", getPostRequest);
9
+
10
+ guarded(() => {
11
+ router.post("/posts", createNewPostRequest);
12
+ });
@@ -1,27 +1,27 @@
1
- import {
2
- deleteFile,
3
- getUploadedFile,
4
- getUploadedFileUsingHash,
5
- router,
6
- uploadChunkedFiles,
7
- uploadFiles,
8
- } from "@warlock.js/core";
9
- import { adminPath, guarded } from "app/utils/router";
10
-
11
- guarded(() => {
12
- // Upload files
13
- router.post(["/uploads", adminPath("/uploads")], uploadFiles);
14
- // Upload chunked files
15
- router.post(
16
- ["/uploads/chunks", adminPath("/uploads/chunks")],
17
- uploadChunkedFiles,
18
- );
19
- // Delete file by hash from the database
20
- router.delete(["/uploads/:hash", adminPath("/uploads/:hash")], deleteFile);
21
- });
22
-
23
- // Please note that the uploaded files should not be grouped in protected middleware i.e guarded with JWT
24
- // Get uploaded file using the file path directly
25
- router.get("/uploads/*", getUploadedFile);
26
- // Get uploaded file using hash
27
- router.get("/uploads/:hash", getUploadedFileUsingHash);
1
+ import {
2
+ deleteFile,
3
+ getUploadedFile,
4
+ getUploadedFileUsingHash,
5
+ router,
6
+ uploadChunkedFiles,
7
+ uploadFiles,
8
+ } from "@warlock.js/core";
9
+ import { adminPath, guarded } from "app/utils/router";
10
+
11
+ guarded(() => {
12
+ // Upload files
13
+ router.post(["/uploads", adminPath("/uploads")], uploadFiles);
14
+ // Upload chunked files
15
+ router.post(
16
+ ["/uploads/chunks", adminPath("/uploads/chunks")],
17
+ uploadChunkedFiles,
18
+ );
19
+ // Delete file by hash from the database
20
+ router.delete(["/uploads/:hash", adminPath("/uploads/:hash")], deleteFile);
21
+ });
22
+
23
+ // Please note that the uploaded files should not be grouped in protected middleware i.e guarded with JWT
24
+ // Get uploaded file using the file path directly
25
+ router.get("/uploads/*", getUploadedFile);
26
+ // Get uploaded file using hash
27
+ router.get("/uploads/:hash", getUploadedFileUsingHash);
@@ -1,40 +1,40 @@
1
- import type { Request, Response } from "@warlock.js/core";
2
- import { User } from "app/users/models/user";
3
-
4
- export default async function adminLogin(request: Request, response: Response) {
5
- const user = request.user;
6
-
7
- const auth = await user.generateAccessToken();
8
-
9
- return response.success({
10
- user: {
11
- ...(await user.toJSON()),
12
- accessToken: auth,
13
- userType: user.userType,
14
- },
15
- });
16
- }
17
-
18
- adminLogin.validation = {
19
- rules: {
20
- password: ["required"],
21
- email: ["required", "email"],
22
- },
23
- validate: async (request: Request, response: Response) => {
24
- const user = await User.attempt(request.only(["email", "password"]));
25
-
26
- if (!user) {
27
- return response.badRequest({
28
- error: "Invalid credentials",
29
- });
30
- }
31
-
32
- if (!user.get("isActive")) {
33
- return response.badRequest({
34
- error: "Your account is suspended!",
35
- });
36
- }
37
-
38
- request.user = user;
39
- },
40
- };
1
+ import type { Request, Response } from "@warlock.js/core";
2
+ import { User } from "app/users/models/user";
3
+
4
+ export default async function adminLogin(request: Request, response: Response) {
5
+ const user = request.user;
6
+
7
+ const auth = await user.generateAccessToken();
8
+
9
+ return response.success({
10
+ user: {
11
+ ...(await user.toJSON()),
12
+ accessToken: auth,
13
+ userType: user.userType,
14
+ },
15
+ });
16
+ }
17
+
18
+ adminLogin.validation = {
19
+ rules: {
20
+ password: ["required"],
21
+ email: ["required", "email"],
22
+ },
23
+ validate: async (request: Request, response: Response) => {
24
+ const user = await User.attempt(request.only(["email", "password"]));
25
+
26
+ if (!user) {
27
+ return response.badRequest({
28
+ error: "Invalid credentials",
29
+ });
30
+ }
31
+
32
+ if (!user.get("isActive")) {
33
+ return response.badRequest({
34
+ error: "Your account is suspended!",
35
+ });
36
+ }
37
+
38
+ request.user = user;
39
+ },
40
+ };
@@ -1,49 +1,28 @@
1
- import { t, type Request, type Response } from "@warlock.js/core";
2
- import { User } from "app/users/models/user";
3
-
4
- export default async function login(
5
- request: Request<User>,
6
- response: Response,
7
- ) {
8
- const user = request.user;
9
-
10
- const auth = await user.generateAccessToken();
11
-
12
- user.save({
13
- lastLogin: new Date(),
14
- });
15
-
16
- return response.success({
17
- user: {
18
- ...(await user.toJSON()),
19
- accessToken: auth,
20
- userType: user.userType,
21
- },
22
- });
23
- }
24
-
25
- login.validation = {
26
- rules: {
27
- email: ["required", "email"],
28
- password: ["required", "string"],
29
- },
30
- validate: async (request: Request, response: Response) => {
31
- const user = await User.attempt(request.only(["email", "password"]));
32
-
33
- if (!user) {
34
- return response.badRequest({
35
- error: t("auth.invalidCredentials"),
36
- });
37
- }
38
-
39
- if (!user.isActive) {
40
- // you can send the activation code again
41
- // or just return a bad request with an error message
42
- return response.forbidden({
43
- error: t("auth.accountNotActivated"),
44
- });
45
- }
46
-
47
- request.user = user;
48
- },
49
- };
1
+ import {
2
+ type Request,
3
+ type RequestHandler,
4
+ type Response,
5
+ } from "@warlock.js/core";
6
+ import { User } from "app/users/models/user";
7
+
8
+ export const loginRequest: RequestHandler = async (
9
+ request: Request,
10
+ response: Response,
11
+ ) => {
12
+ const user = await User.attempt(request.only(["email", "password"]));
13
+
14
+ if (!user) {
15
+ return response.badRequest({
16
+ message: "Invalid credentials",
17
+ });
18
+ }
19
+
20
+ // generate a JWT token for the logged-in user
21
+ const token = await user.generateAccessToken();
22
+
23
+ return response.success({
24
+ message: "User logged in successfully",
25
+ user,
26
+ accessToken: token,
27
+ });
28
+ };
@@ -1,10 +1,10 @@
1
- import type { Request, Response } from "@warlock.js/core";
2
- import type { User } from "app/users/models/user";
3
-
4
- export default function logout(request: Request<User>, response: Response) {
5
- const user = request.user;
6
-
7
- user.removeAccessToken(request.accessToken);
8
-
9
- return response.success();
10
- }
1
+ import type { Request, Response } from "@warlock.js/core";
2
+ import type { User } from "app/users/models/user";
3
+
4
+ export default function logout(request: Request<User>, response: Response) {
5
+ const user = request.user;
6
+
7
+ user.removeAccessToken(request.accessToken);
8
+
9
+ return response.success();
10
+ }
@@ -0,0 +1,24 @@
1
+ import { Random } from "@mongez/reinforcements";
2
+ import type { RequestHandler } from "@warlock.js/core";
3
+ import { v, type Request, type Response } from "@warlock.js/core";
4
+ import { User } from "app/users/models/user";
5
+
6
+ export const registerRequest: RequestHandler = async (
7
+ request: Request,
8
+ response: Response,
9
+ ) => {
10
+ User.create({
11
+ ...request.validated(),
12
+ activationCode: Random.int(100000, 999999),
13
+ });
14
+
15
+ return response.success();
16
+ };
17
+
18
+ registerRequest.validation = {
19
+ schema: v.object({
20
+ name: v.string().minLength(2).required(),
21
+ email: v.string().email().required().unique(User),
22
+ password: v.string().minLength(8).required(),
23
+ }),
24
+ };