hightjs 0.3.5 → 0.4.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.
- package/README.md +1 -1
- package/dist/builder.js +60 -5
- package/dist/client/entry.client.js +59 -1
- package/dist/hotReload.js +83 -3
- package/dist/index.js +56 -45
- package/docs/checklist.md +1 -1
- package/docs/middlewares.md +1 -1
- package/docs/rotas-backend.md +3 -3
- package/docs/websocket.md +1 -1
- package/example/package-lock.json +1 -1
- package/example/src/backend/routes/auth.ts +3 -0
- package/example/src/{web/backend → backend}/routes/version.ts +1 -1
- package/example/src/web/components/Home.tsx +140 -0
- package/example/src/web/components/LoginPage.tsx +149 -0
- package/example/src/web/routes/index.tsx +1 -141
- package/example/src/web/routes/login.tsx +1 -146
- package/package.json +3 -1
- package/src/builder.js +66 -5
- package/src/client/entry.client.tsx +69 -2
- package/src/hotReload.ts +83 -3
- package/src/index.ts +66 -57
- package/example/src/web/backend/routes/auth.ts +0 -3
- /package/example/src/{auth.ts → backend/auth.ts} +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {useSession} from "hightjs/auth/react"
|
|
3
|
+
import { Link } from "hightjs/client";
|
|
4
|
+
export default function Home() {
|
|
5
|
+
const { data: session, status, signOut } = useSession();
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 bg-gradient-to-r from-black to-gray-500 text-gray-200 relative overflow-hidden">
|
|
10
|
+
<div className="absolute inset-0 -z-10 h-full w-full bg-gradient-to-r from-black to-gray-500 bg-[radial-gradient(circle_500px_at_50%_200px,#3e007555,transparent)]"></div>
|
|
11
|
+
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start z-10">
|
|
12
|
+
<div className="flex items-center gap-4">
|
|
13
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="38" height="38" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-purple-500"><path d="m12 3-8.9 5.06a4 4 0 0 0-1.1 5.44l1.1 1.94a4 4 0 0 0 5.44 1.1l8.9-5.06a4 4 0 0 0 1.1-5.44l-1.1-1.94a4 4 0 0 0-5.44-1.1z"></path></svg>
|
|
14
|
+
<h1 className="text-3xl font-bold text-purple-400 [text-shadow:_0_0_12px_theme(colors.purple.500)]">HightJS</h1>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div className="flex flex-col items-center gap-4 self-center">
|
|
18
|
+
{status === 'loading' && <p>Carregando...</p>}
|
|
19
|
+
{status === 'authenticated' && session?.user && (
|
|
20
|
+
<>
|
|
21
|
+
<p className="text-lg">Você está logado como amoraaaa <span className="font-bold text-purple-400">{session.user.name}</span>!</p>
|
|
22
|
+
<button
|
|
23
|
+
onClick={() => signOut({callbackUrl: '/'})}
|
|
24
|
+
className="rounded-full border border-solid border-transparent transition-all duration-300 flex items-center justify-center bg-purple-600 text-white gap-2 hover:bg-purple-500 font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-40 shadow-[0_0_15px_-3px_theme(colors.purple.600)] hover:shadow-[0_0_25px_-3px_theme(colors.purple.500)]"
|
|
25
|
+
>
|
|
26
|
+
Sair
|
|
27
|
+
</button>
|
|
28
|
+
|
|
29
|
+
</>
|
|
30
|
+
)}
|
|
31
|
+
{status === 'unauthenticated' && (
|
|
32
|
+
<Link
|
|
33
|
+
href="/login"
|
|
34
|
+
className="rounded-full border border-solid border-transparent transition-all duration-300 flex items-center justify-center bg-purple-600 text-white gap-2 hover:bg-purple-500 font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-40 shadow-[0_0_15px_-3px_theme(colors.purple.600)] hover:shadow-[0_0_25px_-3px_theme(colors.purple.500)]"
|
|
35
|
+
>
|
|
36
|
+
Login
|
|
37
|
+
</Link>
|
|
38
|
+
)}
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left text-gray-400">
|
|
42
|
+
<li className="mb-2 tracking-[-.01em]">
|
|
43
|
+
Comece editando{" "}
|
|
44
|
+
<code className="bg-gray-800 border border-gray-700 font-mono font-semibold px-1 py-0.5 rounded text-purple-400">
|
|
45
|
+
src/web/routes/index.tsx
|
|
46
|
+
</code>
|
|
47
|
+
.
|
|
48
|
+
</li>
|
|
49
|
+
<li className="tracking-[-.01em]">
|
|
50
|
+
Salve e veja suas mudanças instantaneamente.
|
|
51
|
+
</li>
|
|
52
|
+
</ol>
|
|
53
|
+
|
|
54
|
+
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
|
55
|
+
<a
|
|
56
|
+
className="rounded-full border border-solid border-transparent transition-all duration-300 flex items-center justify-center bg-purple-600 text-white gap-2 hover:bg-purple-500 font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto shadow-[0_0_15px_-3px_theme(colors.purple.600)] hover:shadow-[0_0_25px_-3px_theme(colors.purple.500)]"
|
|
57
|
+
href="#"
|
|
58
|
+
target="_blank"
|
|
59
|
+
rel="noopener noreferrer"
|
|
60
|
+
>
|
|
61
|
+
<svg
|
|
62
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
63
|
+
width="20"
|
|
64
|
+
height="20"
|
|
65
|
+
viewBox="0 0 24 24"
|
|
66
|
+
fill="none"
|
|
67
|
+
stroke="currentColor"
|
|
68
|
+
strokeWidth="2"
|
|
69
|
+
strokeLinecap="round"
|
|
70
|
+
strokeLinejoin="round"
|
|
71
|
+
className="lucide lucide-rocket"
|
|
72
|
+
>
|
|
73
|
+
<path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.33-.04-3.86l1.8-1.8c.44-.44.86-.92 1.22-1.44l-2.06-2.06c-.52.36-1 .78-1.44 1.22l-1.8-1.8c-1.53.74-3.02.73-3.86-.04Z" />
|
|
74
|
+
<path d="m12 15 5-5" />
|
|
75
|
+
<path d="M9 3h6v6h-6Z" />
|
|
76
|
+
<path d="M19.5 16.5c1.5-1.26 2-5 2-5s-3.74.5-5 2c-.71.84-.7 2.33.04 3.86l-1.8 1.8c-.44.44-.86.92-1.22 1.44l2.06 2.06c.52-.36 1-.78 1.44-1.22l1.8 1.8c1.53-.74 3.02-.73 3.86.04Z" />
|
|
77
|
+
</svg>
|
|
78
|
+
Fazer Deploy
|
|
79
|
+
</a>
|
|
80
|
+
<a
|
|
81
|
+
className="rounded-full border border-solid border-white/20 transition-colors flex items-center justify-center hover:bg-white/10 hover:border-white/30 font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px] text-gray-300"
|
|
82
|
+
href="#"
|
|
83
|
+
target="_blank"
|
|
84
|
+
rel="noopener noreferrer"
|
|
85
|
+
>
|
|
86
|
+
Leia a documentação
|
|
87
|
+
</a>
|
|
88
|
+
</div>
|
|
89
|
+
</main>
|
|
90
|
+
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center z-10">
|
|
91
|
+
<a
|
|
92
|
+
className="flex items-center gap-2 text-gray-400 transition-colors hover:text-purple-400 hover:underline hover:underline-offset-4"
|
|
93
|
+
href="#"
|
|
94
|
+
target="_blank"
|
|
95
|
+
rel="noopener noreferrer"
|
|
96
|
+
>
|
|
97
|
+
<img
|
|
98
|
+
aria-hidden
|
|
99
|
+
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWJvb2stb3BlbiI+PHBhdGggZD0iTTIgM3YxNGEyIDIgMCAwIDAgMiAyaDE2YTIgMiAwIDAgMCAyLTJWM20tOCAxOGExIDQgMCAwIDEtMy44LTJsMS42LTEuNmExIDQgMCAwIDEgMy44IDJ6bTggMGE0IDQgMCAwIDAgMy44LTJsLTEuNi0xLjZhNCA0IDAgMCAwLTMuOCAyeiIvPjwvc3ZnPg=="
|
|
100
|
+
alt="Ícone de arquivo"
|
|
101
|
+
width={16}
|
|
102
|
+
height={16}
|
|
103
|
+
/>
|
|
104
|
+
Aprenda
|
|
105
|
+
</a>
|
|
106
|
+
<a
|
|
107
|
+
className="flex items-center gap-2 text-gray-400 transition-colors hover:text-purple-400 hover:underline hover:underline-offset-4"
|
|
108
|
+
href="#"
|
|
109
|
+
target="_blank"
|
|
110
|
+
rel="noopener noreferrer"
|
|
111
|
+
>
|
|
112
|
+
<img
|
|
113
|
+
aria-hidden
|
|
114
|
+
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWxheW91dC10ZW1wbGF0ZSI+PHJlY3Qgd2lkdGg9IjE4IiBoZWlnaHQ9IjciIHg9IjMiIHk9IjMiIHJ4PSIyIiByeT0iMiIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjciIHg9IjMiIHk9IjE0IiByeD0iMiIgcnk9IjIiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSI3IiB4PSIxNCIgeT0iMTQiIHJ4PSIyIiByeT0iMiIvPjwvc3ZnPg=="
|
|
115
|
+
alt="Ícone de janela"
|
|
116
|
+
width={16}
|
|
117
|
+
height={16}
|
|
118
|
+
/>
|
|
119
|
+
Exemplos
|
|
120
|
+
</a>
|
|
121
|
+
<a
|
|
122
|
+
className="flex items-center gap-2 text-gray-400 transition-colors hover:text-purple-400 hover:underline hover:underline-offset-4"
|
|
123
|
+
href="#"
|
|
124
|
+
target="_blank"
|
|
125
|
+
rel="noopener noreferrer"
|
|
126
|
+
>
|
|
127
|
+
<img
|
|
128
|
+
aria-hidden
|
|
129
|
+
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWdsb2JlIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxwYXRoIGQ9Ik0xMiAyYTE0LjUgMTQuNSAwIDAgMCAwIDIwIDE0LjUgMTQuNSAwIDAgMCAwLTIweiIvPjxwYXRoIGQ9Ik0yIDEySDEybTEwIDBIMTIiLz48L3N2Zz4="
|
|
130
|
+
alt="Ícone de globo"
|
|
131
|
+
width={16}
|
|
132
|
+
height={16}
|
|
133
|
+
/>
|
|
134
|
+
Ir para hightjs.dev →
|
|
135
|
+
</a>
|
|
136
|
+
</footer>
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import React, {useState} from "react";
|
|
2
|
+
import {useSession} from "hightjs/auth/react";
|
|
3
|
+
import {router} from "hightjs/client";
|
|
4
|
+
export default function LoginPage() {
|
|
5
|
+
const [username, setUsername] = useState("");
|
|
6
|
+
const [password, setPassword] = useState("");
|
|
7
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
8
|
+
const {signIn} = useSession();
|
|
9
|
+
|
|
10
|
+
const [error, setError] = useState<string | null>(null);
|
|
11
|
+
|
|
12
|
+
const handleLogin = async (e: React.FormEvent) => {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
setIsLoading(true);
|
|
15
|
+
setError(null);
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const result = await signIn('credentials', {
|
|
19
|
+
redirect: false,
|
|
20
|
+
username: username,
|
|
21
|
+
password: password,
|
|
22
|
+
callbackUrl: '/'
|
|
23
|
+
});
|
|
24
|
+
console.log(result)
|
|
25
|
+
if (!result || result.error) {
|
|
26
|
+
setError('Credenciais inválidas. Verifique seus dados e senha.');
|
|
27
|
+
setIsLoading(false);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
router.push("/")
|
|
31
|
+
|
|
32
|
+
} catch (err) {
|
|
33
|
+
setError('Ocorreu um erro inesperado. Tente novamente.');
|
|
34
|
+
setIsLoading(false);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className="font-sans min-h-screen flex items-center justify-center p-8 bg-gradient-to-r from-black to-gray-500 text-gray-200 relative overflow-hidden">
|
|
41
|
+
{/* Background gradient */}
|
|
42
|
+
<div className="absolute inset-0 -z-10 h-full w-full bg-gradient-to-r from-black to-gray-500 bg-[radial-gradient(circle_500px_at_50%_200px,#3e007555,transparent)]"></div>
|
|
43
|
+
|
|
44
|
+
{/* Additional ambient lights */}
|
|
45
|
+
<div className="absolute top-1/4 left-1/4 w-72 h-72 bg-purple-500/10 rounded-full blur-3xl -z-10"></div>
|
|
46
|
+
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-blue-500/5 rounded-full blur-3xl -z-10"></div>
|
|
47
|
+
|
|
48
|
+
{/* Login Container */}
|
|
49
|
+
<div className="w-full max-w-md">
|
|
50
|
+
{/* Header */}
|
|
51
|
+
<div className="text-center mb-8">
|
|
52
|
+
<div className="flex items-center justify-center gap-3 mb-4">
|
|
53
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-purple-500">
|
|
54
|
+
<path d="m12 3-8.9 5.06a4 4 0 0 0-1.1 5.44l1.1 1.94a4 4 0 0 0 5.44 1.1l8.9-5.06a4 4 0 0 0 1.1-5.44l-1.1-1.94a4 4 0 0 0-5.44-1.1z"></path>
|
|
55
|
+
</svg>
|
|
56
|
+
<h1 className="text-2xl font-bold text-purple-400 [text-shadow:_0_0_12px_theme(colors.purple.500)]">HightJS</h1>
|
|
57
|
+
</div>
|
|
58
|
+
<h2 className="text-xl font-medium text-gray-300 mb-2">Bem-vindo de volta</h2>
|
|
59
|
+
<p className="text-sm text-gray-400">Faça login em sua conta</p>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
{/* Glass Login Form */}
|
|
63
|
+
<div className="relative">
|
|
64
|
+
{/* Glass background */}
|
|
65
|
+
<div className="absolute inset-0 bg-white/5 backdrop-blur-xl border border-white/10 rounded-2xl shadow-2xl"></div>
|
|
66
|
+
|
|
67
|
+
{/* error */}
|
|
68
|
+
{error && (
|
|
69
|
+
<div className="relative p-4 mb-4 text-sm text-red-800 bg-red-200 rounded-lg" role="alert">
|
|
70
|
+
{error}
|
|
71
|
+
</div>
|
|
72
|
+
)}
|
|
73
|
+
|
|
74
|
+
{/* Form content */}
|
|
75
|
+
<form onSubmit={handleLogin} className="relative p-8 space-y-6">
|
|
76
|
+
{/* Email field */}
|
|
77
|
+
<div className="space-y-2">
|
|
78
|
+
<label htmlFor="email" className="text-sm font-medium text-gray-300">
|
|
79
|
+
Usuário
|
|
80
|
+
</label>
|
|
81
|
+
<input
|
|
82
|
+
id="username"
|
|
83
|
+
type="username"
|
|
84
|
+
value={username}
|
|
85
|
+
onChange={(e) => setUsername(e.target.value)}
|
|
86
|
+
className="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-xl text-gray-200 placeholder-gray-400 focus:border-purple-500/50 focus:ring-2 focus:ring-purple-500/20 focus:outline-none backdrop-blur-sm transition-all duration-300"
|
|
87
|
+
required
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
{/* Password field */}
|
|
92
|
+
<div className="space-y-2">
|
|
93
|
+
<label htmlFor="password" className="text-sm font-medium text-gray-300">
|
|
94
|
+
Senha
|
|
95
|
+
</label>
|
|
96
|
+
<input
|
|
97
|
+
id="password"
|
|
98
|
+
type="password"
|
|
99
|
+
placeholder="••••••••"
|
|
100
|
+
value={password}
|
|
101
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
102
|
+
className="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-xl text-gray-200 placeholder-gray-400 focus:border-purple-500/50 focus:ring-2 focus:ring-purple-500/20 focus:outline-none backdrop-blur-sm transition-all duration-300"
|
|
103
|
+
required
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
{/* Remember me and forgot password */}
|
|
108
|
+
<div className="flex items-center justify-between text-sm">
|
|
109
|
+
<label className="flex items-center text-gray-400 cursor-pointer">
|
|
110
|
+
<input
|
|
111
|
+
type="checkbox"
|
|
112
|
+
className="mr-2 rounded border-white/20 bg-white/5 text-purple-500 focus:ring-purple-500/20"
|
|
113
|
+
/>
|
|
114
|
+
Lembrar de mim
|
|
115
|
+
</label>
|
|
116
|
+
<a href="#" className="text-purple-400 hover:text-purple-300 transition-colors hover:underline">
|
|
117
|
+
Esqueceu a senha?
|
|
118
|
+
</a>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
{/* Login button */}
|
|
122
|
+
<button
|
|
123
|
+
type="submit"
|
|
124
|
+
disabled={isLoading}
|
|
125
|
+
className="w-full bg-purple-600 hover:bg-purple-500 text-white font-medium py-3 px-4 rounded-xl transition-all duration-300 shadow-[0_0_15px_-3px_theme(colors.purple.600)] hover:shadow-[0_0_25px_-3px_theme(colors.purple.500)] disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-purple-500/20"
|
|
126
|
+
>
|
|
127
|
+
{isLoading ? (
|
|
128
|
+
<div className="flex items-center justify-center gap-2">
|
|
129
|
+
<svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
|
130
|
+
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
131
|
+
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
132
|
+
</svg>
|
|
133
|
+
Entrando...
|
|
134
|
+
</div>
|
|
135
|
+
) : (
|
|
136
|
+
'Entrar'
|
|
137
|
+
)}
|
|
138
|
+
</button>
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
</form>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
@@ -1,145 +1,5 @@
|
|
|
1
1
|
import {RouteConfig} from "hightjs/client";
|
|
2
|
-
|
|
3
|
-
import React from "react";
|
|
4
|
-
import {useSession} from "hightjs/auth/react"
|
|
5
|
-
import { Link } from "hightjs/client";
|
|
6
|
-
|
|
7
|
-
function Home() {
|
|
8
|
-
const { data: session, status, signOut } = useSession();
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 bg-gradient-to-r from-black to-gray-500 text-gray-200 relative overflow-hidden">
|
|
13
|
-
<div className="absolute inset-0 -z-10 h-full w-full bg-gradient-to-r from-black to-gray-500 bg-[radial-gradient(circle_500px_at_50%_200px,#3e007555,transparent)]"></div>
|
|
14
|
-
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start z-10">
|
|
15
|
-
<div className="flex items-center gap-4">
|
|
16
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="38" height="38" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-purple-500"><path d="m12 3-8.9 5.06a4 4 0 0 0-1.1 5.44l1.1 1.94a4 4 0 0 0 5.44 1.1l8.9-5.06a4 4 0 0 0 1.1-5.44l-1.1-1.94a4 4 0 0 0-5.44-1.1z"></path></svg>
|
|
17
|
-
<h1 className="text-3xl font-bold text-purple-400 [text-shadow:_0_0_12px_theme(colors.purple.500)]">HightJS</h1>
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
|
-
<div className="flex flex-col items-center gap-4 self-center">
|
|
21
|
-
{status === 'loading' && <p>Carregando...</p>}
|
|
22
|
-
{status === 'authenticated' && session?.user && (
|
|
23
|
-
<>
|
|
24
|
-
<p className="text-lg">Você está logado como <span className="font-bold text-purple-400">{session.user.name}</span>!</p>
|
|
25
|
-
<button
|
|
26
|
-
onClick={() => signOut({callbackUrl: '/'})}
|
|
27
|
-
className="rounded-full border border-solid border-transparent transition-all duration-300 flex items-center justify-center bg-purple-600 text-white gap-2 hover:bg-purple-500 font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-40 shadow-[0_0_15px_-3px_theme(colors.purple.600)] hover:shadow-[0_0_25px_-3px_theme(colors.purple.500)]"
|
|
28
|
-
>
|
|
29
|
-
Sair
|
|
30
|
-
</button>
|
|
31
|
-
|
|
32
|
-
</>
|
|
33
|
-
)}
|
|
34
|
-
{status === 'unauthenticated' && (
|
|
35
|
-
<Link
|
|
36
|
-
href="/login"
|
|
37
|
-
className="rounded-full border border-solid border-transparent transition-all duration-300 flex items-center justify-center bg-purple-600 text-white gap-2 hover:bg-purple-500 font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-40 shadow-[0_0_15px_-3px_theme(colors.purple.600)] hover:shadow-[0_0_25px_-3px_theme(colors.purple.500)]"
|
|
38
|
-
>
|
|
39
|
-
Login
|
|
40
|
-
</Link>
|
|
41
|
-
)}
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
<ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left text-gray-400">
|
|
45
|
-
<li className="mb-2 tracking-[-.01em]">
|
|
46
|
-
Comece editando{" "}
|
|
47
|
-
<code className="bg-gray-800 border border-gray-700 font-mono font-semibold px-1 py-0.5 rounded text-purple-400">
|
|
48
|
-
src/web/routes/index.tsx
|
|
49
|
-
</code>
|
|
50
|
-
.
|
|
51
|
-
</li>
|
|
52
|
-
<li className="tracking-[-.01em]">
|
|
53
|
-
Salve e veja suas mudanças instantaneamente.
|
|
54
|
-
</li>
|
|
55
|
-
</ol>
|
|
56
|
-
|
|
57
|
-
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
|
58
|
-
<a
|
|
59
|
-
className="rounded-full border border-solid border-transparent transition-all duration-300 flex items-center justify-center bg-purple-600 text-white gap-2 hover:bg-purple-500 font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto shadow-[0_0_15px_-3px_theme(colors.purple.600)] hover:shadow-[0_0_25px_-3px_theme(colors.purple.500)]"
|
|
60
|
-
href="#"
|
|
61
|
-
target="_blank"
|
|
62
|
-
rel="noopener noreferrer"
|
|
63
|
-
>
|
|
64
|
-
<svg
|
|
65
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
66
|
-
width="20"
|
|
67
|
-
height="20"
|
|
68
|
-
viewBox="0 0 24 24"
|
|
69
|
-
fill="none"
|
|
70
|
-
stroke="currentColor"
|
|
71
|
-
strokeWidth="2"
|
|
72
|
-
strokeLinecap="round"
|
|
73
|
-
strokeLinejoin="round"
|
|
74
|
-
className="lucide lucide-rocket"
|
|
75
|
-
>
|
|
76
|
-
<path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.33-.04-3.86l1.8-1.8c.44-.44.86-.92 1.22-1.44l-2.06-2.06c-.52.36-1 .78-1.44 1.22l-1.8-1.8c-1.53.74-3.02.73-3.86-.04Z" />
|
|
77
|
-
<path d="m12 15 5-5" />
|
|
78
|
-
<path d="M9 3h6v6h-6Z" />
|
|
79
|
-
<path d="M19.5 16.5c1.5-1.26 2-5 2-5s-3.74.5-5 2c-.71.84-.7 2.33.04 3.86l-1.8 1.8c-.44.44-.86.92-1.22 1.44l2.06 2.06c.52-.36 1-.78 1.44-1.22l1.8 1.8c1.53-.74 3.02-.73 3.86.04Z" />
|
|
80
|
-
</svg>
|
|
81
|
-
Fazer Deploy
|
|
82
|
-
</a>
|
|
83
|
-
<a
|
|
84
|
-
className="rounded-full border border-solid border-white/20 transition-colors flex items-center justify-center hover:bg-white/10 hover:border-white/30 font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px] text-gray-300"
|
|
85
|
-
href="#"
|
|
86
|
-
target="_blank"
|
|
87
|
-
rel="noopener noreferrer"
|
|
88
|
-
>
|
|
89
|
-
Leia a documentação
|
|
90
|
-
</a>
|
|
91
|
-
</div>
|
|
92
|
-
</main>
|
|
93
|
-
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center z-10">
|
|
94
|
-
<a
|
|
95
|
-
className="flex items-center gap-2 text-gray-400 transition-colors hover:text-purple-400 hover:underline hover:underline-offset-4"
|
|
96
|
-
href="#"
|
|
97
|
-
target="_blank"
|
|
98
|
-
rel="noopener noreferrer"
|
|
99
|
-
>
|
|
100
|
-
<img
|
|
101
|
-
aria-hidden
|
|
102
|
-
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWJvb2stb3BlbiI+PHBhdGggZD0iTTIgM3YxNGEyIDIgMCAwIDAgMiAyaDE2YTIgMiAwIDAgMCAyLTJWM20tOCAxOGExIDQgMCAwIDEtMy44LTJsMS42LTEuNmExIDQgMCAwIDEgMy44IDJ6bTggMGE0IDQgMCAwIDAgMy44LTJsLTEuNi0xLjZhNCA0IDAgMCAwLTMuOCAyeiIvPjwvc3ZnPg=="
|
|
103
|
-
alt="Ícone de arquivo"
|
|
104
|
-
width={16}
|
|
105
|
-
height={16}
|
|
106
|
-
/>
|
|
107
|
-
Aprenda
|
|
108
|
-
</a>
|
|
109
|
-
<a
|
|
110
|
-
className="flex items-center gap-2 text-gray-400 transition-colors hover:text-purple-400 hover:underline hover:underline-offset-4"
|
|
111
|
-
href="#"
|
|
112
|
-
target="_blank"
|
|
113
|
-
rel="noopener noreferrer"
|
|
114
|
-
>
|
|
115
|
-
<img
|
|
116
|
-
aria-hidden
|
|
117
|
-
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWxheW91dC10ZW1wbGF0ZSI+PHJlY3Qgd2lkdGg9IjE4IiBoZWlnaHQ9IjciIHg9IjMiIHk9IjMiIHJ4PSIyIiByeT0iMiIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjciIHg9IjMiIHk9IjE0IiByeD0iMiIgcnk9IjIiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSI3IiB4PSIxNCIgeT0iMTQiIHJ4PSIyIiByeT0iMiIvPjwvc3ZnPg=="
|
|
118
|
-
alt="Ícone de janela"
|
|
119
|
-
width={16}
|
|
120
|
-
height={16}
|
|
121
|
-
/>
|
|
122
|
-
Exemplos
|
|
123
|
-
</a>
|
|
124
|
-
<a
|
|
125
|
-
className="flex items-center gap-2 text-gray-400 transition-colors hover:text-purple-400 hover:underline hover:underline-offset-4"
|
|
126
|
-
href="#"
|
|
127
|
-
target="_blank"
|
|
128
|
-
rel="noopener noreferrer"
|
|
129
|
-
>
|
|
130
|
-
<img
|
|
131
|
-
aria-hidden
|
|
132
|
-
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWdsb2JlIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxwYXRoIGQ9Ik0xMiAyYTE0LjUgMTQuNSAwIDAgMCAwIDIwIDE0LjUgMTQuNSAwIDAgMCAwLTIweiIvPjxwYXRoIGQ9Ik0yIDEySDEybTEwIDBIMTIiLz48L3N2Zz4="
|
|
133
|
-
alt="Ícone de globo"
|
|
134
|
-
width={16}
|
|
135
|
-
height={16}
|
|
136
|
-
/>
|
|
137
|
-
Ir para hightjs.dev →
|
|
138
|
-
</a>
|
|
139
|
-
</footer>
|
|
140
|
-
</div>
|
|
141
|
-
);
|
|
142
|
-
}
|
|
2
|
+
import Home from "../components/Home";
|
|
143
3
|
|
|
144
4
|
|
|
145
5
|
|
|
@@ -1,154 +1,9 @@
|
|
|
1
1
|
import {RouteConfig, router} from "hightjs/client";
|
|
2
2
|
import {GuestOnly, useSession} from "hightjs/auth/react"
|
|
3
3
|
import React, {useState} from "react";
|
|
4
|
+
import LoginPage from "../components/LoginPage";
|
|
4
5
|
|
|
5
6
|
|
|
6
|
-
function LoginPage() {
|
|
7
|
-
const [username, setUsername] = useState("");
|
|
8
|
-
const [password, setPassword] = useState("");
|
|
9
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
10
|
-
const {signIn} = useSession();
|
|
11
|
-
|
|
12
|
-
const [error, setError] = useState<string | null>(null);
|
|
13
|
-
|
|
14
|
-
const handleLogin = async (e: React.FormEvent) => {
|
|
15
|
-
e.preventDefault();
|
|
16
|
-
setIsLoading(true);
|
|
17
|
-
setError(null);
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
const result = await signIn('credentials', {
|
|
21
|
-
redirect: false,
|
|
22
|
-
username: username,
|
|
23
|
-
password: password,
|
|
24
|
-
callbackUrl: '/'
|
|
25
|
-
});
|
|
26
|
-
console.log(result)
|
|
27
|
-
if (!result || result.error) {
|
|
28
|
-
setError('Credenciais inválidas. Verifique seus dados e senha.');
|
|
29
|
-
setIsLoading(false);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
router.push("/")
|
|
33
|
-
|
|
34
|
-
} catch (err) {
|
|
35
|
-
setError('Ocorreu um erro inesperado. Tente novamente.');
|
|
36
|
-
setIsLoading(false);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<div className="font-sans min-h-screen flex items-center justify-center p-8 bg-gradient-to-r from-black to-gray-500 text-gray-200 relative overflow-hidden">
|
|
43
|
-
{/* Background gradient */}
|
|
44
|
-
<div className="absolute inset-0 -z-10 h-full w-full bg-gradient-to-r from-black to-gray-500 bg-[radial-gradient(circle_500px_at_50%_200px,#3e007555,transparent)]"></div>
|
|
45
|
-
|
|
46
|
-
{/* Additional ambient lights */}
|
|
47
|
-
<div className="absolute top-1/4 left-1/4 w-72 h-72 bg-purple-500/10 rounded-full blur-3xl -z-10"></div>
|
|
48
|
-
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-blue-500/5 rounded-full blur-3xl -z-10"></div>
|
|
49
|
-
|
|
50
|
-
{/* Login Container */}
|
|
51
|
-
<div className="w-full max-w-md">
|
|
52
|
-
{/* Header */}
|
|
53
|
-
<div className="text-center mb-8">
|
|
54
|
-
<div className="flex items-center justify-center gap-3 mb-4">
|
|
55
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-purple-500">
|
|
56
|
-
<path d="m12 3-8.9 5.06a4 4 0 0 0-1.1 5.44l1.1 1.94a4 4 0 0 0 5.44 1.1l8.9-5.06a4 4 0 0 0 1.1-5.44l-1.1-1.94a4 4 0 0 0-5.44-1.1z"></path>
|
|
57
|
-
</svg>
|
|
58
|
-
<h1 className="text-2xl font-bold text-purple-400 [text-shadow:_0_0_12px_theme(colors.purple.500)]">HightJS</h1>
|
|
59
|
-
</div>
|
|
60
|
-
<h2 className="text-xl font-medium text-gray-300 mb-2">Bem-vindo de volta</h2>
|
|
61
|
-
<p className="text-sm text-gray-400">Faça login em sua conta</p>
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
{/* Glass Login Form */}
|
|
65
|
-
<div className="relative">
|
|
66
|
-
{/* Glass background */}
|
|
67
|
-
<div className="absolute inset-0 bg-white/5 backdrop-blur-xl border border-white/10 rounded-2xl shadow-2xl"></div>
|
|
68
|
-
|
|
69
|
-
{/* error */}
|
|
70
|
-
{error && (
|
|
71
|
-
<div className="relative p-4 mb-4 text-sm text-red-800 bg-red-200 rounded-lg" role="alert">
|
|
72
|
-
{error}
|
|
73
|
-
</div>
|
|
74
|
-
)}
|
|
75
|
-
|
|
76
|
-
{/* Form content */}
|
|
77
|
-
<form onSubmit={handleLogin} className="relative p-8 space-y-6">
|
|
78
|
-
{/* Email field */}
|
|
79
|
-
<div className="space-y-2">
|
|
80
|
-
<label htmlFor="email" className="text-sm font-medium text-gray-300">
|
|
81
|
-
Usuário
|
|
82
|
-
</label>
|
|
83
|
-
<input
|
|
84
|
-
id="username"
|
|
85
|
-
type="username"
|
|
86
|
-
value={username}
|
|
87
|
-
onChange={(e) => setUsername(e.target.value)}
|
|
88
|
-
className="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-xl text-gray-200 placeholder-gray-400 focus:border-purple-500/50 focus:ring-2 focus:ring-purple-500/20 focus:outline-none backdrop-blur-sm transition-all duration-300"
|
|
89
|
-
required
|
|
90
|
-
/>
|
|
91
|
-
</div>
|
|
92
|
-
|
|
93
|
-
{/* Password field */}
|
|
94
|
-
<div className="space-y-2">
|
|
95
|
-
<label htmlFor="password" className="text-sm font-medium text-gray-300">
|
|
96
|
-
Senha
|
|
97
|
-
</label>
|
|
98
|
-
<input
|
|
99
|
-
id="password"
|
|
100
|
-
type="password"
|
|
101
|
-
placeholder="••••••••"
|
|
102
|
-
value={password}
|
|
103
|
-
onChange={(e) => setPassword(e.target.value)}
|
|
104
|
-
className="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-xl text-gray-200 placeholder-gray-400 focus:border-purple-500/50 focus:ring-2 focus:ring-purple-500/20 focus:outline-none backdrop-blur-sm transition-all duration-300"
|
|
105
|
-
required
|
|
106
|
-
/>
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
{/* Remember me and forgot password */}
|
|
110
|
-
<div className="flex items-center justify-between text-sm">
|
|
111
|
-
<label className="flex items-center text-gray-400 cursor-pointer">
|
|
112
|
-
<input
|
|
113
|
-
type="checkbox"
|
|
114
|
-
className="mr-2 rounded border-white/20 bg-white/5 text-purple-500 focus:ring-purple-500/20"
|
|
115
|
-
/>
|
|
116
|
-
Lembrar de mim
|
|
117
|
-
</label>
|
|
118
|
-
<a href="#" className="text-purple-400 hover:text-purple-300 transition-colors hover:underline">
|
|
119
|
-
Esqueceu a senha?
|
|
120
|
-
</a>
|
|
121
|
-
</div>
|
|
122
|
-
|
|
123
|
-
{/* Login button */}
|
|
124
|
-
<button
|
|
125
|
-
type="submit"
|
|
126
|
-
disabled={isLoading}
|
|
127
|
-
className="w-full bg-purple-600 hover:bg-purple-500 text-white font-medium py-3 px-4 rounded-xl transition-all duration-300 shadow-[0_0_15px_-3px_theme(colors.purple.600)] hover:shadow-[0_0_25px_-3px_theme(colors.purple.500)] disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-purple-500/20"
|
|
128
|
-
>
|
|
129
|
-
{isLoading ? (
|
|
130
|
-
<div className="flex items-center justify-center gap-2">
|
|
131
|
-
<svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
|
132
|
-
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
133
|
-
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
134
|
-
</svg>
|
|
135
|
-
Entrando...
|
|
136
|
-
</div>
|
|
137
|
-
) : (
|
|
138
|
-
'Entrar'
|
|
139
|
-
)}
|
|
140
|
-
</button>
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
</form>
|
|
146
|
-
</div>
|
|
147
|
-
|
|
148
|
-
</div>
|
|
149
|
-
</div>
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
7
|
|
|
153
8
|
const wrapper = () => {
|
|
154
9
|
const session = useSession()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hightjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "HightJS is a high-level framework for building web applications with ease and speed. It provides a robust set of tools and features to streamline development and enhance productivity.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/express": "^4.17.21",
|
|
49
|
+
"@types/fs-extra": "^11.0.4",
|
|
49
50
|
"@types/node": "^20.11.24",
|
|
50
51
|
"@types/react": "^19.2.0",
|
|
51
52
|
"@types/react-dom": "^19.2.0",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"express": "^4.0.0",
|
|
66
67
|
"fastify": "^5.6.1",
|
|
67
68
|
"framer-motion": "^12.23.22",
|
|
69
|
+
"fs-extra": "^11.3.2",
|
|
68
70
|
"ws": "^8.18.1"
|
|
69
71
|
},
|
|
70
72
|
"peerDependency": {
|