@onexapis/cli 1.1.37 → 1.1.38

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 (48) hide show
  1. package/dist/cli.js +688 -454
  2. package/dist/cli.js.map +1 -1
  3. package/dist/cli.mjs +681 -449
  4. package/dist/cli.mjs.map +1 -1
  5. package/dist/index.js +343 -256
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +339 -253
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/preview/preview-app.tsx +5 -13
  10. package/package.json +8 -4
  11. package/templates/default/bundle-entry.ts +0 -5
  12. package/templates/default/index.ts +1 -21
  13. package/templates/default/sections-registry.ts +0 -28
  14. package/templates/default/theme.layout.ts +2 -53
  15. package/templates/default/AUTH_AND_PROFILE.md +0 -167
  16. package/templates/default/LAYOUT.md +0 -195
  17. package/templates/default/hooks/index.ts +0 -26
  18. package/templates/default/hooks/use-forgot-password-form.ts +0 -90
  19. package/templates/default/hooks/use-login-form.ts +0 -102
  20. package/templates/default/hooks/use-profile-form.ts +0 -255
  21. package/templates/default/hooks/use-register-form.ts +0 -154
  22. package/templates/default/hooks/use-verify-code-form.ts +0 -224
  23. package/templates/default/pages/forgot-password.ts +0 -41
  24. package/templates/default/pages/login.ts +0 -41
  25. package/templates/default/pages/profile.ts +0 -39
  26. package/templates/default/pages/register.ts +0 -41
  27. package/templates/default/pages/verify-code.ts +0 -41
  28. package/templates/default/sections/auth-forgot-password/auth-forgot-password-default.tsx +0 -192
  29. package/templates/default/sections/auth-forgot-password/auth-forgot-password.schema.ts +0 -150
  30. package/templates/default/sections/auth-forgot-password/index.ts +0 -14
  31. package/templates/default/sections/auth-login/auth-login-default.tsx +0 -238
  32. package/templates/default/sections/auth-login/auth-login.schema.ts +0 -171
  33. package/templates/default/sections/auth-login/index.ts +0 -14
  34. package/templates/default/sections/auth-register/auth-register-default.tsx +0 -327
  35. package/templates/default/sections/auth-register/auth-register.schema.ts +0 -188
  36. package/templates/default/sections/auth-register/index.ts +0 -14
  37. package/templates/default/sections/auth-verify-code/auth-verify-code-default.tsx +0 -209
  38. package/templates/default/sections/auth-verify-code/auth-verify-code.schema.ts +0 -150
  39. package/templates/default/sections/auth-verify-code/index.ts +0 -14
  40. package/templates/default/sections/footer/footer-default.tsx +0 -214
  41. package/templates/default/sections/footer/footer.schema.ts +0 -170
  42. package/templates/default/sections/footer/index.ts +0 -14
  43. package/templates/default/sections/header/header-default.tsx +0 -322
  44. package/templates/default/sections/header/header.schema.ts +0 -168
  45. package/templates/default/sections/header/index.ts +0 -14
  46. package/templates/default/sections/profile/index.ts +0 -14
  47. package/templates/default/sections/profile/profile-default.tsx +0 -522
  48. package/templates/default/sections/profile/profile.schema.ts +0 -228
@@ -1,224 +0,0 @@
1
- /**
2
- * Verify Code Form Hook
3
- * Manages OTP input state, countdown timer, and submission via useAuth
4
- */
5
-
6
- "use client";
7
-
8
- import { useState, useRef, useEffect, useCallback } from "react";
9
- import { useAuth } from "@onexapis/core/hooks";
10
-
11
- export interface UseVerifyCodeFormReturn {
12
- code: string[];
13
- error: string | null;
14
- countdown: number;
15
- email: string;
16
- username: string;
17
- isVerifying: boolean;
18
- isResending: boolean;
19
- isLoading: boolean;
20
- inputRefs: React.MutableRefObject<(HTMLInputElement | null)[]>;
21
- handleCodeChange: (index: number, value: string) => void;
22
- handleKeyDown: (
23
- index: number,
24
- e: React.KeyboardEvent<HTMLInputElement>
25
- ) => void;
26
- handlePaste: (e: React.ClipboardEvent) => void;
27
- handleSubmit: (e: React.FormEvent) => void;
28
- handleResend: () => void;
29
- setError: (error: string | null) => void;
30
- }
31
-
32
- export function useVerifyCodeForm(): UseVerifyCodeFormReturn {
33
- const [code, setCode] = useState<string[]>(["", "", "", "", "", ""]);
34
- const [error, setError] = useState<string | null>(null);
35
- const [countdown, setCountdown] = useState(0);
36
- const [email, setEmail] = useState("");
37
- const [username, setUsername] = useState("");
38
- const [isVerifying, setIsVerifying] = useState(false);
39
- const [isResending, setIsResending] = useState(false);
40
- const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
41
-
42
- const { verifyCode, verifyCodeReset, resendCode } = useAuth();
43
-
44
- // Extract username from URL search params
45
- useEffect(() => {
46
- if (typeof window !== "undefined") {
47
- const params = new URLSearchParams(window.location.search);
48
- const u = params.get("username") || "";
49
- setUsername(u);
50
-
51
- if (u) {
52
- const storedEmail = localStorage.getItem(`register_email_${u}`);
53
- if (storedEmail) setEmail(storedEmail);
54
-
55
- const storedValue = localStorage.getItem(`resend_countdown_${u}`);
56
- if (storedValue) {
57
- const expiryTimestamp = parseInt(storedValue, 10);
58
- const remaining = Math.max(
59
- 0,
60
- Math.floor((expiryTimestamp - Date.now()) / 1000)
61
- );
62
- if (remaining > 0) setCountdown(remaining);
63
- }
64
- }
65
- }
66
- }, []);
67
-
68
- // Countdown timer
69
- useEffect(() => {
70
- if (countdown > 0) {
71
- const timer = setInterval(() => {
72
- setCountdown((prev) => prev - 1);
73
- }, 1000);
74
- return () => clearInterval(timer);
75
- }
76
- }, [countdown]);
77
-
78
- const handleSubmitCode = useCallback(
79
- async (fullCode: string) => {
80
- if (!username) {
81
- setError("Account information not found");
82
- return;
83
- }
84
-
85
- setIsVerifying(true);
86
- setError(null);
87
- try {
88
- const params = new URLSearchParams(window.location.search);
89
- const mode = params.get("mode");
90
-
91
- if (mode === "reset") {
92
- const result = await verifyCodeReset({ username, code: fullCode });
93
- // Clean up and redirect to reset-password
94
- localStorage.removeItem(`register_email_${username}`);
95
- localStorage.removeItem(`resend_countdown_${username}`);
96
- const session = result?.session;
97
- window.location.href = session
98
- ? `/reset-password?session=${encodeURIComponent(session)}`
99
- : "/reset-password";
100
- } else {
101
- await verifyCode({ username, code: fullCode });
102
- // Clean up and redirect to login
103
- localStorage.removeItem(`register_email_${username}`);
104
- localStorage.removeItem(`resend_countdown_${username}`);
105
- window.location.href = "/login";
106
- }
107
- } catch (err) {
108
- const message =
109
- err instanceof Error ? err.message : "Verification failed";
110
- setError(message);
111
- } finally {
112
- setIsVerifying(false);
113
- }
114
- },
115
- [username, verifyCode, verifyCodeReset]
116
- );
117
-
118
- const handleCodeChange = useCallback(
119
- (index: number, value: string) => {
120
- const digit = value.replace(/\D/g, "").slice(-1);
121
- const newCode = [...code];
122
- newCode[index] = digit;
123
- setCode(newCode);
124
- setError(null);
125
-
126
- if (digit && index < 5) {
127
- inputRefs.current[index + 1]?.focus();
128
- }
129
-
130
- if (digit && index === 5) {
131
- const fullCode = newCode.join("");
132
- if (fullCode.length === 6) {
133
- handleSubmitCode(fullCode);
134
- }
135
- }
136
- },
137
- [code, handleSubmitCode]
138
- );
139
-
140
- const handleKeyDown = useCallback(
141
- (index: number, e: React.KeyboardEvent<HTMLInputElement>) => {
142
- if (e.key === "Backspace" && !code[index] && index > 0) {
143
- inputRefs.current[index - 1]?.focus();
144
- }
145
- },
146
- [code]
147
- );
148
-
149
- const handlePaste = useCallback(
150
- (e: React.ClipboardEvent) => {
151
- e.preventDefault();
152
- const pastedData = e.clipboardData.getData("text");
153
- const digits = pastedData.replace(/\D/g, "").slice(0, 6);
154
-
155
- if (digits.length > 0) {
156
- const newCode = [...code];
157
- for (let i = 0; i < 6; i++) {
158
- newCode[i] = digits[i] || "";
159
- }
160
- setCode(newCode);
161
-
162
- const lastIndex = Math.min(digits.length - 1, 5);
163
- inputRefs.current[lastIndex]?.focus();
164
-
165
- if (digits.length === 6) {
166
- handleSubmitCode(digits);
167
- }
168
- }
169
- },
170
- [code, handleSubmitCode]
171
- );
172
-
173
- const handleSubmit = useCallback(
174
- (e: React.FormEvent) => {
175
- e.preventDefault();
176
- const fullCode = code.join("");
177
- if (fullCode.length !== 6) {
178
- setError("Please enter the full 6-digit code");
179
- return;
180
- }
181
- handleSubmitCode(fullCode);
182
- },
183
- [code, handleSubmitCode]
184
- );
185
-
186
- const handleResend = useCallback(async () => {
187
- if (countdown > 0 || !username) return;
188
-
189
- setIsResending(true);
190
- try {
191
- await resendCode({ username });
192
- const expiryTimestamp = Date.now() + 60 * 1000;
193
- localStorage.setItem(
194
- `resend_countdown_${username}`,
195
- expiryTimestamp.toString()
196
- );
197
- setCountdown(60);
198
- } catch (err) {
199
- const message =
200
- err instanceof Error ? err.message : "Failed to resend code";
201
- setError(message);
202
- } finally {
203
- setIsResending(false);
204
- }
205
- }, [countdown, username, resendCode]);
206
-
207
- return {
208
- code,
209
- error,
210
- countdown,
211
- email,
212
- username,
213
- isVerifying,
214
- isResending,
215
- isLoading: isVerifying || isResending,
216
- inputRefs,
217
- handleCodeChange,
218
- handleKeyDown,
219
- handlePaste,
220
- handleSubmit,
221
- handleResend,
222
- setError,
223
- };
224
- }
@@ -1,41 +0,0 @@
1
- /**
2
- * My Simple Theme - Forgot Password Page Configuration
3
- */
4
-
5
- import type { PageConfig } from "@onexapis/core/types";
6
-
7
- export const forgotPasswordPageConfig: Omit<
8
- PageConfig,
9
- "id" | "createdAt" | "updatedAt"
10
- > = {
11
- title: "Forgot Password",
12
- handle: "forgot-password",
13
- path: "/forgot-password",
14
- type: "auth",
15
- renderMode: "sections",
16
- themeId: "my-simple",
17
- editable: true,
18
- published: true,
19
- hideHeader: true,
20
- hideFooter: true,
21
-
22
- seo: {
23
- title: "Forgot Password",
24
- description: "Reset your password",
25
- },
26
-
27
- sections: [
28
- {
29
- id: "auth-forgot-password-1",
30
- type: "my-simple-auth-forgot-password",
31
- template: "default",
32
- order: 0,
33
- enabled: true,
34
- settings: {},
35
- components: [],
36
- blocks: [],
37
- },
38
- ],
39
- };
40
-
41
- export default forgotPasswordPageConfig;
@@ -1,41 +0,0 @@
1
- /**
2
- * My Simple Theme - Login Page Configuration
3
- */
4
-
5
- import type { PageConfig } from "@onexapis/core/types";
6
-
7
- export const loginPageConfig: Omit<
8
- PageConfig,
9
- "id" | "createdAt" | "updatedAt"
10
- > = {
11
- title: "Login",
12
- handle: "login",
13
- path: "/login",
14
- type: "auth",
15
- renderMode: "sections",
16
- themeId: "my-simple",
17
- editable: true,
18
- published: true,
19
- hideHeader: true,
20
- hideFooter: true,
21
-
22
- seo: {
23
- title: "Sign In",
24
- description: "Sign in to your account",
25
- },
26
-
27
- sections: [
28
- {
29
- id: "auth-login-1",
30
- type: "my-simple-auth-login",
31
- template: "default",
32
- order: 0,
33
- enabled: true,
34
- settings: {},
35
- components: [],
36
- blocks: [],
37
- },
38
- ],
39
- };
40
-
41
- export default loginPageConfig;
@@ -1,39 +0,0 @@
1
- /**
2
- * My Simple Theme - Profile Page Configuration
3
- */
4
-
5
- import type { PageConfig } from "@onexapis/core/types";
6
-
7
- export const profilePageConfig: Omit<
8
- PageConfig,
9
- "id" | "createdAt" | "updatedAt"
10
- > = {
11
- title: "Profile",
12
- handle: "profile",
13
- path: "/profile",
14
- type: "account",
15
- renderMode: "sections",
16
- themeId: "my-simple",
17
- editable: true,
18
- published: true,
19
-
20
- seo: {
21
- title: "My Profile",
22
- description: "Manage your account profile",
23
- },
24
-
25
- sections: [
26
- {
27
- id: "profile-1",
28
- type: "my-simple-profile",
29
- template: "default",
30
- order: 0,
31
- enabled: true,
32
- settings: {},
33
- components: [],
34
- blocks: [],
35
- },
36
- ],
37
- };
38
-
39
- export default profilePageConfig;
@@ -1,41 +0,0 @@
1
- /**
2
- * My Simple Theme - Register Page Configuration
3
- */
4
-
5
- import type { PageConfig } from "@onexapis/core/types";
6
-
7
- export const registerPageConfig: Omit<
8
- PageConfig,
9
- "id" | "createdAt" | "updatedAt"
10
- > = {
11
- title: "Register",
12
- handle: "register",
13
- path: "/register",
14
- type: "auth",
15
- renderMode: "sections",
16
- themeId: "my-simple",
17
- editable: true,
18
- published: true,
19
- hideHeader: true,
20
- hideFooter: true,
21
-
22
- seo: {
23
- title: "Create Account",
24
- description: "Create a new account",
25
- },
26
-
27
- sections: [
28
- {
29
- id: "auth-register-1",
30
- type: "my-simple-auth-register",
31
- template: "default",
32
- order: 0,
33
- enabled: true,
34
- settings: {},
35
- components: [],
36
- blocks: [],
37
- },
38
- ],
39
- };
40
-
41
- export default registerPageConfig;
@@ -1,41 +0,0 @@
1
- /**
2
- * My Simple Theme - Verify Code Page Configuration
3
- */
4
-
5
- import type { PageConfig } from "@onexapis/core/types";
6
-
7
- export const verifyCodePageConfig: Omit<
8
- PageConfig,
9
- "id" | "createdAt" | "updatedAt"
10
- > = {
11
- title: "Verify Code",
12
- handle: "verify-code",
13
- path: "/verify-code",
14
- type: "auth",
15
- renderMode: "sections",
16
- themeId: "my-simple",
17
- editable: true,
18
- published: true,
19
- hideHeader: true,
20
- hideFooter: true,
21
-
22
- seo: {
23
- title: "Verify Your Account",
24
- description: "Enter the verification code sent to your email",
25
- },
26
-
27
- sections: [
28
- {
29
- id: "auth-verify-code-1",
30
- type: "my-simple-auth-verify-code",
31
- template: "default",
32
- order: 0,
33
- enabled: true,
34
- settings: {},
35
- components: [],
36
- blocks: [],
37
- },
38
- ],
39
- };
40
-
41
- export default verifyCodePageConfig;
@@ -1,192 +0,0 @@
1
- /**
2
- * Auth Forgot Password - Default Template
3
- * Clean forgot password form with customizable settings
4
- */
5
-
6
- "use client";
7
-
8
- import type { SectionComponentProps } from "@onexapis/core/types";
9
- import coreUtils from "@onexapis/core/utils";
10
- import { useForgotPasswordForm } from "../../hooks/use-forgot-password-form";
11
-
12
- const { getSectionValues } = coreUtils;
13
-
14
- export function AuthForgotPasswordDefault({
15
- section,
16
- schema,
17
- isEditing,
18
- }: SectionComponentProps) {
19
- const { settings } = getSectionValues(section, schema);
20
- const {
21
- heading,
22
- subheading,
23
- usernameLabel,
24
- usernamePlaceholder,
25
- submitButtonText,
26
- loadingText,
27
- backToLoginText,
28
- loginUrl,
29
- registerPromptText,
30
- registerLinkText,
31
- registerUrl,
32
- backgroundColor,
33
- cardBackground,
34
- primaryColor,
35
- textColor,
36
- cardBorderRadius,
37
- } = settings;
38
-
39
- const { username, error, isPending, handleUsernameChange, handleSubmit } =
40
- useForgotPasswordForm();
41
-
42
- const bgColor = String(backgroundColor || "#F9FAFB");
43
- const cardBg = String(cardBackground || "#FFFFFF");
44
- const btnColor = String(primaryColor || "#2563EB");
45
- const headingColor = String(textColor || "#111827");
46
- const radiusClass = `rounded-${String(cardBorderRadius || "2xl")}`;
47
-
48
- return (
49
- <section
50
- className="min-h-screen w-full flex items-center justify-center p-4"
51
- style={{ backgroundColor: bgColor }}
52
- data-section-id={section.id}
53
- data-section-type={section.type}
54
- data-section-template="default"
55
- >
56
- <div
57
- className={`w-full max-w-md shadow-lg p-8 ${radiusClass}`}
58
- style={{ backgroundColor: cardBg }}
59
- >
60
- {/* Header */}
61
- <div className="text-center mb-8">
62
- <h1 className="text-2xl font-bold" style={{ color: headingColor }}>
63
- {String(heading)}
64
- </h1>
65
- {subheading && (
66
- <p className="mt-2 text-sm text-gray-500">{String(subheading)}</p>
67
- )}
68
- </div>
69
-
70
- {/* Error Message */}
71
- {error && (
72
- <div className="mb-4 rounded-lg bg-red-50 border border-red-200 p-3 text-sm text-red-600">
73
- {error}
74
- </div>
75
- )}
76
-
77
- {/* Form */}
78
- <form onSubmit={handleSubmit} className="space-y-5">
79
- {/* Username / Email */}
80
- <div className="flex flex-col gap-1.5">
81
- <label
82
- htmlFor="username"
83
- className="text-sm font-medium text-gray-700"
84
- >
85
- {String(usernameLabel)} <span className="text-red-500">*</span>
86
- </label>
87
- <input
88
- id="username"
89
- name="username"
90
- type="text"
91
- value={username}
92
- onChange={handleUsernameChange}
93
- placeholder={String(usernamePlaceholder)}
94
- disabled={isPending || isEditing}
95
- className="h-11 w-full rounded-lg border border-gray-300 px-4 text-sm text-gray-900 placeholder:text-gray-400 outline-none transition-colors focus:border-blue-500 focus:ring-1 focus:ring-blue-500 disabled:opacity-50"
96
- />
97
- </div>
98
-
99
- {/* Submit Button */}
100
- <button
101
- type="submit"
102
- disabled={isPending || isEditing}
103
- className="h-11 w-full rounded-lg text-sm font-medium text-white transition-colors hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
104
- style={{ backgroundColor: btnColor }}
105
- >
106
- {isPending && (
107
- <svg
108
- className="h-4 w-4 animate-spin"
109
- fill="none"
110
- viewBox="0 0 24 24"
111
- >
112
- <circle
113
- className="opacity-25"
114
- cx="12"
115
- cy="12"
116
- r="10"
117
- stroke="currentColor"
118
- strokeWidth="4"
119
- />
120
- <path
121
- className="opacity-75"
122
- fill="currentColor"
123
- 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"
124
- />
125
- </svg>
126
- )}
127
- {isPending ? String(loadingText) : String(submitButtonText)}
128
- </button>
129
- </form>
130
-
131
- {/* Back to Login */}
132
- <div className="mt-6 text-center">
133
- {isEditing ? (
134
- <span className="inline-flex items-center gap-2 text-sm text-gray-500">
135
- <svg
136
- className="h-4 w-4"
137
- fill="none"
138
- viewBox="0 0 24 24"
139
- stroke="currentColor"
140
- strokeWidth={2}
141
- >
142
- <path d="M10 19l-7-7m0 0l7-7m-7 7h18" />
143
- </svg>
144
- {String(backToLoginText)}
145
- </span>
146
- ) : (
147
- <a
148
- href={String(loginUrl)}
149
- className="inline-flex items-center gap-2 text-sm text-gray-500 hover:text-gray-700 transition-colors"
150
- >
151
- <svg
152
- className="h-4 w-4"
153
- fill="none"
154
- viewBox="0 0 24 24"
155
- stroke="currentColor"
156
- strokeWidth={2}
157
- >
158
- <path d="M10 19l-7-7m0 0l7-7m-7 7h18" />
159
- </svg>
160
- {String(backToLoginText)}
161
- </a>
162
- )}
163
- </div>
164
-
165
- {/* Register Link */}
166
- <div className="mt-4 text-center">
167
- <p className="text-sm text-gray-500">
168
- {String(registerPromptText)}{" "}
169
- {isEditing ? (
170
- <span
171
- className="font-medium hover:opacity-80"
172
- style={{ color: btnColor }}
173
- >
174
- {String(registerLinkText)}
175
- </span>
176
- ) : (
177
- <a
178
- href={String(registerUrl)}
179
- className="font-medium hover:opacity-80 transition-colors"
180
- style={{ color: btnColor }}
181
- >
182
- {String(registerLinkText)}
183
- </a>
184
- )}
185
- </p>
186
- </div>
187
- </div>
188
- </section>
189
- );
190
- }
191
-
192
- export default AuthForgotPasswordDefault;