@thorprovider/medusa-extended 1.11.7 → 1.11.8

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/index.mjs CHANGED
@@ -1873,8 +1873,179 @@ function mapUiMessageStreamToEvents(stream, logger) {
1873
1873
  }
1874
1874
  });
1875
1875
  }
1876
+
1877
+ // src/recovery.ts
1878
+ import { createLogger as createLogger3, ProviderAPIError as ProviderAPIError4 } from "@thorprovider/adapters";
1879
+ var RecoveryClient = class {
1880
+ baseUrl;
1881
+ logger;
1882
+ constructor(config) {
1883
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
1884
+ this.logger = createLogger3("RecoveryClient", config.debug);
1885
+ }
1886
+ // -------------------------------------------------------------------------
1887
+ // Private — HTTP helper
1888
+ // -------------------------------------------------------------------------
1889
+ async request(method, path, body) {
1890
+ const url = `${this.baseUrl}${path}`;
1891
+ this.logger.debug(`[recovery] ${method} ${path}`);
1892
+ const headers = {
1893
+ "Content-Type": "application/json"
1894
+ };
1895
+ const init = {
1896
+ method,
1897
+ headers,
1898
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
1899
+ };
1900
+ let response;
1901
+ try {
1902
+ response = await fetchBackendWithResilience(url, init);
1903
+ } catch (networkError) {
1904
+ throw new ProviderAPIError4(
1905
+ `[recovery] Network error on ${method} ${path}: ${networkError.message}`,
1906
+ "NETWORK_ERROR",
1907
+ networkError
1908
+ );
1909
+ }
1910
+ if (!response.ok) {
1911
+ let message = `HTTP ${response.status}`;
1912
+ try {
1913
+ const json = await response.json();
1914
+ message = json?.message ?? message;
1915
+ } catch {
1916
+ }
1917
+ throw new ProviderAPIError4(
1918
+ `[recovery] ${method} ${path} failed: ${message}`,
1919
+ `RECOVERY_API_${response.status}`,
1920
+ response.status
1921
+ );
1922
+ }
1923
+ return response.json();
1924
+ }
1925
+ // -------------------------------------------------------------------------
1926
+ // Private — reset token helpers
1927
+ // -------------------------------------------------------------------------
1928
+ /**
1929
+ * Decodes the `entity_id` (email) claim from a Medusa reset-password JWT.
1930
+ *
1931
+ * The JWT is unsigned-trust for this claim: the email is later sent to
1932
+ * `POST /auth/user/emailpass/update`, where Medusa itself re-validates the
1933
+ * token signature and payload before applying the change.
1934
+ */
1935
+ decodeResetTokenEmail(token) {
1936
+ const parts = token.split(".");
1937
+ if (parts.length !== 3) return null;
1938
+ try {
1939
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
1940
+ return typeof payload.entity_id === "string" && payload.entity_id.length > 0 ? payload.entity_id : null;
1941
+ } catch {
1942
+ return null;
1943
+ }
1944
+ }
1945
+ // -------------------------------------------------------------------------
1946
+ // Password reset
1947
+ // -------------------------------------------------------------------------
1948
+ /**
1949
+ * Solicita un email de reset de contraseña para el actor `user`
1950
+ * (dropshippers). El backend responde de forma uniforme exista o no la
1951
+ * cuenta (anti enumeración).
1952
+ *
1953
+ * `POST /auth/user/emailpass/reset-password`
1954
+ */
1955
+ async requestUserPasswordReset(email) {
1956
+ await this.request("POST", "/auth/user/emailpass/reset-password", {
1957
+ identifier: email
1958
+ });
1959
+ }
1960
+ /**
1961
+ * Verifica un token de reset de contraseña sin consumirlo. Devuelve el
1962
+ * email enmascarado (p. ej. `j***@ejemplo.com`) solo cuando `status === 'valid'`.
1963
+ *
1964
+ * `GET /store/dropshipper/auth/reset-password/verify`
1965
+ */
1966
+ async verifyUserPasswordResetToken(token) {
1967
+ return this.request("GET", `/store/dropshipper/auth/reset-password/verify?token=${encodeURIComponent(token)}`);
1968
+ }
1969
+ /**
1970
+ * Confirma el reset: re-verifica el token (sin consumir), luego consume el
1971
+ * token vía `POST /auth/user/emailpass/update`. El email se deriva del
1972
+ * propio JWT. Nunca devuelve auto-login: al éxito, la UI redirige a /login.
1973
+ */
1974
+ async confirmUserPasswordReset(token, password) {
1975
+ const verify = await this.verifyUserPasswordResetToken(token);
1976
+ if (verify.status !== "valid") {
1977
+ return { ok: false, status: verify.status };
1978
+ }
1979
+ const email = this.decodeResetTokenEmail(token);
1980
+ if (!email) {
1981
+ return { ok: false, status: "invalid" };
1982
+ }
1983
+ try {
1984
+ const headers = {
1985
+ Authorization: `Bearer ${token}`,
1986
+ "Content-Type": "application/json"
1987
+ };
1988
+ const response = await fetchBackendWithResilience(`${this.baseUrl}/auth/user/emailpass/update`, {
1989
+ method: "POST",
1990
+ headers,
1991
+ body: JSON.stringify({ email, password })
1992
+ });
1993
+ if (!response.ok) {
1994
+ throw new ProviderAPIError4(
1995
+ `[recovery] POST /auth/user/emailpass/update failed: HTTP ${response.status}`,
1996
+ "RECOVERY_API_" + response.status,
1997
+ response.status
1998
+ );
1999
+ }
2000
+ return { ok: true };
2001
+ } catch (error) {
2002
+ this.logger.warn("[recovery] confirmUserPasswordReset failed, re-verifying", error);
2003
+ try {
2004
+ const recheck = await this.verifyUserPasswordResetToken(token);
2005
+ return { ok: false, status: recheck.status };
2006
+ } catch {
2007
+ return { ok: false, status: "invalid" };
2008
+ }
2009
+ }
2010
+ }
2011
+ // -------------------------------------------------------------------------
2012
+ // Account activation
2013
+ // -------------------------------------------------------------------------
2014
+ /**
2015
+ * Verifica un token de activación de cuenta dropshipper sin consumirlo.
2016
+ *
2017
+ * `GET /store/dropshipper/applications/activate/verify`
2018
+ */
2019
+ async verifyActivationToken(token) {
2020
+ return this.request("GET", `/store/dropshipper/applications/activate/verify?token=${encodeURIComponent(token)}`);
2021
+ }
2022
+ /**
2023
+ * Activa la cuenta: re-verifica el token (sin consumir), luego consume el
2024
+ * token vía `POST /store/dropshipper/applications/activate` y establece la
2025
+ * contraseña inicial. Al éxito, la UI redirige a /login sin auto-login.
2026
+ */
2027
+ async activateAccount(token, password) {
2028
+ const verify = await this.verifyActivationToken(token);
2029
+ if (verify.status !== "valid") {
2030
+ return { ok: false, status: verify.status };
2031
+ }
2032
+ try {
2033
+ await this.request("POST", "/store/dropshipper/applications/activate", { token, password });
2034
+ return { ok: true };
2035
+ } catch (error) {
2036
+ this.logger.warn("[recovery] activateAccount failed, re-verifying", error);
2037
+ try {
2038
+ const recheck = await this.verifyActivationToken(token);
2039
+ return { ok: false, status: recheck.status };
2040
+ } catch {
2041
+ return { ok: false, status: "invalid" };
2042
+ }
2043
+ }
2044
+ }
2045
+ };
1876
2046
  export {
1877
2047
  DropshipperClient,
1878
- MedusaAdminClient
2048
+ MedusaAdminClient,
2049
+ RecoveryClient
1879
2050
  };
1880
2051
  //# sourceMappingURL=index.mjs.map