@lana-commerce/core 13.1.0-alpha.9 → 14.0.0-alpha.2

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/CHANGELOG.md CHANGED
@@ -7,6 +7,9 @@ This project adheres to [Semantic Versioning][semantic versioning].
7
7
  ## [Unreleased]
8
8
 
9
9
  ### Major Changes
10
+
11
+ - OAuth APIs of "customer" module were changed in backwards incompatible way. To delete oauth provider you need to specify its type. This is due to the fact that you can connect multiple providers now.
12
+
10
13
  ### Minor Changes
11
14
 
12
15
  - Add "clear" event to "modules/advancedSearch".
@@ -14,6 +17,9 @@ This project adheres to [Semantic Versioning][semantic versioning].
14
17
  - A bunch of internal APIs were removed. While it's a major change, I put it here, because we know for sure that nobody was using those.
15
18
  - Add "wrapWebSocket" function to "websocket" lib.
16
19
  - Propagate new "meta" field for invoice line item descriptions.
20
+ - Add "webauthn" logic to "customer" module.
21
+ - Add webauthn related fields to customer/shop fragments.
22
+ - "Customer" module: now all signin forms share the custom error type. When custom error happens, it is set on all forms.
17
23
 
18
24
  ### Patch Changes
19
25
 
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = "fragment Customer on StorefrontCustomer{id email name display_name mobile mobile_notifications accepts_marketing reminder_messages addresses{...FullAddress}mobile mobile_notifications default_billing_address_id default_shipping_address_id default_payment_source_id is_guest password_defined oauth_provider}\n";
3
+ exports.default = "fragment Customer on StorefrontCustomer{id email name display_name mobile mobile_notifications accepts_marketing reminder_messages addresses{...FullAddress}mobile mobile_notifications default_billing_address_id default_shipping_address_id default_payment_source_id is_guest password_defined oauth_providers webauthn_keys{id name created_at}}\n";
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = "fragment Shop on StorefrontShop{app_domain created_at currency customer_service_email id name product_review_enabled tax_label timezone primary_domain{domain id}customer_oauth_providers{...CustomerOAuthProvider}tips_enabled tips_variant{id}}\n";
3
+ exports.default = "fragment Shop on StorefrontShop{app_domain created_at currency customer_service_email id name product_review_enabled tax_label timezone primary_domain{domain id}customer_oauth_providers{...CustomerOAuthProvider}tips_enabled tips_variant{id}customer_webauthn}\n";
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = "mutation AddWebauthn($shopID:String!$data:WebauthnAdd!){storefrontCustomersWebauthn(shop_id:$shopID data:$data)}";
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = "mutation DeleteWebauthn($shopID:String!$ids:[String!]!){storefrontCustomersWebauthnDelete(shop_id:$shopID ids:$ids)}";
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = "mutation DisconnectOAuth2($shopID:String!){storefrontCustomersOauthDelete(shop_id:$shopID)}";
3
+ exports.default = "mutation DisconnectOAuth2($shopID:String!$provider:CustomerOAuthProviderKind!){storefrontCustomersOauthDelete(shop_id:$shopID provider:$provider)}";
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = "mutation InitWebauthn($shopID:String!$name:String$email:String){storefrontCustomersInitWebauthn(shop_id:$shopID name:$name email:$email){session_id options}}";
@@ -4,6 +4,8 @@ exports.createCustomer = exports.isSamePageParam = exports.createVariantMap = vo
4
4
  const tslib_1 = require("tslib");
5
5
  const jwt_decode_1 = tslib_1.__importDefault(require("jwt-decode"));
6
6
  const effector_1 = require("effector");
7
+ const browser_1 = require("@simplewebauthn/browser");
8
+ const AddWebauthnMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/AddWebauthnMutation.js"));
7
9
  const ApplyGiftCardMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/ApplyGiftCardMutation.js"));
8
10
  const CancelOrderMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/CancelOrderMutation.js"));
9
11
  const CancelSubscriptionMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/CancelSubscriptionMutation.js"));
@@ -13,6 +15,7 @@ const CreatePaymentSourceMutation_js_1 = tslib_1.__importDefault(require("../gra
13
15
  const CreateReturnMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/CreateReturnMutation.js"));
14
16
  const DeleteFavoriteMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/DeleteFavoriteMutation.js"));
15
17
  const DeletePaymentSourceMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/DeletePaymentSourceMutation.js"));
18
+ const DeleteWebauthnMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/DeleteWebauthnMutation.js"));
16
19
  const DisconnectOAuth2Mutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/DisconnectOAuth2Mutation.js"));
17
20
  const EditSubscriptionMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/EditSubscriptionMutation.js"));
18
21
  const GetCustomerAddressesPageDataQuery_js_1 = tslib_1.__importDefault(require("../graphql/operations/GetCustomerAddressesPageDataQuery.js"));
@@ -30,6 +33,7 @@ const GetReturnQuery_js_1 = tslib_1.__importDefault(require("../graphql/operatio
30
33
  const GetReturnsPageQuery_js_1 = tslib_1.__importDefault(require("../graphql/operations/GetReturnsPageQuery.js"));
31
34
  const GetSubscriptionQuery_js_1 = tslib_1.__importDefault(require("../graphql/operations/GetSubscriptionQuery.js"));
32
35
  const GetSubscriptionsPageQuery_js_1 = tslib_1.__importDefault(require("../graphql/operations/GetSubscriptionsPageQuery.js"));
36
+ const InitWebauthnMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/InitWebauthnMutation.js"));
33
37
  const ModifyCustomerMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/ModifyCustomerMutation.js"));
34
38
  const ModifyFavoriteMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/ModifyFavoriteMutation.js"));
35
39
  const NewPasswordMutation_js_1 = tslib_1.__importDefault(require("../graphql/operations/NewPasswordMutation.js"));
@@ -61,6 +65,32 @@ const multiResponseToResponse_js_1 = require("../multiResponseToResponse.js");
61
65
  const nonNull_js_1 = require("../nonNull.js");
62
66
  const requestResponse_js_1 = require("../effector/requestResponse.js");
63
67
  const split_js_1 = require("../effector/split.js");
68
+ function mapSignInResponseToWrongOAuth(params, result) {
69
+ if (result.kind !== "error")
70
+ return undefined;
71
+ const a = result.error.apiError;
72
+ if (!a || a.code !== codes_js_1.ErrorCode.Unauthorized)
73
+ return undefined;
74
+ const m = a.meta;
75
+ if (!m ||
76
+ m.email === undefined ||
77
+ m.oauth_providers === undefined ||
78
+ m.oauth_session_id === undefined ||
79
+ m.password_defined === undefined ||
80
+ m.webauthn_defined === undefined) {
81
+ return undefined;
82
+ }
83
+ return {
84
+ params,
85
+ meta: {
86
+ email: m.email,
87
+ oauth_providers: m.oauth_providers,
88
+ oauth_session_id: m.oauth_session_id,
89
+ password_defined: m.password_defined,
90
+ webauthn_defined: m.webauthn_defined,
91
+ },
92
+ };
93
+ }
64
94
  function getCustomerInfo(shopID, id, opts) {
65
95
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
66
96
  if (!(opts === null || opts === void 0 ? void 0 : opts.authToken))
@@ -248,6 +278,7 @@ function splitRequestResponseData(source) {
248
278
  // pages you're not allowed to be in, while being logged in
249
279
  const disallowedAuthPages = {
250
280
  signup: true,
281
+ webauthn_signup: true,
251
282
  signin: true,
252
283
  };
253
284
  // it's not allowed to store these pages as lastAuthPage
@@ -255,6 +286,7 @@ const disallowedLastAuthPages = Object.assign(Object.assign({}, disallowedAuthPa
255
286
  // only pages you're allowed to be in, while NOT being logged in
256
287
  const allowedNoAuthPages = {
257
288
  signup: true,
289
+ webauthn_signup: true,
258
290
  signin: true,
259
291
  confirm: true,
260
292
  reset_password: true,
@@ -355,6 +387,70 @@ function createSignupPageGraph(binding) {
355
387
  //===================================================================================================================
356
388
  //===================================================================================================================
357
389
  //===================================================================================================================
390
+ function createWebauthnSignupPageGraph(binding) {
391
+ const init = defineInitBlank(binding);
392
+ const form = (0, form_js_1.createForm)({
393
+ name: (0, form_js_1.createStringField)("name", "", [validator_js_1.validNonEmpty, validator_js_1.validMaxLength250]),
394
+ email: (0, form_js_1.createStringField)("email", "", [validator_js_1.validNonEmpty, validator_js_1.validEmail, validator_js_1.validMaxLength250]),
395
+ accepts_marketing: (0, form_js_1.createBooleanField)("accepts_marketing", false),
396
+ });
397
+ (0, effector_1.forward)({
398
+ from: init.event,
399
+ to: form.reset,
400
+ });
401
+ const signupFx = (0, effector_1.createEffect)((p) => tslib_1.__awaiter(this, void 0, void 0, function* () {
402
+ const { shopID, opts } = p.config;
403
+ const resp = yield (0, request_js_1.request)(InitWebauthnMutation_js_1.default)({
404
+ shopID,
405
+ email: p.data.email,
406
+ name: p.data.name,
407
+ }, opts);
408
+ if (resp.kind !== "data") {
409
+ return resp;
410
+ }
411
+ let sessionID;
412
+ let credential;
413
+ try {
414
+ sessionID = resp.data.session_id;
415
+ credential = yield (0, browser_1.startRegistration)({ optionsJSON: JSON.parse(resp.data.options).publicKey });
416
+ }
417
+ catch (err) {
418
+ console.error(err);
419
+ return { kind: "custom_error", text: "webauthn failure" };
420
+ }
421
+ return (0, request_js_1.request)(SignUpMutation_js_1.default)({
422
+ shopID,
423
+ data: {
424
+ email: p.data.email,
425
+ webauthn_credential: JSON.stringify(credential),
426
+ webauthn_session_id: sessionID,
427
+ accepts_marketing: p.data.accepts_marketing,
428
+ timezone_hint: (0, getTimezone_js_1.getTimezone)(),
429
+ },
430
+ }, opts);
431
+ }));
432
+ (0, effector_1.guard)({
433
+ source: (0, effector_1.sample)(binding.internalConfig, form.submitted, (config, data) => ({ config, data })),
434
+ filter: binding.everythingIdle,
435
+ target: signupFx,
436
+ });
437
+ const { data: signupData, error: signupError } = (0, requestResponse_js_1.requestResponseSplit)(signupFx.doneData);
438
+ // success
439
+ (0, effector_1.forward)({
440
+ from: signupData.filterMap((v) => v[0].token || undefined),
441
+ to: binding.setJWT,
442
+ });
443
+ // failure
444
+ handleFormFailure({ source: signupError, form, unexpectedError: binding.unexpectedError }, { from: "[0]." });
445
+ return {
446
+ init,
447
+ form,
448
+ somethingIsPending: (0, combineSome_js_1.combineSome)(init.pending, signupFx.pending),
449
+ };
450
+ }
451
+ //===================================================================================================================
452
+ //===================================================================================================================
453
+ //===================================================================================================================
358
454
  function createResetPasswordPageGraph(binding) {
359
455
  const init = defineInitBlank(binding);
360
456
  // forms, we use shared fields here
@@ -1656,6 +1752,17 @@ function createSigninPageGraph(binding) {
1656
1752
  const init = defineInitBlank(binding);
1657
1753
  const setSignInMode = (0, effector_1.createEvent)();
1658
1754
  const signInMode = (0, effector_1.restore)(setSignInMode, "email-otp-init");
1755
+ const setWrongOAuth = (0, effector_1.createEvent)();
1756
+ const wrongOAuth = (0, effector_1.restore)(setWrongOAuth, null);
1757
+ const wrongOAuthInfo = (0, effector_1.createStore)(null);
1758
+ wrongOAuthInfo.on(setWrongOAuth, (_, v) => v
1759
+ ? {
1760
+ email: v.meta.email,
1761
+ oauthProviders: v.meta.oauth_providers,
1762
+ passwordDefined: v.meta.password_defined,
1763
+ webauthnDefined: v.meta.webauthn_defined,
1764
+ }
1765
+ : null);
1659
1766
  const form = (0, form_js_1.createFormWithCustomError)({
1660
1767
  email: (0, form_js_1.createStringField)("email", "", [validator_js_1.validNonEmpty, validator_js_1.validEmail, validator_js_1.validMaxLength250]),
1661
1768
  password: (0, form_js_1.createStringField)("password", "", [validator_js_1.validNonEmpty]),
@@ -1666,6 +1773,11 @@ function createSigninPageGraph(binding) {
1666
1773
  const formOTPComplete = (0, form_js_1.createFormWithCustomError)({
1667
1774
  code: (0, form_js_1.createStringField)("code", "", [validator_js_1.validNonEmpty, validator_js_1.validMaxLength250]),
1668
1775
  }, null);
1776
+ const setErrorOnAllForms = (0, effector_1.createEvent)();
1777
+ (0, effector_1.forward)({
1778
+ from: setErrorOnAllForms,
1779
+ to: [form.setError, formOTPInit.setError, formOTPComplete.setError],
1780
+ });
1669
1781
  (0, effector_1.forward)({
1670
1782
  from: init.event,
1671
1783
  to: [form.reset, formOTPInit.reset, formOTPComplete.reset],
@@ -1701,7 +1813,44 @@ function createSigninPageGraph(binding) {
1701
1813
  filter: binding.everythingIdle,
1702
1814
  target: signInViaEmailCompleteFx,
1703
1815
  });
1704
- // email/password form
1816
+ const signInViaWebauthnFx = (0, effector_1.createEffect)((p) => tslib_1.__awaiter(this, void 0, void 0, function* () {
1817
+ const { shopID, opts } = p.config;
1818
+ const resp = yield (0, request_js_1.request)(InitWebauthnMutation_js_1.default)({ shopID }, opts);
1819
+ if (resp.kind !== "data") {
1820
+ return resp;
1821
+ }
1822
+ let sessionID;
1823
+ let credential;
1824
+ try {
1825
+ sessionID = resp.data.session_id;
1826
+ credential = yield (0, browser_1.startAuthentication)({ optionsJSON: JSON.parse(resp.data.options).publicKey });
1827
+ }
1828
+ catch (err) {
1829
+ console.error(err);
1830
+ return { kind: "custom_error", text: "webauthn failure" };
1831
+ }
1832
+ return (0, request_js_1.request)(SignInMutation_js_1.default)({
1833
+ shopID,
1834
+ data: {
1835
+ webauthn_credential: JSON.stringify(credential),
1836
+ webauthn_session_id: sessionID,
1837
+ },
1838
+ }, opts);
1839
+ }));
1840
+ // webauthn
1841
+ {
1842
+ const { data: signinData } = (0, requestResponse_js_1.requestResponseSplit)(signInViaWebauthnFx.doneData);
1843
+ // success
1844
+ (0, effector_1.forward)({
1845
+ from: signinData.filterMap((v) => v.token || undefined),
1846
+ to: binding.setJWT,
1847
+ });
1848
+ // failure
1849
+ (0, split_js_1.splitMap)(signInViaWebauthnFx.done)
1850
+ .map((e) => (e.result.kind !== "system_error" ? "unauthorized_webauthn" : undefined), setErrorOnAllForms)
1851
+ .map((e) => (e.result.kind !== "data" ? e.result : undefined), handleFormFailure({ form, unexpectedError: binding.unexpectedError }));
1852
+ }
1853
+ // email/password form (oauth flow also goes here)
1705
1854
  {
1706
1855
  const { data: signinData } = (0, requestResponse_js_1.requestResponseSplit)(signinFx.doneData);
1707
1856
  // success
@@ -1710,7 +1859,8 @@ function createSigninPageGraph(binding) {
1710
1859
  to: binding.setJWT,
1711
1860
  });
1712
1861
  // failure
1713
- (0, split_js_1.splitMap)(signinFx.done)
1862
+ (0, split_js_1.splitMap)(signinFx.done) // we use "done" here because we need "e.params.data.email" for logic
1863
+ .map((e) => mapSignInResponseToWrongOAuth(e.params, e.result), setWrongOAuth)
1714
1864
  .map((e) => {
1715
1865
  var _a;
1716
1866
  return e.result.kind === "error" && ((_a = e.result.error.apiError) === null || _a === void 0 ? void 0 : _a.code) === codes_js_1.ErrorCode.Unauthorized
@@ -1718,7 +1868,7 @@ function createSigninPageGraph(binding) {
1718
1868
  ? "unauthorized"
1719
1869
  : "unauthorized_oauth"
1720
1870
  : undefined;
1721
- }, form.setError)
1871
+ }, setErrorOnAllForms)
1722
1872
  .map((e) => (e.result.kind !== "data" ? e.result : undefined), handleFormFailure({ form, unexpectedError: binding.unexpectedError }));
1723
1873
  }
1724
1874
  // OTP init form
@@ -1731,7 +1881,7 @@ function createSigninPageGraph(binding) {
1731
1881
  });
1732
1882
  // failure
1733
1883
  (0, split_js_1.splitMap)(error)
1734
- .map((e) => { var _a; return e.kind === "error" && ((_a = e.error.apiError) === null || _a === void 0 ? void 0 : _a.code) === codes_js_1.ErrorCode.TryAgainLater ? "try_again_later" : undefined; }, formOTPInit.setError)
1884
+ .map((e) => { var _a; return e.kind === "error" && ((_a = e.error.apiError) === null || _a === void 0 ? void 0 : _a.code) === codes_js_1.ErrorCode.TryAgainLater ? "try_again_later" : undefined; }, setErrorOnAllForms)
1735
1885
  .fallback(handleFormFailure({ form: formOTPInit, unexpectedError: binding.unexpectedError }));
1736
1886
  }
1737
1887
  // OTP complete form
@@ -1744,7 +1894,7 @@ function createSigninPageGraph(binding) {
1744
1894
  });
1745
1895
  // failure
1746
1896
  (0, split_js_1.splitMap)(error)
1747
- .map((e) => { var _a; return (e.kind === "error" && ((_a = e.error.apiError) === null || _a === void 0 ? void 0 : _a.code) === codes_js_1.ErrorCode.NotFound ? "unauthorized" : undefined); }, formOTPComplete.setError)
1897
+ .map((e) => { var _a; return (e.kind === "error" && ((_a = e.error.apiError) === null || _a === void 0 ? void 0 : _a.code) === codes_js_1.ErrorCode.NotFound ? "unauthorized" : undefined); }, setErrorOnAllForms)
1748
1898
  .fallback(handleFormFailure({ form: formOTPComplete, unexpectedError: binding.unexpectedError }));
1749
1899
  }
1750
1900
  // oauth flow
@@ -1768,6 +1918,28 @@ function createSigninPageGraph(binding) {
1768
1918
  filter: binding.everythingIdle,
1769
1919
  target: signinFx,
1770
1920
  });
1921
+ const webauthnClick = (0, effector_1.createEvent)();
1922
+ (0, effector_1.guard)({
1923
+ source: (0, effector_1.sample)(binding.internalConfig, webauthnClick, (config, data) => ({ config, data })),
1924
+ filter: binding.everythingIdle,
1925
+ target: signInViaWebauthnFx,
1926
+ });
1927
+ const connectWrongOAuth = (0, effector_1.createEvent)();
1928
+ const cancelWrongOAuth = (0, effector_1.createEvent)();
1929
+ (0, effector_1.guard)({
1930
+ source: (0, effector_1.sample)(wrongOAuth, connectWrongOAuth, (w) => w
1931
+ ? {
1932
+ config: w.params.config,
1933
+ data: Object.assign(Object.assign({}, w.params.data), { oauth_session_id: w.meta.oauth_session_id }),
1934
+ }
1935
+ : undefined).filterMap((v) => v),
1936
+ filter: binding.everythingIdle,
1937
+ target: signinFx,
1938
+ });
1939
+ (0, effector_1.forward)({
1940
+ from: cancelWrongOAuth.map(() => null),
1941
+ to: setWrongOAuth,
1942
+ });
1771
1943
  return {
1772
1944
  init,
1773
1945
  form,
@@ -1776,6 +1948,10 @@ function createSigninPageGraph(binding) {
1776
1948
  signInMode,
1777
1949
  setSignInMode,
1778
1950
  oauth2Click,
1951
+ webauthnClick,
1952
+ wrongOAuthInfo,
1953
+ connectWrongOAuth,
1954
+ cancelWrongOAuth,
1779
1955
  somethingIsPending: (0, combineSome_js_1.combineSome)(init.pending, signinFx.pending),
1780
1956
  };
1781
1957
  }
@@ -1825,7 +2001,7 @@ function createOAuth2UtilsGraph(binding) {
1825
2001
  }));
1826
2002
  const disconnectFx = (0, effector_1.createEffect)((p) => tslib_1.__awaiter(this, void 0, void 0, function* () {
1827
2003
  const { shopID, opts } = p.config;
1828
- return (0, request_js_1.request)(DisconnectOAuth2Mutation_js_1.default)({ shopID }, opts);
2004
+ return (0, request_js_1.request)(DisconnectOAuth2Mutation_js_1.default)({ shopID, provider: p.data }, opts);
1829
2005
  }));
1830
2006
  // connect flow
1831
2007
  {
@@ -1888,6 +2064,92 @@ function createOAuth2UtilsGraph(binding) {
1888
2064
  somethingIsPending: (0, combineSome_js_1.combineSome)(connectFx.pending, disconnectFx.pending),
1889
2065
  };
1890
2066
  }
2067
+ //--------------------------------------------------------------------------------------------------------------------
2068
+ //--------------------------------------------------------------------------------------------------------------------
2069
+ //--------------------------------------------------------------------------------------------------------------------
2070
+ // not really a part of any page, but somewhat follows page graph conventions, except it doesn't have init.
2071
+ function createWebauthnUtilsGraph(binding) {
2072
+ const createWebauthn = (0, effector_1.createEvent)();
2073
+ const deleteWebauthn = (0, effector_1.createEvent)();
2074
+ const createFx = (0, effector_1.createEffect)((p) => tslib_1.__awaiter(this, void 0, void 0, function* () {
2075
+ const { shopID, opts } = p.config;
2076
+ if (!p.data) {
2077
+ return { kind: "custom_error", text: "no customer info" };
2078
+ }
2079
+ const email = p.data.customer.email;
2080
+ const name = p.data.customer.name;
2081
+ const resp = yield (0, request_js_1.request)(InitWebauthnMutation_js_1.default)({ shopID, email, name }, opts);
2082
+ if (resp.kind !== "data") {
2083
+ return resp;
2084
+ }
2085
+ let sessionID;
2086
+ let credential;
2087
+ try {
2088
+ sessionID = resp.data.session_id;
2089
+ credential = yield (0, browser_1.startRegistration)({ optionsJSON: JSON.parse(resp.data.options).publicKey });
2090
+ }
2091
+ catch (err) {
2092
+ console.error(err);
2093
+ return { kind: "custom_error", text: "webauthn failure" };
2094
+ }
2095
+ return (0, request_js_1.request)(AddWebauthnMutation_js_1.default)({ shopID, data: { webauthn_credential: JSON.stringify(credential), webauthn_session_id: sessionID } }, opts);
2096
+ }));
2097
+ const deleteFx = (0, effector_1.createEffect)((p) => tslib_1.__awaiter(this, void 0, void 0, function* () {
2098
+ const { shopID, opts } = p.config;
2099
+ return (0, request_js_1.request)(DeleteWebauthnMutation_js_1.default)({ shopID, ids: p.data }, opts);
2100
+ }));
2101
+ // create flow
2102
+ {
2103
+ (0, effector_1.guard)({
2104
+ source: (0, effector_1.sample)((0, effector_1.combine)({ config: binding.internalConfig, customerInfo: binding.customerInfo }), createWebauthn, ({ config, customerInfo }, _data) => ({ config, data: customerInfo })),
2105
+ filter: binding.everythingIdle,
2106
+ target: createFx,
2107
+ });
2108
+ const { data: connectData, error: connectError } = (0, requestResponse_js_1.requestResponseSplit)(createFx.doneData);
2109
+ // success
2110
+ (0, effector_1.forward)({
2111
+ from: connectData,
2112
+ to: binding.fetchCustomerInfoNow,
2113
+ });
2114
+ (0, effector_1.forward)({
2115
+ from: connectData.map(() => "webauthn_created"),
2116
+ to: binding.message,
2117
+ });
2118
+ // failure
2119
+ (0, effector_1.forward)({
2120
+ from: connectError,
2121
+ to: binding.unexpectedError,
2122
+ });
2123
+ }
2124
+ // delete flow
2125
+ {
2126
+ (0, effector_1.guard)({
2127
+ source: (0, effector_1.sample)(binding.internalConfig, deleteWebauthn, (config, data) => ({ config, data })),
2128
+ filter: binding.everythingIdle,
2129
+ target: deleteFx,
2130
+ });
2131
+ const { data: disconnectData, error: disconnectError } = (0, requestResponse_js_1.requestResponseSplit)(deleteFx.doneData);
2132
+ // success
2133
+ (0, effector_1.forward)({
2134
+ from: disconnectData,
2135
+ to: binding.fetchCustomerInfoNow,
2136
+ });
2137
+ (0, effector_1.forward)({
2138
+ from: disconnectData.map(() => "webauthn_deleted"),
2139
+ to: binding.message,
2140
+ });
2141
+ // failure
2142
+ (0, effector_1.forward)({
2143
+ from: disconnectError,
2144
+ to: binding.unexpectedError,
2145
+ });
2146
+ }
2147
+ return {
2148
+ createWebauthn,
2149
+ deleteWebauthn,
2150
+ somethingIsPending: (0, combineSome_js_1.combineSome)(createFx.pending, deleteFx.pending),
2151
+ };
2152
+ }
1891
2153
  function createCustomer(config, init) {
1892
2154
  var _a;
1893
2155
  const currency = config.currency || (0, effector_1.createStore)(config.shopCurrency);
@@ -1957,6 +2219,7 @@ function createCustomer(config, init) {
1957
2219
  message,
1958
2220
  fetchCustomerInfoNow,
1959
2221
  oauth2,
2222
+ customerInfo,
1960
2223
  };
1961
2224
  config.jwt.on(setJWT, (_, v) => v);
1962
2225
  customerInfo.on(setFavorites, (pv, favorites) => {
@@ -1994,6 +2257,7 @@ function createCustomer(config, init) {
1994
2257
  const pages = {
1995
2258
  signin: createSigninPageGraph(binding),
1996
2259
  signup: createSignupPageGraph(binding),
2260
+ webauthnSignup: createWebauthnSignupPageGraph(binding),
1997
2261
  resetPassword: createResetPasswordPageGraph(binding),
1998
2262
  addresses: createAddressesPageGraph(binding),
1999
2263
  favorites: createFavoritesPageGraph(binding),
@@ -2009,6 +2273,7 @@ function createCustomer(config, init) {
2009
2273
  paymentMethods: createPaymentMethodsPageGraph(binding),
2010
2274
  };
2011
2275
  const oauth2Utils = createOAuth2UtilsGraph(binding);
2276
+ const webauthnUtils = createWebauthnUtilsGraph(binding);
2012
2277
  const currentPage = (0, effector_1.createStore)(null);
2013
2278
  const loadPage = (0, effector_1.createEvent)();
2014
2279
  const loadPageExt = (0, effector_1.sample)(currentPage, loadPage, (p, param) => ({
@@ -2017,6 +2282,7 @@ function createCustomer(config, init) {
2017
2282
  }));
2018
2283
  const loadSignin = loadPageExt.filterMap((v) => (v.param.kind === "signin" ? Object.assign(Object.assign({}, v), { param: v.param }) : undefined));
2019
2284
  const loadSignup = loadPageExt.filterMap((v) => (v.param.kind === "signup" ? Object.assign(Object.assign({}, v), { param: v.param }) : undefined));
2285
+ const loadWebauthnSignup = loadPageExt.filterMap((v) => v.param.kind === "webauthn_signup" ? Object.assign(Object.assign({}, v), { param: v.param }) : undefined);
2020
2286
  const loadResetPassword = loadPageExt.filterMap((v) => v.param.kind === "reset_password" ? Object.assign(Object.assign({}, v), { param: v.param }) : undefined);
2021
2287
  const loadAddresses = loadPageExt.filterMap((v) => v.param.kind === "addresses" ? Object.assign(Object.assign({}, v), { param: v.param }) : undefined);
2022
2288
  const loadFavorites = loadPageExt.filterMap((v) => v.param.kind === "favorites" ? Object.assign(Object.assign({}, v), { param: v.param }) : undefined);
@@ -2032,6 +2298,7 @@ function createCustomer(config, init) {
2032
2298
  const loadPaymentMethods = loadPageExt.filterMap((v) => v.param.kind === "payment_methods" ? Object.assign(Object.assign({}, v), { param: v.param }) : undefined);
2033
2299
  (0, effector_1.forward)({ from: loadSignin, to: pages.signin.init.load });
2034
2300
  (0, effector_1.forward)({ from: loadSignup, to: pages.signup.init.load });
2301
+ (0, effector_1.forward)({ from: loadWebauthnSignup, to: pages.webauthnSignup.init.load });
2035
2302
  (0, effector_1.forward)({ from: loadResetPassword, to: pages.resetPassword.init.load });
2036
2303
  (0, effector_1.forward)({ from: loadAddresses, to: pages.addresses.init.load });
2037
2304
  (0, effector_1.forward)({ from: loadFavorites, to: pages.favorites.init.load });
@@ -2053,6 +2320,7 @@ function createCustomer(config, init) {
2053
2320
  from: [
2054
2321
  pages.signin.init.loaded,
2055
2322
  pages.signup.init.loaded,
2323
+ pages.webauthnSignup.init.loaded,
2056
2324
  pages.resetPassword.init.loaded,
2057
2325
  pages.addresses.init.loaded,
2058
2326
  pages.favorites.init.loaded,
@@ -2069,7 +2337,7 @@ function createCustomer(config, init) {
2069
2337
  ],
2070
2338
  to: currentPage,
2071
2339
  });
2072
- const somethingPending = (0, combineSome_js_1.combineSome)(pages.signin.somethingIsPending, pages.signup.somethingIsPending, pages.resetPassword.somethingIsPending, pages.addresses.somethingIsPending, pages.favorites.somethingIsPending, pages.orders.somethingIsPending, pages.subscriptions.somethingIsPending, pages.returns.somethingIsPending, pages.order.somethingIsPending, pages.subscription.somethingIsPending, pages.return.somethingIsPending, pages.createReturn.somethingIsPending, pages.storeCredit.somethingIsPending, pages.profile.somethingIsPending, pages.paymentMethods.somethingIsPending, oauth2Utils.somethingIsPending);
2340
+ const somethingPending = (0, combineSome_js_1.combineSome)(pages.signin.somethingIsPending, pages.signup.somethingIsPending, pages.webauthnSignup.somethingIsPending, pages.resetPassword.somethingIsPending, pages.addresses.somethingIsPending, pages.favorites.somethingIsPending, pages.orders.somethingIsPending, pages.subscriptions.somethingIsPending, pages.returns.somethingIsPending, pages.order.somethingIsPending, pages.subscription.somethingIsPending, pages.return.somethingIsPending, pages.createReturn.somethingIsPending, pages.storeCredit.somethingIsPending, pages.profile.somethingIsPending, pages.paymentMethods.somethingIsPending, oauth2Utils.somethingIsPending, webauthnUtils.somethingIsPending);
2073
2341
  (0, effector_1.forward)({
2074
2342
  from: somethingPending.map((v) => !v),
2075
2343
  to: everythingIdle,
@@ -2150,7 +2418,11 @@ function createCustomer(config, init) {
2150
2418
  to: internalGoTo,
2151
2419
  });
2152
2420
  // customerMenuVisible helper
2153
- const customerLoggedIn = jwtAndCurrentPage.map(([jwt, currentPage]) => jwt !== "" && currentPage && currentPage.kind !== "signin" && currentPage.kind !== "signup");
2421
+ const customerLoggedIn = jwtAndCurrentPage.map(([jwt, currentPage]) => jwt !== "" &&
2422
+ currentPage &&
2423
+ currentPage.kind !== "signin" &&
2424
+ currentPage.kind !== "signup" &&
2425
+ currentPage.kind !== "webauthn_signup");
2154
2426
  return {
2155
2427
  message,
2156
2428
  logout,
@@ -2169,6 +2441,10 @@ function createCustomer(config, init) {
2169
2441
  connect: oauth2Utils.connectOAuth2,
2170
2442
  disconnect: oauth2Utils.disconnectOAuth2,
2171
2443
  },
2444
+ webauthn: {
2445
+ create: webauthnUtils.createWebauthn,
2446
+ delete: webauthnUtils.deleteWebauthn,
2447
+ },
2172
2448
  };
2173
2449
  }
2174
2450
  exports.createCustomer = createCustomer;
package/cjs/script.js CHANGED
@@ -45,6 +45,7 @@ function embedUI(config) {
45
45
  shopCurrencies: (0, arrayToDict_js_1.arrayToDict)(config.currencies, (c) => c.currency.code),
46
46
  tipsVariantID: config.shop.tips_enabled ? (_b = config.shop.tips_variant) === null || _b === void 0 ? void 0 : _b.id : undefined,
47
47
  oauth2Providers: config.shop.customer_oauth_providers,
48
+ customerWebauthn: config.shop.customer_webauthn,
48
49
  stripe: stripeGateway
49
50
  ? {
50
51
  accountID: stripeGateway.account_id,
@@ -1 +1 @@
1
- export default "fragment Customer on StorefrontCustomer{id email name display_name mobile mobile_notifications accepts_marketing reminder_messages addresses{...FullAddress}mobile mobile_notifications default_billing_address_id default_shipping_address_id default_payment_source_id is_guest password_defined oauth_provider}\n";
1
+ export default "fragment Customer on StorefrontCustomer{id email name display_name mobile mobile_notifications accepts_marketing reminder_messages addresses{...FullAddress}mobile mobile_notifications default_billing_address_id default_shipping_address_id default_payment_source_id is_guest password_defined oauth_providers webauthn_keys{id name created_at}}\n";
@@ -1 +1 @@
1
- export default "fragment Shop on StorefrontShop{app_domain created_at currency customer_service_email id name product_review_enabled tax_label timezone primary_domain{domain id}customer_oauth_providers{...CustomerOAuthProvider}tips_enabled tips_variant{id}}\n";
1
+ export default "fragment Shop on StorefrontShop{app_domain created_at currency customer_service_email id name product_review_enabled tax_label timezone primary_domain{domain id}customer_oauth_providers{...CustomerOAuthProvider}tips_enabled tips_variant{id}customer_webauthn}\n";
@@ -0,0 +1 @@
1
+ export default "mutation AddWebauthn($shopID:String!$data:WebauthnAdd!){storefrontCustomersWebauthn(shop_id:$shopID data:$data)}";
@@ -0,0 +1 @@
1
+ export default "mutation DeleteWebauthn($shopID:String!$ids:[String!]!){storefrontCustomersWebauthnDelete(shop_id:$shopID ids:$ids)}";
@@ -1 +1 @@
1
- export default "mutation DisconnectOAuth2($shopID:String!){storefrontCustomersOauthDelete(shop_id:$shopID)}";
1
+ export default "mutation DisconnectOAuth2($shopID:String!$provider:CustomerOAuthProviderKind!){storefrontCustomersOauthDelete(shop_id:$shopID provider:$provider)}";
@@ -0,0 +1 @@
1
+ export default "mutation InitWebauthn($shopID:String!$name:String$email:String){storefrontCustomersInitWebauthn(shop_id:$shopID name:$name email:$email){session_id options}}";