@asteby/storefront 0.21.1 → 0.22.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/dist/mock.cjs CHANGED
@@ -1919,6 +1919,7 @@ function createMockStorefront(options = {}) {
1919
1919
  notifications: { channels: ["email"] },
1920
1920
  data_export: true,
1921
1921
  account_delete: true,
1922
+ email_change: true,
1922
1923
  ...(options.subjectKinds?.length ?? 0) > 0 ? { subjects: { kinds: options.subjectKinds.map((k) => k.key), share_with_workshop: false } } : {},
1923
1924
  ...options.customerCapabilities
1924
1925
  };
@@ -2324,7 +2325,9 @@ function createMockStorefront(options = {}) {
2324
2325
  first_name: extra.first_name ?? null,
2325
2326
  last_name: extra.last_name ?? null,
2326
2327
  default_address_id: null,
2327
- created_at: now()
2328
+ created_at: now(),
2329
+ // Registered with no mail connector: the e-mail is only a login name until a code proves it.
2330
+ email_verified: capabilities.email_verification
2328
2331
  };
2329
2332
  state.customers.push(customer);
2330
2333
  }
@@ -2760,7 +2763,8 @@ function createMockStorefront(options = {}) {
2760
2763
  first_name: null,
2761
2764
  last_name: null,
2762
2765
  default_address_id: null,
2763
- created_at: now()
2766
+ created_at: now(),
2767
+ email_verified: kind === "email"
2764
2768
  };
2765
2769
  state.customers.push(customer);
2766
2770
  }
@@ -2963,6 +2967,48 @@ function createMockStorefront(options = {}) {
2963
2967
  info.reauth_at = Date.now();
2964
2968
  return { body: { reauth_at: new Date(info.reauth_at).toISOString(), valid_for_seconds: REAUTH_WINDOW_MS / 1e3 }, cache: "private" };
2965
2969
  });
2970
+ const emailCodeKey = (kind, customerId, email) => `${kind}_email:${customerId}:${email}`;
2971
+ route("POST", "/customer/email/verification", "customer:write", ({ headers }) => {
2972
+ const { c } = sessionOf(headers);
2973
+ if (!c.email) throw new HttpError(422, "invalid_state", "The account has no email", "email");
2974
+ if (c.email_verified !== false) throw new HttpError(422, "invalid_state", "The email is already verified", "email");
2975
+ state.otps.set(emailCodeKey("verify", c.id, c.email), otpCode);
2976
+ return { status: 204 };
2977
+ });
2978
+ route("POST", "/customer/email/verification/confirm", "customer:write", ({ headers, body }) => {
2979
+ const { c } = sessionOf(headers);
2980
+ if (!c.email) throw new HttpError(422, "invalid_state", "The account has no email", "email");
2981
+ if (c.email_verified !== false) throw new HttpError(422, "invalid_state", "The email is already verified", "email");
2982
+ const key = emailCodeKey("verify", c.id, c.email);
2983
+ if (typeof body.code !== "string" || state.otps.get(key) !== body.code) throw new HttpError(400, "validation", "The code is invalid or expired; request a new one", "code");
2984
+ state.otps.delete(key);
2985
+ c.email_verified = true;
2986
+ return { body: c, cache: "private" };
2987
+ });
2988
+ route("POST", "/customer/email/change", "customer:write", ({ headers, body }) => {
2989
+ const { c, info } = sessionOf(headers);
2990
+ requireRecentReauth(info);
2991
+ const email = emailOf(body);
2992
+ if (email === c.email) throw new HttpError(400, "validation", "This is already the email of the account", "email");
2993
+ const taken = state.customers.some((x) => x.email === email) || state.passwords.has(email);
2994
+ if (!taken) state.otps.set(emailCodeKey("change", c.id, email), otpCode);
2995
+ return { status: 202, body: { status: "verification_required" }, cache: "private" };
2996
+ });
2997
+ route("POST", "/customer/email/change/confirm", "customer:write", ({ headers, body }) => {
2998
+ const { c, token } = sessionOf(headers);
2999
+ const email = emailOf(body);
3000
+ const key = emailCodeKey("change", c.id, email);
3001
+ if (typeof body.code !== "string" || state.otps.get(key) !== body.code) throw new HttpError(400, "validation", "The code is invalid or expired; request a new one", "code");
3002
+ state.otps.delete(key);
3003
+ if (c.email && state.passwords.has(c.email)) {
3004
+ state.passwords.set(email, state.passwords.get(c.email));
3005
+ state.passwords.delete(c.email);
3006
+ }
3007
+ c.email = email;
3008
+ c.email_verified = true;
3009
+ for (const [t, id] of [...state.sessions.entries()]) if (id === c.id && t !== token) state.sessions.delete(t);
3010
+ return { body: c, cache: "private" };
3011
+ });
2966
3012
  route("POST", "/customer/data-export", "customer:write", ({ headers }) => {
2967
3013
  const { c, info } = sessionOf(headers);
2968
3014
  requireRecentReauth(info);