create-nexwire 4.2.4 → 4.3.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 (113) hide show
  1. package/README.md +20 -8
  2. package/express/.env +1 -1
  3. package/express/.vscode/extensions.json +6 -0
  4. package/express/.vscode/settings.json +37 -26
  5. package/express/biome.json +99 -66
  6. package/express/package.json +31 -29
  7. package/express/src/config/database.ts +48 -29
  8. package/express/src/config/index.ts +83 -83
  9. package/express/src/config/openapi.ts +6 -24
  10. package/express/src/config/queue.ts +30 -30
  11. package/express/src/config/validate.ts +50 -40
  12. package/express/src/database/migrations/sqlite/0000_init.sql +47 -47
  13. package/express/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -1
  14. package/express/src/database/migrations/sqlite/meta/_journal.json +1 -1
  15. package/express/src/database/schema.ts +2 -2
  16. package/express/src/framework/cache/cache.ts +40 -8
  17. package/express/src/framework/circuit-breaker/cb.ts +88 -60
  18. package/express/src/framework/database/connection.ts +52 -27
  19. package/express/src/framework/events/dispatcher.ts +61 -49
  20. package/express/src/framework/facade.ts +46 -3
  21. package/express/src/framework/http/app.ts +28 -22
  22. package/express/src/framework/http/logger.ts +27 -16
  23. package/express/src/framework/http/openapi.ts +9 -11
  24. package/express/src/framework/modules/routes.ts +26 -21
  25. package/express/src/framework/notification/channels/broadcast.ts +15 -0
  26. package/express/src/framework/notification/channels/mail.ts +40 -0
  27. package/express/src/framework/notification/contracts.ts +29 -0
  28. package/express/src/framework/notification/index.ts +19 -94
  29. package/express/src/framework/notification/registry.ts +15 -0
  30. package/express/src/framework/providers/adapter.ts +27 -17
  31. package/express/src/framework/queue/queue.ts +43 -44
  32. package/express/src/framework/realtime/broadcast.ts +29 -5
  33. package/express/src/framework/realtime/socket.ts +149 -119
  34. package/express/src/framework/redis/client.ts +148 -151
  35. package/express/src/framework/runtime/server-adapter.ts +39 -34
  36. package/express/src/framework/scheduler/lock.ts +128 -116
  37. package/express/src/framework/server.ts +33 -49
  38. package/express/src/framework/session/session.ts +69 -14
  39. package/express/src/framework/storage/storage.ts +744 -785
  40. package/express/src/framework/support/mail.ts +15 -7
  41. package/express/src/providers/notification.ts +4 -0
  42. package/express/src/resources/src/components/Checkbox.vue +32 -29
  43. package/express/src/resources/src/components/Input.vue +243 -223
  44. package/express/src/resources/src/components/InputGroup.vue +147 -145
  45. package/express/src/resources/src/components/InputPasswordToggle.vue +229 -213
  46. package/express/src/resources/src/components/Modal.vue +71 -55
  47. package/express/src/resources/src/components/Refresh.vue +19 -0
  48. package/express/src/resources/src/helpers/assets.ts +51 -0
  49. package/express/src/resources/src/layouts/Layout/Header.vue +124 -105
  50. package/express/src/resources/src/main.ts +3 -1
  51. package/express/src/resources/src/plugins/gum.ts +1 -1
  52. package/express/src/resources/src/plugins/pulse.ts +157 -147
  53. package/express/src/resources/src/stores/auth.ts +184 -164
  54. package/express/src/resources/vite.config.ts +54 -36
  55. package/express/src/storage/database/nexwire.sqlite +0 -0
  56. package/express/src/storage/logs/app.log +0 -0
  57. package/express/src/storage/logs/fatal.log +0 -0
  58. package/express/src/types/global.d.ts +32 -26
  59. package/hono/.env +1 -1
  60. package/hono/.vscode/extensions.json +6 -0
  61. package/hono/.vscode/settings.json +37 -26
  62. package/hono/biome.json +25 -2
  63. package/hono/package.json +25 -23
  64. package/hono/src/config/database.ts +48 -29
  65. package/hono/src/config/index.ts +83 -83
  66. package/hono/src/config/openapi.ts +6 -24
  67. package/hono/src/config/queue.ts +30 -30
  68. package/hono/src/config/validate.ts +50 -40
  69. package/hono/src/database/migrations/sqlite/0000_init.sql +47 -47
  70. package/hono/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -1
  71. package/hono/src/database/migrations/sqlite/meta/_journal.json +1 -1
  72. package/hono/src/database/schema.ts +2 -2
  73. package/hono/src/framework/cache/cache.ts +40 -8
  74. package/hono/src/framework/circuit-breaker/cb.ts +88 -60
  75. package/hono/src/framework/database/connection.ts +52 -27
  76. package/hono/src/framework/events/dispatcher.ts +61 -49
  77. package/hono/src/framework/facade.ts +38 -1
  78. package/hono/src/framework/http/openapi.ts +7 -9
  79. package/hono/src/framework/notification/channels/broadcast.ts +15 -0
  80. package/hono/src/framework/notification/channels/mail.ts +40 -0
  81. package/hono/src/framework/notification/contracts.ts +29 -0
  82. package/hono/src/framework/notification/index.ts +19 -94
  83. package/hono/src/framework/notification/registry.ts +15 -0
  84. package/hono/src/framework/providers/adapter.ts +27 -17
  85. package/hono/src/framework/queue/queue.ts +43 -44
  86. package/hono/src/framework/realtime/broadcast.ts +29 -5
  87. package/hono/src/framework/realtime/socket.ts +217 -196
  88. package/hono/src/framework/redis/client.ts +148 -151
  89. package/hono/src/framework/scheduler/lock.ts +128 -116
  90. package/hono/src/framework/server.ts +27 -29
  91. package/hono/src/framework/session/session.ts +62 -14
  92. package/hono/src/framework/storage/storage.ts +744 -785
  93. package/hono/src/framework/support/mail.ts +56 -48
  94. package/hono/src/providers/notification.ts +4 -0
  95. package/hono/src/resources/src/components/Checkbox.vue +32 -29
  96. package/hono/src/resources/src/components/Input.vue +243 -234
  97. package/hono/src/resources/src/components/InputGroup.vue +147 -149
  98. package/hono/src/resources/src/components/InputPasswordToggle.vue +229 -222
  99. package/hono/src/resources/src/components/Modal.vue +71 -55
  100. package/hono/src/resources/src/components/Refresh.vue +19 -0
  101. package/hono/src/resources/src/helpers/assets.ts +51 -0
  102. package/hono/src/resources/src/layouts/Layout/Header.vue +124 -105
  103. package/hono/src/resources/src/main.ts +3 -1
  104. package/hono/src/resources/src/plugins/gum.ts +1 -1
  105. package/hono/src/resources/src/plugins/pulse.ts +157 -147
  106. package/hono/src/resources/src/stores/auth.ts +184 -164
  107. package/hono/src/resources/vite.config.ts +54 -36
  108. package/hono/src/storage/database/nexwire.sqlite +0 -0
  109. package/hono/src/storage/logs/app.log +0 -0
  110. package/hono/src/storage/logs/fatal.log +0 -0
  111. package/hono/src/types/global.d.ts +32 -26
  112. package/package.json +2 -2
  113. package/src/index.js +139 -14
@@ -1,164 +1,184 @@
1
- import axios from "axios";
2
- import { defineStore } from "pinia";
3
- import { ref } from "vue";
4
- import { type AuthUser, clearUser, setUser } from "@/composables/useAuth";
5
-
6
- type LoginPayload = { email: string; password: string; remember?: boolean };
7
- type RegisterPayload = {
8
- name: string;
9
- email: string;
10
- password: string;
11
- password_confirmation: string;
12
- };
13
- type VerifyEmailPayload = { email: string; token: string };
14
- type ForgotPayload = { email: string };
15
- type ResetPayload = {
16
- email: string;
17
- token: string;
18
- password: string;
19
- password_confirmation: string;
20
- };
21
-
22
- type ApiResponse<T> = { message: string; data?: T };
23
- type AuthData = { user: AuthUser };
24
-
25
- async function request<T>(method: "GET" | "POST", path: string, payload?: unknown): Promise<ApiResponse<T>> {
26
- try {
27
- const response = await axios.request<ApiResponse<T>>({
28
- method,
29
- url: `/api/auth${path}`,
30
- data: payload
31
- });
32
-
33
- return response.data;
34
- } catch (error: unknown) {
35
- if (axios.isAxiosError(error)) {
36
- throw new Error(String(error.response?.data?.message || error.message || "Request failed"));
37
- }
38
- throw new Error("Request failed");
39
- }
40
- }
41
-
42
- const MAX_BOOTSTRAP_ATTEMPTS = 5;
43
- const BOOTSTRAP_BACKOFF_MS = 500;
44
-
45
- const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
46
-
47
- export const useAuthStore = defineStore("auth", () => {
48
- const user = ref<AuthUser | null>(null);
49
- const isAuthenticated = ref(false);
50
- const processing = ref(false);
51
- const initialized = ref(false);
52
-
53
- const syncUser = (value: AuthUser | null) => {
54
- user.value = value;
55
- isAuthenticated.value = !!value;
56
- if (value) setUser(value);
57
- else clearUser();
58
- };
59
-
60
- const bootstrap = async () => {
61
- if (initialized.value) return;
62
-
63
- for (let attempt = 1; attempt <= MAX_BOOTSTRAP_ATTEMPTS; attempt++) {
64
- try {
65
- const response = await axios.get<ApiResponse<AuthUser>>("/api/auth/me");
66
- syncUser((response.data?.data || null) as AuthUser | null);
67
- break;
68
- } catch (error) {
69
- const backendUnreachable = axios.isAxiosError(error) && !error.response;
70
- if (!backendUnreachable || attempt === MAX_BOOTSTRAP_ATTEMPTS) {
71
- syncUser(null);
72
- break;
73
- }
74
- await sleep(BOOTSTRAP_BACKOFF_MS * 2 ** (attempt - 1));
75
- }
76
- }
77
-
78
- initialized.value = true;
79
- };
80
-
81
- const login = async (payload: LoginPayload) => {
82
- processing.value = true;
83
- try {
84
- const data = await request<AuthData>("POST", "/login", payload);
85
- syncUser((data?.data?.user || null) as AuthUser | null);
86
- initialized.value = true;
87
- return data.message || "Login successful";
88
- } finally {
89
- processing.value = false;
90
- }
91
- };
92
-
93
- const register = async (payload: RegisterPayload) => {
94
- processing.value = true;
95
- try {
96
- const data = await request<AuthData>("POST", "/register", payload);
97
- const createdUser = (data?.data?.user || null) as AuthUser | null;
98
- if (createdUser) {
99
- syncUser(createdUser);
100
- initialized.value = true;
101
- } else {
102
- syncUser(null);
103
- }
104
- return data.message || "Registration successful";
105
- } finally {
106
- processing.value = false;
107
- }
108
- };
109
-
110
- const verifyEmail = async (payload: VerifyEmailPayload) => {
111
- processing.value = true;
112
- try {
113
- const data = await request<unknown>("POST", "/verify-email", payload);
114
- return data.message || "Email verified successfully";
115
- } finally {
116
- processing.value = false;
117
- }
118
- };
119
-
120
- const forgotPassword = async (payload: ForgotPayload) => {
121
- processing.value = true;
122
- try {
123
- const data = await request<unknown>("POST", "/forgot-password", payload);
124
- return data.message || "If this email exists, a reset link has been sent";
125
- } finally {
126
- processing.value = false;
127
- }
128
- };
129
-
130
- const resetPassword = async (payload: ResetPayload) => {
131
- processing.value = true;
132
- try {
133
- const data = await request<unknown>("POST", "/reset-password", payload);
134
- return data.message || "Password reset successfully";
135
- } finally {
136
- processing.value = false;
137
- }
138
- };
139
-
140
- const logout = async () => {
141
- processing.value = true;
142
- try {
143
- await request<unknown>("POST", "/logout");
144
- } finally {
145
- syncUser(null);
146
- processing.value = false;
147
- initialized.value = true;
148
- }
149
- };
150
-
151
- return {
152
- user,
153
- isAuthenticated,
154
- processing,
155
- initialized,
156
- bootstrap,
157
- register,
158
- login,
159
- forgotPassword,
160
- resetPassword,
161
- verifyEmail,
162
- logout
163
- };
164
- });
1
+ import axios from "axios";
2
+ import { defineStore } from "pinia";
3
+ import { ref } from "vue";
4
+ import { type AuthUser, clearUser, setUser } from "@/composables/useAuth";
5
+
6
+ type LoginPayload = { email?: string; phone?: string; password: string; remember?: boolean };
7
+ type VerifyEmailPayload = { email: string; token: string };
8
+ type ForgotPayload = { email: string };
9
+
10
+ type RegisterPayload = {
11
+ name: string;
12
+ email?: string;
13
+ phone?: string;
14
+ password: string;
15
+ password_confirmation: string;
16
+ };
17
+
18
+ type ResetPayload = {
19
+ email: string;
20
+ token: string;
21
+ password: string;
22
+ password_confirmation: string;
23
+ };
24
+
25
+ type ApiResponse<T> = { message: string; data?: T };
26
+ type AuthData = { user: AuthUser };
27
+
28
+ async function request<T>(method: "GET" | "POST", path: string, payload?: unknown): Promise<ApiResponse<T>> {
29
+ try {
30
+ const response = await axios.request<ApiResponse<T>>({
31
+ method,
32
+ url: `/api/auth${path}`,
33
+ data: payload
34
+ });
35
+
36
+ return response.data;
37
+ } catch (error: unknown) {
38
+ if (axios.isAxiosError(error)) {
39
+ throw new Error(String(error.response?.data?.message || error.message || "Request failed"));
40
+ }
41
+ throw new Error("Request failed");
42
+ }
43
+ }
44
+
45
+ const MAX_BOOTSTRAP_ATTEMPTS = 5;
46
+ const BOOTSTRAP_BACKOFF_MS = 500;
47
+
48
+ const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
49
+
50
+ export const useAuthStore = defineStore("auth", () => {
51
+ const user = ref<AuthUser | null>(null);
52
+ const isAuthenticated = ref(false);
53
+ const processing = ref(false);
54
+ const initialized = ref(false);
55
+
56
+ const syncUser = (value: AuthUser | null) => {
57
+ user.value = value;
58
+ isAuthenticated.value = !!value;
59
+ if (value) setUser(value);
60
+ else clearUser();
61
+ };
62
+
63
+ let bootstrapPromise: Promise<void> | null = null;
64
+ const bootstrap = async () => {
65
+ if (initialized.value) return;
66
+
67
+ // Reuse the same request if multiple navigations call bootstrap.
68
+ if (bootstrapPromise) {
69
+ return bootstrapPromise;
70
+ }
71
+
72
+ bootstrapPromise = (async () => {
73
+ for (let attempt = 1; attempt <= MAX_BOOTSTRAP_ATTEMPTS; attempt++) {
74
+ try {
75
+ const response = await axios.get<ApiResponse<AuthUser>>("/api/auth/me");
76
+
77
+ syncUser((response.data?.data || null) as AuthUser | null);
78
+ initialized.value = true;
79
+ return;
80
+ } catch (error) {
81
+ const backendUnreachable = axios.isAxiosError(error) && !error.response;
82
+
83
+ if (!backendUnreachable || attempt === MAX_BOOTSTRAP_ATTEMPTS) {
84
+ syncUser(null);
85
+ initialized.value = true;
86
+ return;
87
+ }
88
+
89
+ await sleep(BOOTSTRAP_BACKOFF_MS * 2 ** (attempt - 1));
90
+ }
91
+ }
92
+ })();
93
+
94
+ try {
95
+ await bootstrapPromise;
96
+ } finally {
97
+ bootstrapPromise = null;
98
+ }
99
+ };
100
+
101
+ const login = async (payload: LoginPayload) => {
102
+ processing.value = true;
103
+ try {
104
+ const data = await request<AuthData>("POST", "/login", payload);
105
+ syncUser((data?.data?.user || null) as AuthUser | null);
106
+ initialized.value = true;
107
+ return data.message || "Login successful";
108
+ } finally {
109
+ processing.value = false;
110
+ }
111
+ };
112
+
113
+ const register = async (payload: RegisterPayload) => {
114
+ processing.value = true;
115
+ try {
116
+ const data = await request<AuthData>("POST", "/register", payload);
117
+ const createdUser = (data?.data?.user || null) as AuthUser | null;
118
+ if (createdUser) {
119
+ syncUser(createdUser);
120
+ initialized.value = true;
121
+ } else {
122
+ syncUser(null);
123
+ }
124
+ return data.message || "Registration successful";
125
+ } finally {
126
+ processing.value = false;
127
+ }
128
+ };
129
+
130
+ const verifyEmail = async (payload: VerifyEmailPayload) => {
131
+ processing.value = true;
132
+ try {
133
+ const data = await request<unknown>("POST", "/verify-email", payload);
134
+ return data.message || "Email verified successfully";
135
+ } finally {
136
+ processing.value = false;
137
+ }
138
+ };
139
+
140
+ const forgotPassword = async (payload: ForgotPayload) => {
141
+ processing.value = true;
142
+ try {
143
+ const data = await request<unknown>("POST", "/forgot-password", payload);
144
+ return data.message || "If this email exists, a reset link has been sent";
145
+ } finally {
146
+ processing.value = false;
147
+ }
148
+ };
149
+
150
+ const resetPassword = async (payload: ResetPayload) => {
151
+ processing.value = true;
152
+ try {
153
+ const data = await request<unknown>("POST", "/reset-password", payload);
154
+ return data.message || "Password reset successfully";
155
+ } finally {
156
+ processing.value = false;
157
+ }
158
+ };
159
+
160
+ const logout = async () => {
161
+ processing.value = true;
162
+ try {
163
+ await request<unknown>("POST", "/logout");
164
+ } finally {
165
+ syncUser(null);
166
+ processing.value = false;
167
+ initialized.value = true;
168
+ }
169
+ };
170
+
171
+ return {
172
+ user,
173
+ isAuthenticated,
174
+ processing,
175
+ initialized,
176
+ bootstrap,
177
+ register,
178
+ login,
179
+ forgotPassword,
180
+ resetPassword,
181
+ verifyEmail,
182
+ logout
183
+ };
184
+ });
@@ -1,46 +1,64 @@
1
1
  import path from "node:path";
2
2
  import { fileURLToPath, URL } from "node:url";
3
3
  import vue from "@vitejs/plugin-vue";
4
- import { defineConfig } from "vite";
4
+ import { defineConfig, loadEnv } from "vite";
5
5
 
6
- const cacheBase = process.env.LOCALAPPDATA || process.env.TEMP || ".";
7
- const apiUrl = process.env.APP_URL || "http://localhost:3000";
8
- const socketEnabled = process.env.SOCKET !== "false";
6
+ const configDir = path.dirname(fileURLToPath(import.meta.url));
7
+ const projectRoot = path.resolve(configDir, "../..");
9
8
 
10
- const proxy: Record<string, any> = {
11
- "/api": { target: apiUrl, changeOrigin: true },
12
- "/health": { target: apiUrl, changeOrigin: true },
13
- "/storage": { target: apiUrl, changeOrigin: true }
14
- };
9
+ export default defineConfig(({ mode }) => {
10
+ // 1. Load the .env file just like the backend does. Resolve it from the
11
+ // config file so a different process cwd cannot point Vite at the wrong .env.
12
+ const env = loadEnv(mode, projectRoot, "");
15
13
 
16
- proxy["/socket.io"] = { target: apiUrl, changeOrigin: true, ws: true };
14
+ const cacheBase = process.env.LOCALAPPDATA || process.env.TEMP || ".";
15
+ const apiUrl = env.APP_URL || "http://localhost:3000";
17
16
 
18
- export default defineConfig({
19
- define: {
20
- __SOCKET_ENABLED__: socketEnabled,
21
- __API_URL__: JSON.stringify(apiUrl)
22
- },
23
- root: "src/resources",
24
- cacheDir: path.join(cacheBase, "nexwire", "vite-cache", "resources"),
25
- plugins: [vue()],
26
- css: {
27
- preprocessorOptions: {
28
- scss: {
29
- quietDeps: true
17
+ // Match the backend default: Socket.IO is off unless SOCKET=true
18
+ const socketEnabled = env.SOCKET === "true";
19
+
20
+ const proxy: Record<string, any> = {
21
+ "/api": { target: apiUrl, changeOrigin: true },
22
+ "/health": { target: apiUrl, changeOrigin: true },
23
+ "/storage": { target: apiUrl, changeOrigin: true }
24
+ };
25
+
26
+ if (socketEnabled) {
27
+ proxy["/socket.io"] = { target: apiUrl, changeOrigin: true, ws: true, timeout: 10000 };
28
+ }
29
+
30
+ return {
31
+ define: {
32
+ // 3. ALWAYS stringify the value when using Vite define
33
+ // `import.meta.env.*` is inlined into every module in dev as well as in
34
+ // the production bundle, so the UI never depends on a stale global.
35
+ "import.meta.env.VITE_SOCKET_ENABLED": JSON.stringify(socketEnabled),
36
+ __SOCKET_ENABLED__: JSON.stringify(socketEnabled),
37
+ __API_URL__: JSON.stringify(apiUrl)
38
+ },
39
+ root: fileURLToPath(new URL(".", import.meta.url)),
40
+ cacheDir: path.join(cacheBase, "nexwire", "vite-cache", "resources"),
41
+ plugins: [vue()],
42
+ css: {
43
+ preprocessorOptions: {
44
+ scss: {
45
+ quietDeps: true,
46
+ silenceDeprecations: ["import", "if-function", "global-builtin", "color-functions", "slash-div"]
47
+ }
30
48
  }
49
+ },
50
+ resolve: {
51
+ alias: {
52
+ "@": fileURLToPath(new URL("./src", import.meta.url))
53
+ }
54
+ },
55
+ build: {
56
+ outDir: "../../public",
57
+ emptyOutDir: true
58
+ },
59
+ server: {
60
+ port: 5173,
61
+ proxy // /socket.io is only proxied when SOCKET=true
31
62
  }
32
- },
33
- resolve: {
34
- alias: {
35
- "@": fileURLToPath(new URL("./src", import.meta.url))
36
- }
37
- },
38
- build: {
39
- outDir: "../../public",
40
- emptyOutDir: true
41
- },
42
- server: {
43
- port: 5173,
44
- proxy
45
- }
63
+ };
46
64
  });
File without changes
File without changes
@@ -1,26 +1,32 @@
1
- declare module "*.vue" {
2
- import type { DefineComponent } from "vue";
3
-
4
- const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>;
5
- export default component;
6
- }
7
-
8
- declare module "bootstrap/js/dist/modal.js" {
9
- export default class Modal {
10
- constructor(element: Element, options?: { backdrop?: boolean | "static"; keyboard?: boolean });
11
- show(): void;
12
- hide(): void;
13
- dispose(): void;
14
- }
15
- }
16
-
17
- declare module "bootstrap/js/dist/toast.js" {
18
- export default class Toast {
19
- static getOrCreateInstance(element: Element): Toast;
20
- show(): void;
21
- }
22
- }
23
-
24
- declare module "luxon";
25
- declare module "nodemailer";
26
- declare module "vue-select";
1
+ declare module "*.vue" {
2
+ import type { DefineComponent } from "vue";
3
+
4
+ const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>;
5
+ export default component;
6
+ }
7
+
8
+ declare module "bootstrap/js/dist/modal.js" {
9
+ export default class Modal {
10
+ constructor(element: Element, options?: { backdrop?: boolean | "static"; keyboard?: boolean });
11
+ show(): void;
12
+ hide(): void;
13
+ dispose(): void;
14
+ }
15
+ }
16
+
17
+ declare module "bootstrap/js/dist/toast.js" {
18
+ export default class Toast {
19
+ static getOrCreateInstance(element: Element): Toast;
20
+ show(): void;
21
+ }
22
+ }
23
+
24
+ declare module "luxon";
25
+ declare module "nodemailer";
26
+ declare module "vue-select";
27
+
28
+ interface ImportMetaEnv {
29
+ readonly VITE_API_URL?: string;
30
+ readonly VITE_SOCKET_URL?: string;
31
+ readonly VITE_SOCKET_ENABLED?: boolean;
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nexwire",
3
- "version": "4.2.4",
3
+ "version": "4.3.0",
4
4
  "type": "module",
5
5
  "description": "Scaffold a new nexwire project",
6
6
  "bin": {
@@ -72,7 +72,7 @@
72
72
  "ioredis": "^5",
73
73
  "lodash-es": "^4",
74
74
  "luxon": "^3",
75
- "maildev": "^3",
75
+ "maildev": "^2.2.1",
76
76
  "mysql2": "^3",
77
77
  "nodemailer": "^10",
78
78
  "pinia": "^3",