@nitronjs/framework 0.2.3 → 0.2.4
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 +3 -1
- package/cli/create.js +88 -72
- package/cli/njs.js +13 -6
- package/lib/Auth/Auth.js +167 -0
- package/lib/Build/CssBuilder.js +9 -0
- package/lib/Build/FileAnalyzer.js +16 -0
- package/lib/Build/HydrationBuilder.js +17 -0
- package/lib/Build/Manager.js +15 -0
- package/lib/Build/colors.js +4 -0
- package/lib/Build/plugins.js +84 -20
- package/lib/Console/Commands/DevCommand.js +13 -9
- package/lib/Console/Commands/MakeCommand.js +24 -10
- package/lib/Console/Commands/MigrateCommand.js +0 -1
- package/lib/Console/Commands/MigrateFreshCommand.js +18 -25
- package/lib/Console/Commands/MigrateRollbackCommand.js +6 -3
- package/lib/Console/Commands/MigrateStatusCommand.js +6 -3
- package/lib/Console/Commands/SeedCommand.js +4 -2
- package/lib/Console/Commands/StorageLinkCommand.js +20 -5
- package/lib/Console/Output.js +143 -0
- package/lib/Core/Config.js +2 -1
- package/lib/Core/Paths.js +8 -0
- package/lib/Database/DB.js +141 -51
- package/lib/Database/Drivers/MySQLDriver.js +102 -157
- package/lib/Database/Migration/Checksum.js +3 -8
- package/lib/Database/Migration/MigrationRepository.js +25 -35
- package/lib/Database/Migration/MigrationRunner.js +56 -61
- package/lib/Database/Model.js +157 -83
- package/lib/Database/QueryBuilder.js +31 -0
- package/lib/Database/QueryValidation.js +36 -44
- package/lib/Database/Schema/Blueprint.js +25 -36
- package/lib/Database/Schema/Manager.js +31 -68
- package/lib/Database/Seeder/SeederRunner.js +12 -31
- package/lib/Date/DateTime.js +9 -0
- package/lib/Encryption/Encryption.js +52 -0
- package/lib/Faker/Faker.js +11 -0
- package/lib/Filesystem/Storage.js +120 -0
- package/lib/HMR/Server.js +79 -9
- package/lib/Hashing/Hash.js +41 -0
- package/lib/Http/Server.js +177 -152
- package/lib/Logging/{Manager.js → Log.js} +68 -80
- package/lib/Mail/Mail.js +187 -0
- package/lib/Route/Router.js +416 -0
- package/lib/Session/File.js +135 -233
- package/lib/Session/Manager.js +117 -171
- package/lib/Session/Memory.js +28 -38
- package/lib/Session/Session.js +71 -107
- package/lib/Support/Str.js +103 -0
- package/lib/Translation/Lang.js +54 -0
- package/lib/View/Client/hmr-client.js +87 -51
- package/lib/View/Client/nitronjs-icon.png +0 -0
- package/lib/View/{Manager.js → View.js} +44 -29
- package/lib/index.d.ts +42 -8
- package/lib/index.js +19 -12
- package/package.json +1 -1
- package/skeleton/app/Controllers/HomeController.js +7 -1
- package/skeleton/resources/css/global.css +1 -0
- package/skeleton/resources/views/Site/Home.tsx +456 -79
- package/skeleton/tsconfig.json +6 -1
- package/lib/Auth/Manager.js +0 -111
- package/lib/Database/Connection.js +0 -61
- package/lib/Database/Manager.js +0 -162
- package/lib/Encryption/Manager.js +0 -47
- package/lib/Filesystem/Manager.js +0 -74
- package/lib/Hashing/Manager.js +0 -25
- package/lib/Mail/Manager.js +0 -120
- package/lib/Route/Loader.js +0 -80
- package/lib/Route/Manager.js +0 -286
- package/lib/Translation/Manager.js +0 -49
|
@@ -1,86 +1,463 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import "@css/global.css";
|
|
4
|
+
import { useEffect, useRef } from "react";
|
|
5
|
+
|
|
6
|
+
export const Meta = {
|
|
7
|
+
title: "Welcome to NitronJS",
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function Home({ version }: { version: string }) {
|
|
11
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
12
|
+
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const container = containerRef.current;
|
|
16
|
+
const canvas = canvasRef.current;
|
|
17
|
+
if (!container || !canvas) return;
|
|
18
|
+
|
|
19
|
+
const ctx = canvas.getContext("2d");
|
|
20
|
+
if (!ctx) return;
|
|
21
|
+
|
|
22
|
+
canvas.width = window.innerWidth;
|
|
23
|
+
canvas.height = window.innerHeight;
|
|
24
|
+
|
|
25
|
+
let mouseX = canvas.width / 2;
|
|
26
|
+
let mouseY = canvas.height / 2;
|
|
27
|
+
|
|
28
|
+
interface Star {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
size: number;
|
|
32
|
+
speed: number;
|
|
33
|
+
opacity: number;
|
|
34
|
+
baseX: number;
|
|
35
|
+
baseY: number;
|
|
36
|
+
twinkleSpeed: number;
|
|
37
|
+
twinkleOffset: number;
|
|
38
|
+
driftX: number;
|
|
39
|
+
driftY: number;
|
|
40
|
+
velocityX: number;
|
|
41
|
+
velocityY: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface Particle {
|
|
45
|
+
x: number;
|
|
46
|
+
y: number;
|
|
47
|
+
vx: number;
|
|
48
|
+
vy: number;
|
|
49
|
+
size: number;
|
|
50
|
+
life: number;
|
|
51
|
+
maxLife: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface Nebula {
|
|
55
|
+
x: number;
|
|
56
|
+
y: number;
|
|
57
|
+
baseX: number;
|
|
58
|
+
baseY: number;
|
|
59
|
+
size: number;
|
|
60
|
+
speed: number;
|
|
61
|
+
color: { r: number; g: number; b: number };
|
|
62
|
+
opacity: number;
|
|
63
|
+
pulseSpeed: number;
|
|
64
|
+
pulseOffset: number;
|
|
65
|
+
driftX: number;
|
|
66
|
+
driftY: number;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const stars: Star[] = [];
|
|
70
|
+
const particles: Particle[] = [];
|
|
71
|
+
const nebulas: Nebula[] = [];
|
|
72
|
+
const starCount = 300;
|
|
73
|
+
const nebulaCount = 5;
|
|
74
|
+
|
|
75
|
+
for (let i = 0; i < starCount; i++) {
|
|
76
|
+
const x = Math.random() * canvas.width;
|
|
77
|
+
const y = Math.random() * canvas.height;
|
|
78
|
+
|
|
79
|
+
stars.push({
|
|
80
|
+
x,
|
|
81
|
+
y,
|
|
82
|
+
baseX: x,
|
|
83
|
+
baseY: y,
|
|
84
|
+
size: Math.random() * 2 + 0.5,
|
|
85
|
+
speed: Math.random() * 0.5 + 0.1,
|
|
86
|
+
opacity: Math.random() * 0.8 + 0.2,
|
|
87
|
+
twinkleSpeed: Math.random() * 0.02 + 0.01,
|
|
88
|
+
twinkleOffset: Math.random() * Math.PI * 2,
|
|
89
|
+
driftX: (Math.random() - 0.5) * 0.2,
|
|
90
|
+
driftY: (Math.random() - 0.5) * 0.2,
|
|
91
|
+
velocityX: 0,
|
|
92
|
+
velocityY: 0
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Create nebulas
|
|
97
|
+
const nebulaColors = [
|
|
98
|
+
{ r: 147, g: 51, b: 234 }, // Purple
|
|
99
|
+
{ r: 59, g: 130, b: 246 }, // Blue
|
|
100
|
+
{ r: 236, g: 72, b: 153 }, // Pink
|
|
101
|
+
{ r: 79, g: 70, b: 229 }, // Indigo
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
for (let i = 0; i < nebulaCount; i++) {
|
|
105
|
+
const x = Math.random() * canvas.width;
|
|
106
|
+
const y = Math.random() * canvas.height;
|
|
107
|
+
const colorIndex = Math.floor(Math.random() * nebulaColors.length);
|
|
108
|
+
|
|
109
|
+
nebulas.push({
|
|
110
|
+
x,
|
|
111
|
+
y,
|
|
112
|
+
baseX: x,
|
|
113
|
+
baseY: y,
|
|
114
|
+
size: Math.random() * 250 + 200,
|
|
115
|
+
speed: Math.random() * 0.3 + 0.1,
|
|
116
|
+
color: nebulaColors[colorIndex],
|
|
117
|
+
opacity: Math.random() * 0.25 + 0.15,
|
|
118
|
+
pulseSpeed: Math.random() * 0.01 + 0.005,
|
|
119
|
+
pulseOffset: Math.random() * Math.PI * 2,
|
|
120
|
+
driftX: (Math.random() - 0.5) * 0.3,
|
|
121
|
+
driftY: (Math.random() - 0.5) * 0.3
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const handleMouseMove = (e: MouseEvent) => {
|
|
126
|
+
const rect = container.getBoundingClientRect();
|
|
127
|
+
mouseX = e.clientX - rect.left;
|
|
128
|
+
mouseY = e.clientY - rect.top;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const handleClick = (e: MouseEvent) => {
|
|
132
|
+
const rect = container.getBoundingClientRect();
|
|
133
|
+
const clickX = e.clientX - rect.left;
|
|
134
|
+
const clickY = e.clientY - rect.top;
|
|
135
|
+
|
|
136
|
+
for (let i = 0; i < 30; i++) {
|
|
137
|
+
const angle = (Math.PI * 2 * i) / 30;
|
|
138
|
+
const speed = Math.random() * 3 + 2;
|
|
139
|
+
|
|
140
|
+
particles.push({
|
|
141
|
+
x: clickX,
|
|
142
|
+
y: clickY,
|
|
143
|
+
vx: Math.cos(angle) * speed,
|
|
144
|
+
vy: Math.sin(angle) * speed,
|
|
145
|
+
size: Math.random() * 2 + 1,
|
|
146
|
+
life: 1,
|
|
147
|
+
maxLife: Math.random() * 0.5 + 0.5
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
stars.forEach(star => {
|
|
152
|
+
const dx = star.baseX - clickX;
|
|
153
|
+
const dy = star.baseY - clickY;
|
|
154
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
155
|
+
|
|
156
|
+
if (distance < 200) {
|
|
157
|
+
const angle = Math.atan2(dy, dx);
|
|
158
|
+
const force = (200 - distance) / 200;
|
|
159
|
+
star.velocityX += Math.cos(angle) * force * 8;
|
|
160
|
+
star.velocityY += Math.sin(angle) * force * 8;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const handleResize = () => {
|
|
166
|
+
canvas.width = window.innerWidth;
|
|
167
|
+
canvas.height = window.innerHeight;
|
|
168
|
+
|
|
169
|
+
stars.forEach(star => {
|
|
170
|
+
if (star.baseX > canvas.width) star.baseX = canvas.width - 50;
|
|
171
|
+
if (star.baseY > canvas.height) star.baseY = canvas.height - 50;
|
|
172
|
+
star.x = star.baseX;
|
|
173
|
+
star.y = star.baseY;
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
nebulas.forEach(nebula => {
|
|
177
|
+
if (nebula.baseX > canvas.width) nebula.baseX = canvas.width / 2;
|
|
178
|
+
if (nebula.baseY > canvas.height) nebula.baseY = canvas.height / 2;
|
|
179
|
+
nebula.x = nebula.baseX;
|
|
180
|
+
nebula.y = nebula.baseY;
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const drawStar = (x: number, y: number, size: number, rotation: number) => {
|
|
185
|
+
const spikes = 5;
|
|
186
|
+
const outerRadius = size;
|
|
187
|
+
const innerRadius = size * 0.4;
|
|
188
|
+
|
|
189
|
+
ctx.save();
|
|
190
|
+
ctx.translate(x, y);
|
|
191
|
+
ctx.rotate(rotation);
|
|
192
|
+
ctx.beginPath();
|
|
193
|
+
|
|
194
|
+
for (let i = 0; i < spikes * 2; i++) {
|
|
195
|
+
const radius = i % 2 === 0 ? outerRadius : innerRadius;
|
|
196
|
+
const angle = (Math.PI * i) / spikes;
|
|
197
|
+
const px = Math.cos(angle) * radius;
|
|
198
|
+
const py = Math.sin(angle) * radius;
|
|
199
|
+
|
|
200
|
+
if (i === 0) {
|
|
201
|
+
ctx.moveTo(px, py);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
ctx.lineTo(px, py);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
ctx.closePath();
|
|
209
|
+
ctx.fill();
|
|
210
|
+
ctx.restore();
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const animate = () => {
|
|
214
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
215
|
+
ctx.fillStyle = "rgb(10, 10, 10)";
|
|
216
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
217
|
+
|
|
218
|
+
const time = Date.now() * 0.001;
|
|
219
|
+
|
|
220
|
+
// Reset all context properties at start of frame
|
|
221
|
+
ctx.shadowBlur = 0;
|
|
222
|
+
ctx.shadowColor = "transparent";
|
|
223
|
+
ctx.filter = "none";
|
|
224
|
+
ctx.globalCompositeOperation = "source-over";
|
|
225
|
+
|
|
226
|
+
// Draw nebulas first (background layer)
|
|
227
|
+
nebulas.forEach(nebula => {
|
|
228
|
+
const pulse = Math.sin(time * nebula.pulseSpeed + nebula.pulseOffset) * 0.3 + 0.7;
|
|
229
|
+
const currentSize = nebula.size * pulse;
|
|
230
|
+
const currentOpacity = nebula.opacity * pulse;
|
|
231
|
+
|
|
232
|
+
// Drift movement with boundary bounce
|
|
233
|
+
nebula.baseX += nebula.driftX;
|
|
234
|
+
nebula.baseY += nebula.driftY;
|
|
235
|
+
|
|
236
|
+
// Bounce off boundaries (with some padding for the nebula size)
|
|
237
|
+
const padding = 50;
|
|
238
|
+
if (nebula.baseX < padding) {
|
|
239
|
+
nebula.baseX = padding;
|
|
240
|
+
nebula.driftX *= -1;
|
|
241
|
+
}
|
|
242
|
+
if (nebula.baseX > canvas.width - padding) {
|
|
243
|
+
nebula.baseX = canvas.width - padding;
|
|
244
|
+
nebula.driftX *= -1;
|
|
245
|
+
}
|
|
246
|
+
if (nebula.baseY < padding) {
|
|
247
|
+
nebula.baseY = padding;
|
|
248
|
+
nebula.driftY *= -1;
|
|
249
|
+
}
|
|
250
|
+
if (nebula.baseY > canvas.height - padding) {
|
|
251
|
+
nebula.baseY = canvas.height - padding;
|
|
252
|
+
nebula.driftY *= -1;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
nebula.x = nebula.baseX;
|
|
256
|
+
nebula.y = nebula.baseY;
|
|
257
|
+
|
|
258
|
+
const { r, g, b } = nebula.color;
|
|
259
|
+
|
|
260
|
+
ctx.globalCompositeOperation = "screen";
|
|
261
|
+
|
|
262
|
+
// Layer 1: Outer glow (largest, most diffuse)
|
|
263
|
+
const outerGradient = ctx.createRadialGradient(
|
|
264
|
+
nebula.x, nebula.y, 0,
|
|
265
|
+
nebula.x, nebula.y, currentSize * 1.2
|
|
266
|
+
);
|
|
267
|
+
outerGradient.addColorStop(0, `rgba(${r}, ${g}, ${b}, ${currentOpacity * 0.05})`);
|
|
268
|
+
outerGradient.addColorStop(0.4, `rgba(${r}, ${g}, ${b}, ${currentOpacity * 0.03})`);
|
|
269
|
+
outerGradient.addColorStop(1, `rgba(${r}, ${g}, ${b}, 0)`);
|
|
270
|
+
|
|
271
|
+
ctx.fillStyle = outerGradient;
|
|
272
|
+
ctx.filter = `blur(${45 + pulse * 20}px)`;
|
|
273
|
+
ctx.beginPath();
|
|
274
|
+
ctx.arc(nebula.x, nebula.y, currentSize * 1.2, 0, Math.PI * 2);
|
|
275
|
+
ctx.fill();
|
|
276
|
+
|
|
277
|
+
// Layer 2: Middle layer (medium blur)
|
|
278
|
+
const middleGradient = ctx.createRadialGradient(
|
|
279
|
+
nebula.x, nebula.y, 0,
|
|
280
|
+
nebula.x, nebula.y, currentSize * 0.7
|
|
281
|
+
);
|
|
282
|
+
middleGradient.addColorStop(0, `rgba(${r}, ${g}, ${b}, ${currentOpacity * 0.25})`);
|
|
283
|
+
middleGradient.addColorStop(0.5, `rgba(${r}, ${g}, ${b}, ${currentOpacity * 0.15})`);
|
|
284
|
+
middleGradient.addColorStop(1, `rgba(${r}, ${g}, ${b}, 0)`);
|
|
285
|
+
|
|
286
|
+
ctx.fillStyle = middleGradient;
|
|
287
|
+
ctx.filter = `blur(${25 + pulse * 10}px)`;
|
|
288
|
+
ctx.beginPath();
|
|
289
|
+
ctx.arc(nebula.x, nebula.y, currentSize * 0.7, 0, Math.PI * 2);
|
|
290
|
+
ctx.fill();
|
|
291
|
+
|
|
292
|
+
// Layer 3: Inner core (brightest, sharpest)
|
|
293
|
+
const coreGradient = ctx.createRadialGradient(
|
|
294
|
+
nebula.x, nebula.y, 0,
|
|
295
|
+
nebula.x, nebula.y, currentSize * 0.3
|
|
296
|
+
);
|
|
297
|
+
coreGradient.addColorStop(0, `rgba(${r}, ${g}, ${b}, ${currentOpacity * 0.6})`);
|
|
298
|
+
coreGradient.addColorStop(0.5, `rgba(${r}, ${g}, ${b}, ${currentOpacity * 0.3})`);
|
|
299
|
+
coreGradient.addColorStop(1, `rgba(${r}, ${g}, ${b}, 0)`);
|
|
300
|
+
|
|
301
|
+
ctx.fillStyle = coreGradient;
|
|
302
|
+
ctx.filter = `blur(${8 + pulse * 5}px)`;
|
|
303
|
+
ctx.beginPath();
|
|
304
|
+
ctx.arc(nebula.x, nebula.y, currentSize * 0.3, 0, Math.PI * 2);
|
|
305
|
+
ctx.fill();
|
|
306
|
+
|
|
307
|
+
// Layer 4: Bright center point
|
|
308
|
+
const centerGradient = ctx.createRadialGradient(
|
|
309
|
+
nebula.x, nebula.y, 0,
|
|
310
|
+
nebula.x, nebula.y, currentSize * 0.1
|
|
311
|
+
);
|
|
312
|
+
centerGradient.addColorStop(0, `rgba(${Math.min(255, r + 80)}, ${Math.min(255, g + 80)}, ${Math.min(255, b + 80)}, ${currentOpacity * 0.8})`);
|
|
313
|
+
centerGradient.addColorStop(0.7, `rgba(${r}, ${g}, ${b}, ${currentOpacity * 0.4})`);
|
|
314
|
+
centerGradient.addColorStop(1, `rgba(${r}, ${g}, ${b}, 0)`);
|
|
315
|
+
|
|
316
|
+
ctx.fillStyle = centerGradient;
|
|
317
|
+
ctx.filter = `blur(3px)`;
|
|
318
|
+
ctx.beginPath();
|
|
319
|
+
ctx.arc(nebula.x, nebula.y, currentSize * 0.1, 0, Math.PI * 2);
|
|
320
|
+
ctx.fill();
|
|
321
|
+
|
|
322
|
+
// Reset context state after nebula
|
|
323
|
+
ctx.filter = "none";
|
|
324
|
+
ctx.globalCompositeOperation = "source-over";
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// Draw stars
|
|
328
|
+
stars.forEach((star) => {
|
|
329
|
+
star.baseX += star.driftX + star.velocityX;
|
|
330
|
+
star.baseY += star.driftY + star.velocityY;
|
|
331
|
+
|
|
332
|
+
star.velocityX *= 0.95;
|
|
333
|
+
star.velocityY *= 0.95;
|
|
334
|
+
|
|
335
|
+
if (star.baseX < 20) {
|
|
336
|
+
star.baseX = 20;
|
|
337
|
+
star.driftX *= -1;
|
|
338
|
+
star.velocityX *= -0.5;
|
|
339
|
+
}
|
|
340
|
+
if (star.baseX > canvas.width - 20) {
|
|
341
|
+
star.baseX = canvas.width - 20;
|
|
342
|
+
star.driftX *= -1;
|
|
343
|
+
star.velocityX *= -0.5;
|
|
344
|
+
}
|
|
345
|
+
if (star.baseY < 20) {
|
|
346
|
+
star.baseY = 20;
|
|
347
|
+
star.driftY *= -1;
|
|
348
|
+
star.velocityY *= -0.5;
|
|
349
|
+
}
|
|
350
|
+
if (star.baseY > canvas.height - 20) {
|
|
351
|
+
star.baseY = canvas.height - 20;
|
|
352
|
+
star.driftY *= -1;
|
|
353
|
+
star.velocityY *= -0.5;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const dx = mouseX - star.baseX;
|
|
357
|
+
const dy = mouseY - star.baseY;
|
|
358
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
359
|
+
const maxDistance = 300;
|
|
360
|
+
|
|
361
|
+
const twinkle = Math.sin(time * star.twinkleSpeed + star.twinkleOffset) * 0.3 + 0.7;
|
|
362
|
+
|
|
363
|
+
if (distance < maxDistance) {
|
|
364
|
+
const force = (maxDistance - distance) / maxDistance;
|
|
365
|
+
star.x = star.baseX + dx * force * star.speed * 0.3;
|
|
366
|
+
star.y = star.baseY + dy * force * star.speed * 0.3;
|
|
367
|
+
|
|
368
|
+
const brightness = Math.min(1, star.opacity * twinkle + force * 0.5);
|
|
369
|
+
ctx.fillStyle = `rgba(147, 197, 253, ${brightness})`;
|
|
370
|
+
ctx.shadowBlur = 4 + force * 8;
|
|
371
|
+
ctx.shadowColor = "rgba(147, 197, 253, 0.8)";
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
star.x += (star.baseX - star.x) * 0.1;
|
|
375
|
+
star.y += (star.baseY - star.y) * 0.1;
|
|
376
|
+
|
|
377
|
+
ctx.fillStyle = `rgba(255, 255, 255, ${star.opacity * twinkle})`;
|
|
378
|
+
ctx.shadowBlur = 0;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const rotation = time * star.twinkleSpeed * 2;
|
|
382
|
+
drawStar(star.x, star.y, star.size + 1, rotation);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// Draw particles
|
|
386
|
+
for (let i = particles.length - 1; i >= 0; i--) {
|
|
387
|
+
const particle = particles[i];
|
|
388
|
+
|
|
389
|
+
particle.x += particle.vx;
|
|
390
|
+
particle.y += particle.vy;
|
|
391
|
+
particle.vx *= 0.98;
|
|
392
|
+
particle.vy *= 0.98;
|
|
393
|
+
particle.life -= 0.02;
|
|
394
|
+
|
|
395
|
+
if (particle.life <= 0) {
|
|
396
|
+
particles.splice(i, 1);
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const alpha = particle.life;
|
|
401
|
+
const gradient = ctx.createRadialGradient(
|
|
402
|
+
particle.x, particle.y, 0,
|
|
403
|
+
particle.x, particle.y, particle.size * 2
|
|
404
|
+
);
|
|
405
|
+
gradient.addColorStop(0, `rgba(147, 197, 253, ${alpha})`);
|
|
406
|
+
gradient.addColorStop(0.5, `rgba(96, 165, 250, ${alpha * 0.5})`);
|
|
407
|
+
gradient.addColorStop(1, `rgba(59, 130, 246, 0)`);
|
|
408
|
+
|
|
409
|
+
ctx.fillStyle = gradient;
|
|
410
|
+
ctx.shadowBlur = 8;
|
|
411
|
+
ctx.shadowColor = `rgba(147, 197, 253, ${alpha})`;
|
|
412
|
+
|
|
413
|
+
ctx.beginPath();
|
|
414
|
+
ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
|
|
415
|
+
ctx.fill();
|
|
416
|
+
|
|
417
|
+
ctx.shadowBlur = 0;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
requestAnimationFrame(animate);
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
container.addEventListener("mousemove", handleMouseMove);
|
|
424
|
+
container.addEventListener("click", handleClick);
|
|
425
|
+
window.addEventListener("resize", handleResize);
|
|
426
|
+
const animationId = requestAnimationFrame(animate);
|
|
427
|
+
|
|
428
|
+
return () => {
|
|
429
|
+
container.removeEventListener("mousemove", handleMouseMove);
|
|
430
|
+
container.removeEventListener("click", handleClick);
|
|
431
|
+
window.removeEventListener("resize", handleResize);
|
|
432
|
+
cancelAnimationFrame(animationId);
|
|
433
|
+
};
|
|
434
|
+
}, []);
|
|
4
435
|
|
|
5
|
-
export default function Home({ version = "0.2.0" }: HomeProps) {
|
|
6
436
|
return (
|
|
7
|
-
<main
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
display: "flex",
|
|
13
|
-
flexDirection: "column",
|
|
14
|
-
alignItems: "center",
|
|
15
|
-
justifyContent: "center",
|
|
16
|
-
padding: "2rem",
|
|
17
|
-
boxSizing: "border-box"
|
|
18
|
-
}}>
|
|
19
|
-
<div style={{
|
|
20
|
-
width: 64,
|
|
21
|
-
height: 64,
|
|
22
|
-
background: "#fff",
|
|
23
|
-
borderRadius: 14,
|
|
24
|
-
display: "flex",
|
|
25
|
-
alignItems: "center",
|
|
26
|
-
justifyContent: "center",
|
|
27
|
-
marginBottom: "2rem"
|
|
28
|
-
}}>
|
|
29
|
-
<svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#0a0a0a" strokeWidth="2.5">
|
|
30
|
-
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
|
|
31
|
-
</svg>
|
|
32
|
-
</div>
|
|
437
|
+
<main ref={containerRef} className="relative w-full h-screen overflow-hidden flex flex-col items-center justify-center gap-8">
|
|
438
|
+
<canvas
|
|
439
|
+
ref={canvasRef}
|
|
440
|
+
className="absolute inset-0 bg-neutral-950"
|
|
441
|
+
/>
|
|
33
442
|
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
lineHeight: 1.6,
|
|
50
|
-
textAlign: "center"
|
|
51
|
-
}}>
|
|
52
|
-
Your application is ready. Start building by editing the files in <code style={{ color: "#a1a1aa", background: "#1a1a1a", padding: "2px 6px", borderRadius: 4 }}>resources/views</code>
|
|
53
|
-
</p>
|
|
54
|
-
|
|
55
|
-
<a
|
|
56
|
-
href="https://nitronjs.dev/docs"
|
|
57
|
-
style={{
|
|
58
|
-
display: "inline-flex",
|
|
59
|
-
alignItems: "center",
|
|
60
|
-
gap: "0.5rem",
|
|
61
|
-
padding: "0.75rem 1.5rem",
|
|
62
|
-
background: "#fff",
|
|
63
|
-
color: "#0a0a0a",
|
|
64
|
-
textDecoration: "none",
|
|
65
|
-
fontWeight: 600,
|
|
66
|
-
fontSize: "0.9rem",
|
|
67
|
-
borderRadius: 8
|
|
68
|
-
}}
|
|
69
|
-
>
|
|
70
|
-
Documentation
|
|
71
|
-
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
|
72
|
-
<path d="M5 12h14M12 5l7 7-7 7"/>
|
|
73
|
-
</svg>
|
|
74
|
-
</a>
|
|
75
|
-
|
|
76
|
-
<div style={{
|
|
77
|
-
position: "fixed",
|
|
78
|
-
bottom: "1.5rem",
|
|
79
|
-
color: "#3f3f46",
|
|
80
|
-
fontSize: "0.8rem"
|
|
81
|
-
}}>
|
|
82
|
-
v{version}
|
|
443
|
+
<div className="z-10 flex flex-col items-center justify-center gap-8 px-4">
|
|
444
|
+
<h1 className="text-center text-white text-6xl font-bold drop-shadow-2xl">
|
|
445
|
+
Welcome to <span className="bg-linear-to-r from-blue-500 to-purple-500 bg-clip-text text-transparent">NitronJS!</span>
|
|
446
|
+
</h1>
|
|
447
|
+
<p className="text-center text-zinc-400 text-xl drop-shadow-lg">
|
|
448
|
+
This is the home page of your NitronJS application.
|
|
449
|
+
</p>
|
|
450
|
+
<a
|
|
451
|
+
className="py-4 px-6 bg-white rounded-lg text-center text-neutral-900 font-semibold hover:scale-105 hover:shadow-2xl hover:shadow-blue-500/20 transition-all duration-300"
|
|
452
|
+
href="https://nitronjs.dev/docs"
|
|
453
|
+
target="_blank"
|
|
454
|
+
>
|
|
455
|
+
Read the Documentation
|
|
456
|
+
</a>
|
|
457
|
+
<p className="absolute bottom-10 left-1/2 -translate-x-1/2 text-center text-zinc-500 text-sm"><b>Version:</b> {version}</p>
|
|
83
458
|
</div>
|
|
459
|
+
|
|
460
|
+
<div className="absolute bottom-0 left-0 right-0 h-px bg-linear-to-r from-transparent via-blue-500/50 to-transparent" />
|
|
84
461
|
</main>
|
|
85
462
|
);
|
|
86
463
|
}
|
package/skeleton/tsconfig.json
CHANGED
|
@@ -13,7 +13,12 @@
|
|
|
13
13
|
"noEmit": true,
|
|
14
14
|
"baseUrl": ".",
|
|
15
15
|
"paths": {
|
|
16
|
-
"@/*": ["./*"]
|
|
16
|
+
"@/*": ["./*"],
|
|
17
|
+
"@css/*": ["./resources/css/*"],
|
|
18
|
+
"@views/*": ["./resources/views/*"],
|
|
19
|
+
"@models/*": ["./app/Models/*"],
|
|
20
|
+
"@controllers/*": ["./app/Controllers/*"],
|
|
21
|
+
"@middlewares/*": ["./app/Middlewares/*"],
|
|
17
22
|
}
|
|
18
23
|
},
|
|
19
24
|
"include": [
|
package/lib/Auth/Manager.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import Hash from "../Hashing/Manager.js";
|
|
2
|
-
import Config from "../Core/Config.js";
|
|
3
|
-
|
|
4
|
-
class Auth {
|
|
5
|
-
static setup(server) {
|
|
6
|
-
server.decorateRequest('auth', null);
|
|
7
|
-
|
|
8
|
-
server.addHook('onRequest', async (req, res) => {
|
|
9
|
-
req.auth = {
|
|
10
|
-
guard: (guardName = null) => ({
|
|
11
|
-
attempt: (credentials) => Auth.attempt(req, credentials, guardName),
|
|
12
|
-
logout: () => Auth.logout(req, guardName),
|
|
13
|
-
user: () => Auth.user(req, guardName),
|
|
14
|
-
check: () => Auth.check(req, guardName),
|
|
15
|
-
home: () => Auth.home(res, guardName),
|
|
16
|
-
redirect: () => Auth.redirect(res, guardName)
|
|
17
|
-
}),
|
|
18
|
-
attempt: (credentials) => Auth.attempt(req, credentials, null),
|
|
19
|
-
logout: () => Auth.logout(req, null),
|
|
20
|
-
user: () => Auth.user(req, null),
|
|
21
|
-
check: () => Auth.check(req, null),
|
|
22
|
-
home: () => Auth.home(res, null),
|
|
23
|
-
redirect: () => Auth.redirect(res, null)
|
|
24
|
-
};
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static #getAuthConfig() {
|
|
29
|
-
return Config.all("auth");
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static async attempt(req, credentials, guardName = null) {
|
|
33
|
-
const authConfig = this.#getAuthConfig();
|
|
34
|
-
const guard = guardName || authConfig.defaults.guard;
|
|
35
|
-
const config = authConfig.guards[guard];
|
|
36
|
-
|
|
37
|
-
if (!config) throw new Error(`Guard '${guard}' not configured`);
|
|
38
|
-
|
|
39
|
-
const { provider, identifier } = config;
|
|
40
|
-
|
|
41
|
-
const user = await provider
|
|
42
|
-
.where(identifier, '=', credentials[identifier])
|
|
43
|
-
.first();
|
|
44
|
-
|
|
45
|
-
if (!user) return false;
|
|
46
|
-
|
|
47
|
-
const isValid = await Hash.check(credentials.password, user.password);
|
|
48
|
-
if (!isValid) return false;
|
|
49
|
-
|
|
50
|
-
req.session.regenerate();
|
|
51
|
-
req.session.set(`auth_${guard}`, user.id);
|
|
52
|
-
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
static logout(req, guardName = null) {
|
|
57
|
-
const authConfig = this.#getAuthConfig();
|
|
58
|
-
const guard = guardName || authConfig.defaults.guard;
|
|
59
|
-
|
|
60
|
-
req.session.set(`auth_${guard}`, null);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
static async user(req, guardName = null) {
|
|
64
|
-
const authConfig = this.#getAuthConfig();
|
|
65
|
-
const guard = guardName || authConfig.defaults.guard;
|
|
66
|
-
const userId = req.session.get(`auth_${guard}`) || null;
|
|
67
|
-
|
|
68
|
-
if (!userId) return null;
|
|
69
|
-
|
|
70
|
-
const config = authConfig.guards[guard];
|
|
71
|
-
|
|
72
|
-
if (!config) return null;
|
|
73
|
-
|
|
74
|
-
return await config.provider.find(userId);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
static check(req, guardName = null) {
|
|
78
|
-
const authConfig = this.#getAuthConfig();
|
|
79
|
-
const guard = guardName || authConfig.defaults.guard;
|
|
80
|
-
|
|
81
|
-
return req.session.get(`auth_${guard}`) !== null && req.session.get(`auth_${guard}`) !== undefined;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
static home(res, guardName = null) {
|
|
85
|
-
const authConfig = this.#getAuthConfig();
|
|
86
|
-
const guard = guardName || authConfig.defaults.guard;
|
|
87
|
-
const config = authConfig.guards[guard];
|
|
88
|
-
|
|
89
|
-
return res.redirect(this.#resolveUrl(config?.home));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
static redirect(res, guardName = null) {
|
|
93
|
-
const authConfig = this.#getAuthConfig();
|
|
94
|
-
const guard = guardName || authConfig.defaults.guard;
|
|
95
|
-
const config = authConfig.guards[guard];
|
|
96
|
-
|
|
97
|
-
return res.redirect(this.#resolveUrl(config?.redirect));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
static #resolveUrl(path) {
|
|
101
|
-
if (!path) return '/';
|
|
102
|
-
|
|
103
|
-
if (path.startsWith('/') || path.startsWith('http://') || path.startsWith('https://')) {
|
|
104
|
-
return path;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return route(path);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export default Auth;
|