create-warlock 4.2.6 โ 4.2.7
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/CHANGELOG.md +6 -0
- package/package.json +2 -2
- package/templates/warlock/.env.example +36 -0
- package/templates/warlock/.gitattributes +1 -0
- package/templates/warlock/.husky/pre-commit +4 -0
- package/templates/warlock/.prettierignore +4 -0
- package/templates/warlock/.prettierrc.json +10 -0
- package/templates/warlock/.vscode/settings.json +41 -0
- package/templates/warlock/README.md +57 -0
- package/templates/warlock/_.gitignore +6 -0
- package/templates/warlock/docs/new-module.md +551 -0
- package/templates/warlock/eslint.config.js +98 -0
- package/templates/warlock/package.json +74 -0
- package/templates/warlock/public/home.css +523 -0
- package/templates/warlock/skills/api-design/SKILL.md +461 -0
- package/templates/warlock/skills/code-standards/SKILL.md +595 -0
- package/templates/warlock/skills/data-and-persistence/SKILL.md +330 -0
- package/templates/warlock/skills/git-workflow/SKILL.md +282 -0
- package/templates/warlock/skills/module-boundaries/SKILL.md +283 -0
- package/templates/warlock/skills/observability-and-resilience/SKILL.md +306 -0
- package/templates/warlock/skills/security-baseline/SKILL.md +352 -0
- package/templates/warlock/skills/testing-strategy/SKILL.md +323 -0
- package/templates/warlock/src/app/auth/controllers/forgot-password.controller.ts +28 -0
- package/templates/warlock/src/app/auth/controllers/login.controller.ts +22 -0
- package/templates/warlock/src/app/auth/controllers/logout-all.controller.ts +16 -0
- package/templates/warlock/src/app/auth/controllers/logout.controller.ts +16 -0
- package/templates/warlock/src/app/auth/controllers/me.controller.ts +13 -0
- package/templates/warlock/src/app/auth/controllers/refresh-token.controller.ts +29 -0
- package/templates/warlock/src/app/auth/controllers/reset-password.controller.ts +23 -0
- package/templates/warlock/src/app/auth/main.ts +9 -0
- package/templates/warlock/src/app/auth/models/otp/index.ts +1 -0
- package/templates/warlock/src/app/auth/models/otp/migrations/22-12-2025_10-30-20.otp-migration.ts +30 -0
- package/templates/warlock/src/app/auth/models/otp/otp.model.ts +69 -0
- package/templates/warlock/src/app/auth/requests/guarded.request.ts +10 -0
- package/templates/warlock/src/app/auth/routes.ts +22 -0
- package/templates/warlock/src/app/auth/schema/login.schema.ts +8 -0
- package/templates/warlock/src/app/auth/schema/reset-password.schema.ts +9 -0
- package/templates/warlock/src/app/auth/services/auth.service.ts +66 -0
- package/templates/warlock/src/app/auth/services/forgot-password.service.ts +28 -0
- package/templates/warlock/src/app/auth/services/otp.service.ts +173 -0
- package/templates/warlock/src/app/auth/services/reset-password.service.ts +39 -0
- package/templates/warlock/src/app/auth/utils/auth-error-code.ts +6 -0
- package/templates/warlock/src/app/auth/utils/locales.ts +89 -0
- package/templates/warlock/src/app/auth/utils/types.ts +14 -0
- package/templates/warlock/src/app/posts/controllers/create-new-post.controller.ts +21 -0
- package/templates/warlock/src/app/posts/controllers/update-post.controller.ts +30 -0
- package/templates/warlock/src/app/posts/models/post/migrations/09-01-2026_02-07-51-post.migration.ts +15 -0
- package/templates/warlock/src/app/posts/models/post/post.model.ts +23 -0
- package/templates/warlock/src/app/posts/resources/post.resource.ts +14 -0
- package/templates/warlock/src/app/posts/routes.ts +8 -0
- package/templates/warlock/src/app/posts/schema/create-post.schema.ts +9 -0
- package/templates/warlock/src/app/posts/schema/update-post.schema.ts +9 -0
- package/templates/warlock/src/app/shared/components/HomePageComponent.tsx +229 -0
- package/templates/warlock/src/app/shared/controllers/home-page.controller.ts +18 -0
- package/templates/warlock/src/app/shared/controllers/home-page.controller.tsx +8 -0
- package/templates/warlock/src/app/shared/routes.ts +4 -0
- package/templates/warlock/src/app/shared/services/scheduler.service.ts +3 -0
- package/templates/warlock/src/app/shared/tests/infrastructure.test.ts +22 -0
- package/templates/warlock/src/app/shared/utils/global-columns-schema.ts +8 -0
- package/templates/warlock/src/app/shared/utils/locales.ts +766 -0
- package/templates/warlock/src/app/shared/utils/router.ts +30 -0
- package/templates/warlock/src/app/uploads/controllers/fetch-uploaded-file.controller.ts +33 -0
- package/templates/warlock/src/app/uploads/routes.ts +4 -0
- package/templates/warlock/src/app/users/commands/hello-world.command.ts +8 -0
- package/templates/warlock/src/app/users/controllers/create-new-user.controller.ts +27 -0
- package/templates/warlock/src/app/users/controllers/list-users.controller.ts +12 -0
- package/templates/warlock/src/app/users/events/inject-created-by-user.into-model.event.ts +32 -0
- package/templates/warlock/src/app/users/events/sync.ts +5 -0
- package/templates/warlock/src/app/users/main.ts +5 -0
- package/templates/warlock/src/app/users/models/user/index.ts +1 -0
- package/templates/warlock/src/app/users/models/user/migrations/11-12-2025_23-58-03-user.migration.ts +15 -0
- package/templates/warlock/src/app/users/models/user/user.model.ts +64 -0
- package/templates/warlock/src/app/users/repositories/users.repository.ts +23 -0
- package/templates/warlock/src/app/users/resources/user.resource.ts +14 -0
- package/templates/warlock/src/app/users/routes.ts +8 -0
- package/templates/warlock/src/app/users/schema/create-user.schema.ts +11 -0
- package/templates/warlock/src/app/users/seeds/users.seed.ts +21 -0
- package/templates/warlock/src/app/users/services/get-users.service.ts +5 -0
- package/templates/warlock/src/app/users/services/list-users.service.ts +17 -0
- package/templates/warlock/src/app/users/services/login-social.ts +19 -0
- package/templates/warlock/src/config/app.ts +12 -0
- package/templates/warlock/src/config/auth.ts +20 -0
- package/templates/warlock/src/config/cache.ts +59 -0
- package/templates/warlock/src/config/database.ts +65 -0
- package/templates/warlock/src/config/http.ts +23 -0
- package/templates/warlock/src/config/log.ts +22 -0
- package/templates/warlock/src/config/mail.ts +16 -0
- package/templates/warlock/src/config/repository.ts +11 -0
- package/templates/warlock/src/config/storage.ts +34 -0
- package/templates/warlock/src/config/tests.ts +5 -0
- package/templates/warlock/src/config/validation.ts +7 -0
- package/templates/warlock/storage/.gitignore +2 -0
- package/templates/warlock/tsconfig.json +27 -0
- package/templates/warlock/warlock.config.ts +15 -0
- package/templates/warlock/yarn.lock +2332 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { groupedTranslations } from "@warlock.js/core";
|
|
2
|
+
|
|
3
|
+
groupedTranslations("auth", {
|
|
4
|
+
// App-level translations
|
|
5
|
+
invalidCredentials: {
|
|
6
|
+
en: "Invalid email or password",
|
|
7
|
+
ar: "ุงูุจุฑูุฏ ุงูุงููุชุฑููู ุฃู ููู
ุฉ ุงูู
ุฑูุฑ ุบูุฑ ุตุญูุญุฉ",
|
|
8
|
+
},
|
|
9
|
+
loggedOut: {
|
|
10
|
+
en: "Logged out successfully",
|
|
11
|
+
ar: "ุชู
ุชุณุฌูู ุงูุฎุฑูุฌ ุจูุฌุงุญ",
|
|
12
|
+
},
|
|
13
|
+
loggedOutAll: {
|
|
14
|
+
en: "Logged out from all devices",
|
|
15
|
+
ar: "ุชู
ุชุณุฌูู ุงูุฎุฑูุฌ ู
ู ุฌู
ูุน ุงูุฃุฌูุฒุฉ",
|
|
16
|
+
},
|
|
17
|
+
refreshTokenRequired: {
|
|
18
|
+
en: "Refresh token is required",
|
|
19
|
+
ar: "ุฑู
ุฒ ุงูุชุญุฏูุซ ู
ุทููุจ",
|
|
20
|
+
},
|
|
21
|
+
invalidRefreshToken: {
|
|
22
|
+
en: "Invalid or expired refresh token",
|
|
23
|
+
ar: "ุฑู
ุฒ ุงูุชุญุฏูุซ ุบูุฑ ุตุงูุญ ุฃู ู
ูุชูู ุงูุตูุงุญูุฉ",
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
userNotFound: {
|
|
27
|
+
en: "User not found",
|
|
28
|
+
ar: "ุงูู
ุณุชุฎุฏู
ุบูุฑ ู
ูุฌูุฏ",
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
// OTP translations
|
|
32
|
+
otpSent: {
|
|
33
|
+
en: "Verification code sent",
|
|
34
|
+
ar: "ุชู
ุฅุฑุณุงู ุฑู
ุฒ ุงูุชุญูู",
|
|
35
|
+
},
|
|
36
|
+
missingOtp: {
|
|
37
|
+
en: "Verification code not found",
|
|
38
|
+
ar: "ุฑู
ุฒ ุงูุชุญูู ุบูุฑ ู
ูุฌูุฏ",
|
|
39
|
+
},
|
|
40
|
+
otpInvalid: {
|
|
41
|
+
en: "Invalid verification code",
|
|
42
|
+
ar: "ุฑู
ุฒ ุงูุชุญูู ุบูุฑ ุตุงูุญ",
|
|
43
|
+
},
|
|
44
|
+
otpExpired: {
|
|
45
|
+
en: "Verification code has expired",
|
|
46
|
+
ar: "ุฑู
ุฒ ุงูุชุญูู ู
ูุชูู ุงูุตูุงุญูุฉ",
|
|
47
|
+
},
|
|
48
|
+
otpMaxAttempts: {
|
|
49
|
+
en: "Too many failed attempts",
|
|
50
|
+
ar: "ุนุฏุฏ ุงูู
ุญุงููุงุช ุชุฌุงูุฒ ุงูุญุฏ ุงูู
ุณู
ูุญ",
|
|
51
|
+
},
|
|
52
|
+
passwordResetSuccess: {
|
|
53
|
+
en: "Password reset successfully",
|
|
54
|
+
ar: "ุชู
ุฅุนุงุฏุฉ ุชุนููู ููู
ุฉ ุงูู
ุฑูุฑ ุจูุฌุงุญ",
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* ============================================
|
|
59
|
+
* @warlock.js/auth package translations
|
|
60
|
+
* ============================================
|
|
61
|
+
* The following translations are used by the @warlock.js/auth package
|
|
62
|
+
* in the auth middleware. They must be defined here so they can be
|
|
63
|
+
* translated in your application.
|
|
64
|
+
*/
|
|
65
|
+
errors: {
|
|
66
|
+
/**
|
|
67
|
+
* Called when the access token is missing from Authorization header
|
|
68
|
+
*/
|
|
69
|
+
missingAccessToken: {
|
|
70
|
+
en: "Access token is required",
|
|
71
|
+
ar: "ุฑู
ุฒ ุงููุตูู ู
ุทููุจ",
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* Called when an access token is invalid or expired
|
|
75
|
+
*/
|
|
76
|
+
invalidAccessToken: {
|
|
77
|
+
en: "Invalid or expired access token",
|
|
78
|
+
ar: "ุฑู
ุฒ ุงููุตูู ุบูุฑ ุตุงูุญ ุฃู ู
ูุชูู ุงูุตูุงุญูุฉ",
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* Called when the current user type is not authorized to
|
|
82
|
+
* access a protected resource for certain user types
|
|
83
|
+
*/
|
|
84
|
+
unauthorized: {
|
|
85
|
+
en: "You are not authorized to access this resource",
|
|
86
|
+
ar: "ุบูุฑ ู
ุตุฑุญ ูู ุจุงููุตูู ุฅูู ูุฐุง ุงูู
ูุฑุฏ",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTP delivery channels
|
|
3
|
+
*/
|
|
4
|
+
export type OTPChannel = "email" | "sms" | "whatsapp" | "push";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Common OTP types
|
|
8
|
+
*/
|
|
9
|
+
export type OTPType =
|
|
10
|
+
| "password-reset"
|
|
11
|
+
| "email-verification"
|
|
12
|
+
| "phone-verification"
|
|
13
|
+
| "two-factor"
|
|
14
|
+
| string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type GuardedRequestHandler } from "app/auth/requests/guarded.request";
|
|
2
|
+
import { Post } from "../models/post/post.model";
|
|
3
|
+
import { type CreatePostSchema, createPostSchema } from "../schema/create-post.schema";
|
|
4
|
+
|
|
5
|
+
export const createNewPostController: GuardedRequestHandler<CreatePostSchema> = async (
|
|
6
|
+
request,
|
|
7
|
+
response,
|
|
8
|
+
) => {
|
|
9
|
+
const post = await Post.create({
|
|
10
|
+
...request.validated(),
|
|
11
|
+
authorId: request.user.id,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return response.successCreate({
|
|
15
|
+
post,
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
createNewPostController.validation = {
|
|
20
|
+
schema: createPostSchema,
|
|
21
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type GuardedRequestHandler } from "app/auth/requests/guarded.request";
|
|
2
|
+
import { Post } from "../models/post/post.model";
|
|
3
|
+
import { type UpdatePostSchema, updatePostSchema } from "../schema/update-post.schema";
|
|
4
|
+
|
|
5
|
+
export const updatePostController: GuardedRequestHandler<UpdatePostSchema> = async (
|
|
6
|
+
request,
|
|
7
|
+
response,
|
|
8
|
+
) => {
|
|
9
|
+
const id = request.int("id");
|
|
10
|
+
|
|
11
|
+
if (!id) {
|
|
12
|
+
return response.notFound();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const post = await Post.find(id);
|
|
16
|
+
|
|
17
|
+
if (!post) {
|
|
18
|
+
return response.notFound();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
await post.save({ merge: request.validated() });
|
|
22
|
+
|
|
23
|
+
return response.success({
|
|
24
|
+
post,
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
updatePostController.validation = {
|
|
29
|
+
schema: updatePostSchema,
|
|
30
|
+
};
|
package/templates/warlock/src/app/posts/models/post/migrations/09-01-2026_02-07-51-post.migration.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { bool, integer, json, Migration, string, text, timestamp } from "@warlock.js/cascade";
|
|
2
|
+
import { Post } from "../post.model";
|
|
3
|
+
|
|
4
|
+
export default Migration.create(Post, {
|
|
5
|
+
title: string(255),
|
|
6
|
+
description: text(),
|
|
7
|
+
slug: string(255).unique(),
|
|
8
|
+
image: string(500).nullable(),
|
|
9
|
+
isActive: bool(),
|
|
10
|
+
authorId: integer().notNullable(),
|
|
11
|
+
createdBy: json().nullable(),
|
|
12
|
+
updatedBy: json().nullable(),
|
|
13
|
+
deletedBy: json().nullable(),
|
|
14
|
+
deletedAt: timestamp().nullable(),
|
|
15
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Model, RegisterModel } from "@warlock.js/cascade";
|
|
2
|
+
import { useComputedSlug } from "@warlock.js/core";
|
|
3
|
+
import { type Infer, v } from "@warlock.js/seal";
|
|
4
|
+
import { PostResource } from "app/posts/resources/post.resource";
|
|
5
|
+
import { globalColumnsSchema } from "app/shared/utils/global-columns-schema";
|
|
6
|
+
|
|
7
|
+
export const postSchema = globalColumnsSchema.extend({
|
|
8
|
+
title: v.string().required(),
|
|
9
|
+
description: v.string().required(),
|
|
10
|
+
slug: v.computed(useComputedSlug()),
|
|
11
|
+
image: v.string().required(),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
type PostSchema = Infer<typeof postSchema>;
|
|
15
|
+
|
|
16
|
+
@RegisterModel()
|
|
17
|
+
export class Post extends Model<PostSchema> {
|
|
18
|
+
public static table = "posts";
|
|
19
|
+
|
|
20
|
+
public static schema = postSchema;
|
|
21
|
+
|
|
22
|
+
public static resource = PostResource;
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineResource } from "@warlock.js/core";
|
|
2
|
+
|
|
3
|
+
export const PostResource = defineResource({
|
|
4
|
+
schema: {
|
|
5
|
+
id: "number",
|
|
6
|
+
slug: "string",
|
|
7
|
+
title: "string",
|
|
8
|
+
description: "string",
|
|
9
|
+
image: "storageUrl",
|
|
10
|
+
createdBy: "object",
|
|
11
|
+
updatedBy: "object",
|
|
12
|
+
isActive: "boolean",
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { router } from "@warlock.js/core";
|
|
2
|
+
import { guarded } from "app/shared/utils/router";
|
|
3
|
+
import { createNewPostController } from "./controllers/create-new-post.controller";
|
|
4
|
+
import { updatePostController } from "./controllers/update-post.controller";
|
|
5
|
+
|
|
6
|
+
guarded(() => {
|
|
7
|
+
router.route("/posts").create(createNewPostController).update(updatePostController);
|
|
8
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Infer, v } from "@warlock.js/seal";
|
|
2
|
+
|
|
3
|
+
export const createPostSchema = v.object({
|
|
4
|
+
title: v.string().required(),
|
|
5
|
+
description: v.string(),
|
|
6
|
+
image: v.file().image().maxSize({ size: 2, unit: "MB" }).saveTo("posts"),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export type CreatePostSchema = Infer<typeof createPostSchema>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Infer, v } from "@warlock.js/seal";
|
|
2
|
+
|
|
3
|
+
export const updatePostSchema = v.object({
|
|
4
|
+
title: v.string().required(),
|
|
5
|
+
description: v.string(),
|
|
6
|
+
image: v.file().image().maxSize({ size: 2, unit: "MB" }).saveTo("posts"),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export type UpdatePostSchema = Infer<typeof updatePostSchema>;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { Application, publicUrl } from "@warlock.js/core";
|
|
2
|
+
|
|
3
|
+
export function HomePageComponent() {
|
|
4
|
+
return (
|
|
5
|
+
<html>
|
|
6
|
+
<head>
|
|
7
|
+
<meta charSet="UTF-8" />
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
+
<title>Warlock.js - Modern Backend TypeScript Framework</title>
|
|
10
|
+
<meta
|
|
11
|
+
name="description"
|
|
12
|
+
content="A powerful, elegant TypeScript framework for building modern web applications with ease."
|
|
13
|
+
/>
|
|
14
|
+
<link rel="stylesheet" href={publicUrl("home.css")} />
|
|
15
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
16
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
|
17
|
+
<link
|
|
18
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap"
|
|
19
|
+
rel="stylesheet"
|
|
20
|
+
/>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<div className="warlock-home">
|
|
24
|
+
<div className="warlock-container">
|
|
25
|
+
{/* Header */}
|
|
26
|
+
<header className="warlock-header">
|
|
27
|
+
<a href="/" className="warlock-logo">
|
|
28
|
+
<span className="warlock-logo-icon">โก</span>
|
|
29
|
+
<span>Warlock.js</span>
|
|
30
|
+
</a>
|
|
31
|
+
<nav className="warlock-nav">
|
|
32
|
+
<a href="https://warlock.js.org" target="_blank" rel="noopener noreferrer">
|
|
33
|
+
Docs
|
|
34
|
+
</a>
|
|
35
|
+
<a href="https://github.com/warlockjs" target="_blank" rel="noopener noreferrer">
|
|
36
|
+
GitHub
|
|
37
|
+
</a>
|
|
38
|
+
<a href="https://discord.gg/x3W9SN2jvx" target="_blank" rel="noopener noreferrer">
|
|
39
|
+
Discord
|
|
40
|
+
</a>
|
|
41
|
+
</nav>
|
|
42
|
+
</header>
|
|
43
|
+
{/* Hero Section */}
|
|
44
|
+
<section className="warlock-hero">
|
|
45
|
+
<h1>
|
|
46
|
+
Build Modern Web Apps
|
|
47
|
+
<br />
|
|
48
|
+
with Confidence
|
|
49
|
+
</h1>
|
|
50
|
+
<p>
|
|
51
|
+
A powerful, elegant TypeScript framework designed for developers who demand
|
|
52
|
+
excellence. Ship faster, scale better, and enjoy the journey.
|
|
53
|
+
</p>
|
|
54
|
+
<div className="warlock-cta">
|
|
55
|
+
<a href="https://warlock.js.org" className="warlock-btn warlock-btn-primary">
|
|
56
|
+
<span>Get Started</span>
|
|
57
|
+
<span>โ</span>
|
|
58
|
+
</a>
|
|
59
|
+
<a
|
|
60
|
+
href="https://github.com/warlockjs"
|
|
61
|
+
className="warlock-btn warlock-btn-secondary"
|
|
62
|
+
>
|
|
63
|
+
<span>View on GitHub</span>
|
|
64
|
+
</a>
|
|
65
|
+
</div>
|
|
66
|
+
</section>
|
|
67
|
+
|
|
68
|
+
{/* Features Section */}
|
|
69
|
+
<section className="warlock-features">
|
|
70
|
+
<h2 className="warlock-section-title">Why Warlock.js?</h2>
|
|
71
|
+
<p className="warlock-section-subtitle">
|
|
72
|
+
Everything you need to build production-ready applications
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<div className="warlock-features-grid">
|
|
76
|
+
<div className="warlock-feature-card">
|
|
77
|
+
<span className="warlock-feature-icon">๐</span>
|
|
78
|
+
<h3>Lightning Fast</h3>
|
|
79
|
+
<p>
|
|
80
|
+
Blazing fast development server with instant hot reload. Build and deploy
|
|
81
|
+
optimized production bundles in seconds.
|
|
82
|
+
</p>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div className="warlock-feature-card">
|
|
86
|
+
<span className="warlock-feature-icon">๐ฏ</span>
|
|
87
|
+
<h3>Type-Safe</h3>
|
|
88
|
+
<p>
|
|
89
|
+
Built with TypeScript from the ground up. Enjoy full type safety across your
|
|
90
|
+
entire application with intelligent auto-completion.
|
|
91
|
+
</p>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div className="warlock-feature-card">
|
|
95
|
+
<span className="warlock-feature-icon">๐๏ธ</span>
|
|
96
|
+
<h3>Battle-Tested Architecture</h3>
|
|
97
|
+
<p>
|
|
98
|
+
Proven patterns and best practices baked in. From routing to database
|
|
99
|
+
management, we've got you covered.
|
|
100
|
+
</p>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div className="warlock-feature-card">
|
|
104
|
+
<span className="warlock-feature-icon">๐</span>
|
|
105
|
+
<h3>Powerful CLI</h3>
|
|
106
|
+
<p>
|
|
107
|
+
Scaffold components, run migrations, manage seeds, and more with an intuitive
|
|
108
|
+
command-line interface that boosts productivity.
|
|
109
|
+
</p>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div className="warlock-feature-card">
|
|
113
|
+
<span className="warlock-feature-icon">๐จ</span>
|
|
114
|
+
<h3>Flexible & Extensible</h3>
|
|
115
|
+
<p>
|
|
116
|
+
Plugin architecture allows you to extend core functionality. Build your own
|
|
117
|
+
tools or use community packages.
|
|
118
|
+
</p>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<div className="warlock-feature-card">
|
|
122
|
+
<span className="warlock-feature-icon">๐</span>
|
|
123
|
+
<h3>Multi-Tenant Ready</h3>
|
|
124
|
+
<p>
|
|
125
|
+
Built-in support for multi-tenancy. Scale from single to multi-tenant
|
|
126
|
+
applications without architectural changes.
|
|
127
|
+
</p>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
</section>
|
|
131
|
+
|
|
132
|
+
{/* Quick Start Section */}
|
|
133
|
+
<section className="warlock-quickstart">
|
|
134
|
+
<h2 className="warlock-section-title">Extend with Features</h2>
|
|
135
|
+
<p className="warlock-section-subtitle">
|
|
136
|
+
Add powerful features to your project instantly
|
|
137
|
+
</p>
|
|
138
|
+
|
|
139
|
+
<div className="warlock-code-block">
|
|
140
|
+
<div className="warlock-code-header">
|
|
141
|
+
<span className="warlock-code-dot"></span>
|
|
142
|
+
<span className="warlock-code-dot"></span>
|
|
143
|
+
<span className="warlock-code-dot"></span>
|
|
144
|
+
</div>
|
|
145
|
+
<div className="warlock-code-content">
|
|
146
|
+
<code className="warlock-code-line">
|
|
147
|
+
<span className="warlock-code-comment">
|
|
148
|
+
# Add React for rendering & email templates
|
|
149
|
+
</span>
|
|
150
|
+
</code>
|
|
151
|
+
<code className="warlock-code-line">
|
|
152
|
+
<span className="warlock-code-command">npx</span> warlock add{" "}
|
|
153
|
+
<span className="warlock-code-flag">react</span>
|
|
154
|
+
</code>
|
|
155
|
+
<code className="warlock-code-line"> </code>
|
|
156
|
+
<code className="warlock-code-line">
|
|
157
|
+
<span className="warlock-code-comment">
|
|
158
|
+
# Add MongoDB, Redis & testing support
|
|
159
|
+
</span>
|
|
160
|
+
</code>
|
|
161
|
+
<code className="warlock-code-line">
|
|
162
|
+
<span className="warlock-code-command">npx</span> warlock add{" "}
|
|
163
|
+
<span className="warlock-code-flag">mongodb redis test</span>
|
|
164
|
+
</code>
|
|
165
|
+
<code className="warlock-code-line"> </code>
|
|
166
|
+
<code className="warlock-code-line">
|
|
167
|
+
<span className="warlock-code-comment"># List all available features</span>
|
|
168
|
+
</code>
|
|
169
|
+
<code className="warlock-code-line">
|
|
170
|
+
<span className="warlock-code-command">npx</span> warlock add{" "}
|
|
171
|
+
<span className="warlock-code-flag">--list</span>
|
|
172
|
+
</code>
|
|
173
|
+
<code className="warlock-code-line"> </code>
|
|
174
|
+
<code className="warlock-code-line">
|
|
175
|
+
<span className="warlock-code-comment">
|
|
176
|
+
# โจ Features: react, mongodb, postgres, mysql, redis, s3, mail, image, test,
|
|
177
|
+
swagger, scheduler & more
|
|
178
|
+
</span>
|
|
179
|
+
</code>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</section>
|
|
183
|
+
|
|
184
|
+
{/* Footer */}
|
|
185
|
+
<footer className="warlock-footer">
|
|
186
|
+
<div className="warlock-social-links">
|
|
187
|
+
<a
|
|
188
|
+
href="https://discord.gg/x3W9SN2jvx"
|
|
189
|
+
className="warlock-social-link"
|
|
190
|
+
target="_blank"
|
|
191
|
+
rel="noopener noreferrer"
|
|
192
|
+
>
|
|
193
|
+
<span className="warlock-social-icon">๐ฌ</span>
|
|
194
|
+
<span>Join Discord</span>
|
|
195
|
+
</a>
|
|
196
|
+
<a
|
|
197
|
+
href="https://github.com/warlockjs"
|
|
198
|
+
className="warlock-social-link"
|
|
199
|
+
target="_blank"
|
|
200
|
+
rel="noopener noreferrer"
|
|
201
|
+
>
|
|
202
|
+
<span className="warlock-social-icon">โญ</span>
|
|
203
|
+
<span>Star on GitHub</span>
|
|
204
|
+
</a>
|
|
205
|
+
<a
|
|
206
|
+
href="https://warlock.js.org"
|
|
207
|
+
className="warlock-social-link"
|
|
208
|
+
target="_blank"
|
|
209
|
+
rel="noopener noreferrer"
|
|
210
|
+
>
|
|
211
|
+
<span className="warlock-social-icon">๐</span>
|
|
212
|
+
<span>Read Docs</span>
|
|
213
|
+
</a>
|
|
214
|
+
</div>
|
|
215
|
+
<p className="warlock-footer-text">
|
|
216
|
+
Built with โก by the{" "}
|
|
217
|
+
<a href="https://github.com/warlockjs" target="_blank" rel="noopener noreferrer">
|
|
218
|
+
Warlock.js Team
|
|
219
|
+
</a>
|
|
220
|
+
{" ยท "}
|
|
221
|
+
<span>v{Application.version}</span>
|
|
222
|
+
</p>
|
|
223
|
+
</footer>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
</body>
|
|
227
|
+
</html>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Application, type RequestHandler } from "@warlock.js/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default welcome route โ a dependency-free JSON response.
|
|
5
|
+
*
|
|
6
|
+
* Projects scaffolded with the `react` feature get the richer HTML welcome
|
|
7
|
+
* page (`home-page.controller.tsx` + `HomePageComponent.tsx`) instead; this
|
|
8
|
+
* plain controller is removed at scaffold time when React is selected.
|
|
9
|
+
*/
|
|
10
|
+
export const homePageController: RequestHandler = async (_request, response) => {
|
|
11
|
+
return response.success({
|
|
12
|
+
message: "Welcome to Warlock ๐ง โ your app is up and running!",
|
|
13
|
+
version: Application.version,
|
|
14
|
+
docs: "https://warlock.js.org",
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
homePageController.description = "Welcome Home Page";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Request, type RequestHandler, type Response } from "@warlock.js/core";
|
|
2
|
+
import { HomePageComponent } from "../components/HomePageComponent";
|
|
3
|
+
|
|
4
|
+
export const homePageController: RequestHandler = async (_request: Request, response: Response) => {
|
|
5
|
+
return response.render(<HomePageComponent />);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
homePageController.description = "Welcome Home Page";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sample test to verify test infrastructure
|
|
3
|
+
*/
|
|
4
|
+
import { testGet } from "@warlock.js/core";
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
|
|
7
|
+
describe("Test Infrastructure", () => {
|
|
8
|
+
it("should have database connection available", async () => {
|
|
9
|
+
// This test verifies the per-worker setup works
|
|
10
|
+
// The setupTest function should have initialized connectors
|
|
11
|
+
expect(true).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("should be able to make HTTP requests to test server", async () => {
|
|
15
|
+
// This test verifies the global HTTP server is running
|
|
16
|
+
const response = await testGet("/");
|
|
17
|
+
|
|
18
|
+
// We expect some response (even 404 is fine - means server is reachable)
|
|
19
|
+
expect(response.status).toBeDefined();
|
|
20
|
+
expect(response.headers.get("content-type")).toBe("text/html");
|
|
21
|
+
});
|
|
22
|
+
});
|