@pradip1995/segment-login-template 0.5.4 → 0.5.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pradip1995/segment-login-template",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -35,7 +35,7 @@
35
35
  "dependencies": {
36
36
  "@pradip1995/commerce-auth": "^4.0.0",
37
37
  "@pradip1995/commerce-core": "^4.0.0",
38
- "@pradip1995/segment-primitives": "^0.4.0",
38
+ "@pradip1995/segment-primitives": "^0.4.3",
39
39
  "@pradip1995/segment-tokens": "^0.3.7"
40
40
  },
41
41
  "devDependencies": {
@@ -10,6 +10,7 @@ import {
10
10
  import type { OtpVerificationComponent } from "./otp-component"
11
11
  import OtpVerificationModal from "./otp-verification-modal"
12
12
  import { acct } from "./account-theme"
13
+ import { isNextRedirect, safeErrorMessage } from "./is-next-redirect"
13
14
 
14
15
  export default function AccountProfile({
15
16
  customer,
@@ -41,9 +42,10 @@ export default function AccountProfile({
41
42
  })
42
43
  return { ok: true as const, error: null as string | null }
43
44
  } catch (err) {
45
+ if (isNextRedirect(err)) throw err
44
46
  return {
45
47
  ok: false as const,
46
- error: err instanceof Error ? err.message : "Failed to update profile",
48
+ error: safeErrorMessage(err, "Failed to update profile"),
47
49
  }
48
50
  }
49
51
  }
@@ -61,7 +63,8 @@ export default function AccountProfile({
61
63
  setOtp("")
62
64
  setOtpOpen(true)
63
65
  } catch (err) {
64
- setOtpError(err instanceof Error ? err.message : "Failed to send code")
66
+ if (isNextRedirect(err)) throw err
67
+ setOtpError(safeErrorMessage(err, "Failed to send code"))
65
68
  } finally {
66
69
  setOtpPending(false)
67
70
  }
@@ -76,14 +79,15 @@ export default function AccountProfile({
76
79
  otpToken: otpToken || "",
77
80
  code: otp,
78
81
  countryCode,
82
+ skipRedirect: true,
79
83
  })
80
84
  if (!res.success) throw new Error(res.error || "Invalid code")
81
85
  setOtpOpen(false)
82
86
  setMessage("Verification successful.")
83
87
  window.location.reload()
84
88
  } catch (err) {
85
- setOtpError(err instanceof Error ? err.message : "Verification failed")
86
- } finally {
89
+ if (isNextRedirect(err)) throw err
90
+ setOtpError(safeErrorMessage(err, "Verification failed"))
87
91
  setOtpPending(false)
88
92
  }
89
93
  }
@@ -203,6 +203,8 @@ export async function verifyRegistrationOtp(input: {
203
203
  otpToken: string
204
204
  code: string
205
205
  countryCode: string
206
+ /** When true, do not redirect after login (account profile verify flow). */
207
+ skipRedirect?: boolean
206
208
  }) {
207
209
  const response = await fetch(`${getBaseUrl()}/store/customers/otp/verify`, {
208
210
  method: "POST",
@@ -239,7 +241,9 @@ export async function verifyRegistrationOtp(input: {
239
241
  }
240
242
  const customerCacheTag = await getCacheTag("customers")
241
243
  revalidateTag(customerCacheTag)
242
- redirect(`/${input.countryCode || "in"}`)
244
+ if (!input.skipRedirect) {
245
+ redirect(`/${input.countryCode || "in"}`)
246
+ }
243
247
  }
244
248
 
245
249
  return {
@@ -1,5 +1,6 @@
1
1
  "use client"
2
2
 
3
+ import { isNextRedirect, safeErrorMessage } from "./is-next-redirect"
3
4
  import { useState } from "react"
4
5
  import { checkEmailRegistered, requestPasswordReset } from "./auth-server"
5
6
  import { auth } from "./account-theme"
@@ -36,7 +37,8 @@ export default function ForgotPasswordForm({ onBack }: { onBack: () => void }) {
36
37
  setSuccess(true)
37
38
  setMessage(result.message || "If an account exists, you will receive a reset link shortly.")
38
39
  } catch (err) {
39
- setError(err instanceof Error ? err.message : "Something went wrong")
40
+ if (isNextRedirect(err)) throw err
41
+ setError(safeErrorMessage(err, "Something went wrong"))
40
42
  } finally {
41
43
  setPending(false)
42
44
  }
@@ -1,5 +1,6 @@
1
1
  "use client"
2
2
 
3
+ import { isNextRedirect, safeErrorMessage } from "./is-next-redirect"
3
4
  import { useEffect, useRef, useState } from "react"
4
5
  import { sendOTP, verifyOTP } from "./auth-server"
5
6
  import OtpVerificationModal from "./otp-verification-modal"
@@ -61,7 +62,8 @@ export default function GuestOrderModal({
61
62
  setOtp("")
62
63
  setStep("otp")
63
64
  } catch (err) {
64
- setError(err instanceof Error ? err.message : "Failed to send code")
65
+ if (isNextRedirect(err)) throw err
66
+ setError(safeErrorMessage(err, "Failed to send code"))
65
67
  setStep("email")
66
68
  } finally {
67
69
  setPending(false)
@@ -84,7 +86,8 @@ export default function GuestOrderModal({
84
86
  window.location.href = `/${countryCode}/account/guest-orders`
85
87
  }, 900)
86
88
  } catch (err) {
87
- setError(err instanceof Error ? err.message : "Verification failed")
89
+ if (isNextRedirect(err)) throw err
90
+ setError(safeErrorMessage(err, "Verification failed"))
88
91
  setPending(false)
89
92
  }
90
93
  }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Shared Next.js redirect/notFound detection for segment-login-template.
3
+ * Keep in sync with @pradip1995/segment-primitives/is-next-redirect.
4
+ */
5
+
6
+ const CONTROL_FLOW_RE = /NEXT_REDIRECT|NEXT_REDIRECTION|NEXT_NOT_FOUND|NEXT_HTTP_ERROR_FALLBACK/i
7
+
8
+ function textLooksLikeControlFlow(value: string): boolean {
9
+ return CONTROL_FLOW_RE.test(value)
10
+ }
11
+
12
+ export function isNextRedirect(err: unknown): boolean {
13
+ if (err == null) return false
14
+
15
+ if (typeof err === "string") {
16
+ return textLooksLikeControlFlow(err)
17
+ }
18
+
19
+ if (typeof err !== "object") {
20
+ return textLooksLikeControlFlow(String(err))
21
+ }
22
+
23
+ const digest =
24
+ "digest" in err ? String((err as { digest?: unknown }).digest ?? "") : ""
25
+ if (textLooksLikeControlFlow(digest)) {
26
+ return true
27
+ }
28
+
29
+ const message =
30
+ err instanceof Error
31
+ ? err.message
32
+ : "message" in err
33
+ ? String((err as { message?: unknown }).message ?? "")
34
+ : ""
35
+
36
+ if (textLooksLikeControlFlow(message)) {
37
+ return true
38
+ }
39
+
40
+ try {
41
+ return textLooksLikeControlFlow(String(err))
42
+ } catch {
43
+ return false
44
+ }
45
+ }
46
+
47
+ export function safeErrorMessage(err: unknown, fallback: string): string {
48
+ if (isNextRedirect(err)) return fallback
49
+ if (err instanceof Error) {
50
+ const msg = err.message?.trim()
51
+ if (!msg || textLooksLikeControlFlow(msg)) return fallback
52
+ return msg
53
+ }
54
+ if (typeof err === "string") {
55
+ const msg = err.trim()
56
+ if (!msg || textLooksLikeControlFlow(msg)) return fallback
57
+ return msg
58
+ }
59
+ return fallback
60
+ }
@@ -1,5 +1,6 @@
1
1
  "use client"
2
2
 
3
+ import { isNextRedirect, safeErrorMessage } from "./is-next-redirect"
3
4
  import { useActionState, useState } from "react"
4
5
  import { login } from "@pradip1995/commerce-core/client/actions/customer"
5
6
  import { sendAuthOtp, verifyAuthOtpAndLogin } from "./auth-server"
@@ -216,7 +217,8 @@ function OtpLoginForm({
216
217
  setOtp("")
217
218
  setShowOtpModal(true)
218
219
  } catch (err) {
219
- setError(err instanceof Error ? err.message : "Failed to send code")
220
+ if (isNextRedirect(err)) throw err
221
+ setError(safeErrorMessage(err, "Failed to send code"))
220
222
  } finally {
221
223
  setPending(false)
222
224
  }
@@ -240,7 +242,7 @@ function OtpLoginForm({
240
242
  setOtpToken(res.token ?? null)
241
243
  setOtp("")
242
244
  } catch (err) {
243
- setError(err instanceof Error ? err.message : "Failed to resend code")
245
+ setError(safeErrorMessage(err, "Failed to resend code"))
244
246
  } finally {
245
247
  setPending(false)
246
248
  }
@@ -269,7 +271,7 @@ function OtpLoginForm({
269
271
  }
270
272
  } catch (err) {
271
273
  if (isNextRedirect(err)) throw err
272
- setError(err instanceof Error ? err.message : "Verification failed")
274
+ setError(safeErrorMessage(err, "Verification failed"))
273
275
  setPending(false)
274
276
  }
275
277
  }
@@ -437,14 +439,6 @@ function Chip({
437
439
  )
438
440
  }
439
441
 
440
- function isNextRedirect(err: unknown) {
441
- return (
442
- typeof err === "object" &&
443
- err !== null &&
444
- "digest" in err &&
445
- String((err as { digest?: string }).digest || "").includes("NEXT_REDIRECT")
446
- )
447
- }
448
442
 
449
443
  function GuestPackageIcon() {
450
444
  return (
@@ -1,5 +1,6 @@
1
1
  "use client"
2
2
 
3
+ import { isNextRedirect, safeErrorMessage } from "./is-next-redirect"
3
4
  import { useEffect, useState } from "react"
4
5
  import { SplitPhoneInput } from "@pradip1995/commerce-core/components/split-phone-input"
5
6
  import {
@@ -80,8 +81,8 @@ export default function OtpUnifiedForm({
80
81
  setOtp("")
81
82
  setResendIn(RESEND_COOLDOWN_SEC)
82
83
  } catch (err) {
83
- const message = err instanceof Error ? err.message : "Failed to send code"
84
- setError(message)
84
+ if (isNextRedirect(err)) throw err
85
+ setError(safeErrorMessage(err, "Failed to send code"))
85
86
  if (!options?.resend) {
86
87
  setStep("identifier")
87
88
  }
@@ -112,7 +113,7 @@ export default function OtpUnifiedForm({
112
113
  }
113
114
  } catch (err) {
114
115
  if (isNextRedirect(err)) throw err
115
- setError(err instanceof Error ? err.message : "Verification failed")
116
+ setError(safeErrorMessage(err, "Verification failed"))
116
117
  setVerifying(false)
117
118
  }
118
119
  }
@@ -330,11 +331,3 @@ function ModeButton({
330
331
  )
331
332
  }
332
333
 
333
- function isNextRedirect(err: unknown) {
334
- return (
335
- typeof err === "object" &&
336
- err !== null &&
337
- "digest" in err &&
338
- String((err as { digest?: string }).digest || "").includes("NEXT_REDIRECT")
339
- )
340
- }
@@ -1,5 +1,6 @@
1
1
  "use client"
2
2
 
3
+ import { isNextRedirect, safeErrorMessage } from "./is-next-redirect"
3
4
  import { useState } from "react"
4
5
  import {
5
6
  registerCustomer,
@@ -87,7 +88,8 @@ export default function RegisterForm({
87
88
  setStep("otp")
88
89
  setShowOtpModal(true)
89
90
  } catch (err) {
90
- setError(err instanceof Error ? err.message : "Registration failed")
91
+ if (isNextRedirect(err)) throw err
92
+ setError(safeErrorMessage(err, "Registration failed"))
91
93
  } finally {
92
94
  setPending(false)
93
95
  }
@@ -117,7 +119,7 @@ export default function RegisterForm({
117
119
  }, 2000)
118
120
  } catch (err) {
119
121
  if (isNextRedirect(err)) throw err
120
- setError(err instanceof Error ? err.message : "Verification failed")
122
+ setError(safeErrorMessage(err, "Verification failed"))
121
123
  } finally {
122
124
  setPending(false)
123
125
  }
@@ -136,7 +138,8 @@ export default function RegisterForm({
136
138
  setOtpToken(result.token ?? null)
137
139
  setOtp("")
138
140
  } catch (err) {
139
- setError(err instanceof Error ? err.message : "Failed to resend code")
141
+ if (isNextRedirect(err)) throw err
142
+ setError(safeErrorMessage(err, "Failed to resend code"))
140
143
  } finally {
141
144
  setPending(false)
142
145
  }
@@ -296,14 +299,6 @@ export default function RegisterForm({
296
299
  )
297
300
  }
298
301
 
299
- function isNextRedirect(err: unknown) {
300
- return (
301
- typeof err === "object" &&
302
- err !== null &&
303
- "digest" in err &&
304
- String((err as { digest?: string }).digest || "").includes("NEXT_REDIRECT")
305
- )
306
- }
307
302
 
308
303
  function VerificationToggle({
309
304
  active,
@@ -1,5 +1,6 @@
1
1
  "use client"
2
2
 
3
+ import { isNextRedirect, safeErrorMessage } from "./is-next-redirect"
3
4
  import { useState } from "react"
4
5
  import { useSearchParams } from "next/navigation"
5
6
  import { completePasswordResetAction } from "./auth-server"
@@ -49,7 +50,7 @@ export default function ResetPasswordForm({ countryCode }: { countryCode: string
49
50
  }
50
51
  } catch (err) {
51
52
  if (isNextRedirect(err)) throw err
52
- setError(err instanceof Error ? err.message : "Failed to reset password")
53
+ setError(safeErrorMessage(err, "Failed to reset password"))
53
54
  setPending(false)
54
55
  }
55
56
  }
@@ -100,11 +101,3 @@ export default function ResetPasswordForm({ countryCode }: { countryCode: string
100
101
  )
101
102
  }
102
103
 
103
- function isNextRedirect(err: unknown) {
104
- return (
105
- typeof err === "object" &&
106
- err !== null &&
107
- "digest" in err &&
108
- String((err as { digest?: string }).digest || "").includes("NEXT_REDIRECT")
109
- )
110
- }