@fytkit/sdk 3.4.0 → 4.0.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/index.js CHANGED
@@ -1,6 +1,30 @@
1
- import { createORPCClient, ORPCError } from '@orpc/client';
1
+ import { ORPCError, isORPCErrorJson, createORPCErrorFromJson, createORPCClient } from '@orpc/client';
2
2
  import { RPCLink } from '@orpc/client/fetch';
3
3
 
4
+ // src/error.ts
5
+
6
+ // src/is-record.ts
7
+ function isRecord(value) {
8
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9
+ }
10
+
11
+ // src/refusal.ts
12
+ function refusalData(error, reason) {
13
+ if (!isRecord(error) || typeof error.kind !== "string") return null;
14
+ const refusal = error.refusal;
15
+ if (!isRecord(refusal) || refusal.reason !== reason || !isRecord(refusal.data)) return null;
16
+ return refusal.data;
17
+ }
18
+ var MEMBER_CAP_QUOTA = "max_clients";
19
+ function pickRefusal(data) {
20
+ if (!isRecord(data)) return {};
21
+ const { reason, ...rest } = data;
22
+ if (typeof reason === "string" && reason.length > 0) return { refusal: { reason, data: rest } };
23
+ if (data.quotaCode === MEMBER_CAP_QUOTA)
24
+ return { refusal: { reason: MEMBER_CAP_QUOTA, data: {} } };
25
+ return {};
26
+ }
27
+
4
28
  // src/error.ts
5
29
  function pickIssues(data) {
6
30
  if (!data || typeof data !== "object") return null;
@@ -31,7 +55,8 @@ function normalizeError(err) {
31
55
  return {
32
56
  kind: "forbidden",
33
57
  reason: message || "Forbidden",
34
- ...pickStringField(data, "code")
58
+ ...pickStringField(data, "code"),
59
+ ...pickRefusal(data)
35
60
  };
36
61
  case "PAYMENT_REQUIRED":
37
62
  return { kind: "payment_required", message: message || "Payment Required" };
@@ -39,25 +64,60 @@ function normalizeError(err) {
39
64
  return {
40
65
  kind: "conflict",
41
66
  message: message || "Conflict",
42
- ...pickStringField(data, "enrollmentId")
67
+ ...pickStringField(data, "enrollmentId"),
68
+ ...pickRefusal(data)
43
69
  };
44
70
  case "NOT_FOUND":
45
- return { kind: "not_found" };
71
+ return { kind: "not_found", ...pickRefusal(data) };
46
72
  case "TOO_MANY_REQUESTS":
47
- return { kind: "rate_limited", retryAfter: pickRetryAfter(data) };
73
+ return { kind: "rate_limited", retryAfter: pickRetryAfter(data), ...pickRefusal(data) };
48
74
  case "BAD_REQUEST":
49
75
  case "UNPROCESSABLE_CONTENT": {
50
76
  const issues = pickIssues(data);
51
- if (issues) return { kind: "validation", issues };
52
- return { kind: "server", status, message, ...pickStringField(data, "code") };
77
+ if (issues) return { kind: "validation", issues, ...pickRefusal(data) };
78
+ return {
79
+ kind: "server",
80
+ status,
81
+ message,
82
+ ...pickStringField(data, "code"),
83
+ ...pickRefusal(data)
84
+ };
53
85
  }
54
86
  default:
55
- return { kind: "server", status, message, ...pickStringField(data, "code") };
87
+ return {
88
+ kind: "server",
89
+ status,
90
+ message,
91
+ ...pickStringField(data, "code"),
92
+ ...pickRefusal(data)
93
+ };
56
94
  }
57
95
  }
58
96
  return { kind: "server", status: 0 };
59
97
  }
60
98
 
99
+ // src/app.ts
100
+ var UNEXPECTED_NOT_MODIFIED = { kind: "server", status: 304 };
101
+ function createAppNamespace(transport) {
102
+ const bootstrap = async (options = {}) => {
103
+ const etag = options.etag ?? null;
104
+ let output;
105
+ try {
106
+ output = await transport.client.app.bootstrap(void 0, {
107
+ context: etag === null ? {} : { ifNoneMatch: etag }
108
+ });
109
+ } catch (error) {
110
+ throw normalizeError(error);
111
+ }
112
+ if (output === void 0 || output === null) {
113
+ if (etag === null) throw UNEXPECTED_NOT_MODIFIED;
114
+ return { status: "unchanged", etag };
115
+ }
116
+ return { status: "ok", data: output.data, etag: output.meta.etag };
117
+ };
118
+ return { bootstrap };
119
+ }
120
+
61
121
  // src/events.ts
62
122
  function createEventBus() {
63
123
  const listeners = /* @__PURE__ */ new Set();
@@ -198,6 +258,10 @@ function createAuthNamespace(opts) {
198
258
  const confirmEmail = async (input) => {
199
259
  await call(() => opts.transport.client.auth.confirmEmail(input));
200
260
  };
261
+ const resendVerification = async () => {
262
+ const result = await call(() => opts.transport.client.auth.resendVerification({}));
263
+ return result.data;
264
+ };
201
265
  const verifyTotp = async (input) => {
202
266
  const result = await call(
203
267
  () => opts.transport.client.auth.verifyTotp({ token: input.challenge.token, code: input.code })
@@ -271,6 +335,9 @@ function createAuthNamespace(opts) {
271
335
  const changeEmail = async (input) => {
272
336
  await call(() => opts.transport.client.auth.changeEmail(input));
273
337
  };
338
+ const confirmEmailChange = async (input) => {
339
+ await call(() => opts.transport.client.auth.confirmEmailChange(input));
340
+ };
274
341
  const listSessions = async () => {
275
342
  const result = await call(() => opts.transport.client.auth.listSessions());
276
343
  return result.data;
@@ -327,6 +394,7 @@ function createAuthNamespace(opts) {
327
394
  requestPasswordReset,
328
395
  confirmPasswordReset,
329
396
  confirmEmail,
397
+ resendVerification,
330
398
  verifyTotp,
331
399
  verifyBackupCode,
332
400
  requestEmailOtp,
@@ -338,6 +406,7 @@ function createAuthNamespace(opts) {
338
406
  regenerateBackupCodes,
339
407
  changePassword,
340
408
  changeEmail,
409
+ confirmEmailChange,
341
410
  listSessions,
342
411
  revokeSession,
343
412
  revokeOtherSessions,
@@ -347,6 +416,9 @@ function createAuthNamespace(opts) {
347
416
  };
348
417
  }
349
418
 
419
+ // src/base-url.ts
420
+ var DEFAULT_BASE_URL = "https://api.fytkit.com";
421
+
350
422
  // src/data.ts
351
423
  function wrapSlice(slice) {
352
424
  const cache = /* @__PURE__ */ new Map();
@@ -385,9 +457,15 @@ function createDataNamespaces(transport) {
385
457
  sessionLogs: wrapSlice(c.sessionLog),
386
458
  progression: wrapSlice(c.progression),
387
459
  bodyMetrics: wrapSlice(c.bodyMetric),
460
+ bodyMeasurements: wrapSlice(c.bodyMeasurement),
461
+ progressPhotos: wrapSlice(c.progressPhoto),
462
+ checkIns: wrapSlice(c.checkin),
463
+ messages: wrapSlice(c.message),
464
+ timeline: wrapSlice(c.timeline),
465
+ health: wrapSlice(c.health),
466
+ habits: wrapSlice(c.habit),
388
467
  progress: wrapSlice(c.progress),
389
468
  media: wrapSlice(c.media),
390
- appConfig: wrapSlice(c.appConfig),
391
469
  subscription: wrapSlice(c.subscription),
392
470
  profile: wrapSlice(c.profile),
393
471
  nutritionLog: wrapSlice(c.nutritionLog),
@@ -445,18 +523,71 @@ function createMemoryStorageAdapter() {
445
523
  }
446
524
  };
447
525
  }
526
+
527
+ // src/retry-after.ts
528
+ var DELAY_SECONDS = /^\d+$/;
529
+ function retryAfterHeaderMs(value, now) {
530
+ if (value === null) return null;
531
+ const trimmed = value.trim();
532
+ if (trimmed.length === 0) return null;
533
+ if (DELAY_SECONDS.test(trimmed)) return Number(trimmed) * 1e3;
534
+ if (!/[a-z]/i.test(trimmed)) return null;
535
+ const at = Date.parse(trimmed);
536
+ return Number.isNaN(at) ? null : Math.max(0, at - now);
537
+ }
538
+ function parseJson(text) {
539
+ try {
540
+ return JSON.parse(text);
541
+ } catch {
542
+ return void 0;
543
+ }
544
+ }
545
+ function hintedBody(body, waitMs) {
546
+ if (isRecord(body) && isRecord(body.json) && typeof body.json.code === "string") {
547
+ const error = body.json;
548
+ const data = isRecord(error.data) ? error.data : {};
549
+ if (typeof data.retryAfterMs === "number") return null;
550
+ return { ...body, json: { ...error, data: { ...data, retryAfterMs: waitMs } } };
551
+ }
552
+ return {
553
+ json: {
554
+ defined: false,
555
+ code: "TOO_MANY_REQUESTS",
556
+ status: 429,
557
+ message: "Too Many Requests",
558
+ data: { retryAfterMs: waitMs }
559
+ }
560
+ };
561
+ }
562
+ async function withRetryAfterHint(response, now) {
563
+ if (response.status !== 429) return response;
564
+ const waitMs = retryAfterHeaderMs(response.headers.get("retry-after"), now);
565
+ if (waitMs === null) return response;
566
+ const hinted = hintedBody(parseJson(await response.clone().text()), waitMs);
567
+ if (hinted === null) return response;
568
+ const headers = new Headers(response.headers);
569
+ headers.set("content-type", "application/json");
570
+ headers.delete("content-length");
571
+ return new Response(JSON.stringify(hinted), {
572
+ status: response.status,
573
+ statusText: response.statusText,
574
+ headers
575
+ });
576
+ }
577
+
578
+ // src/transport.ts
448
579
  function createTransport(options) {
449
580
  let interceptor = null;
450
581
  const baseFetch = options.fetch ?? fetch.bind(globalThis);
451
- const wrappedFetch = (input, init) => {
582
+ const wrappedFetch = async (input, init) => {
452
583
  const request = input instanceof Request ? input : new Request(input, init);
453
584
  const next = (req) => baseFetch(req);
454
- if (!interceptor) return next(request);
455
- return interceptor(request, next);
585
+ const response = interceptor ? await interceptor(request, next) : await next(request);
586
+ return withRetryAfterHint(response, Date.now());
456
587
  };
457
588
  const link = new RPCLink({
458
589
  url: () => `${options.baseUrl}/rpc`,
459
- headers: () => {
590
+ headers: ({ context }) => {
460
591
  const session = options.getSession();
461
592
  const headers = {
462
593
  "X-Fytkit-Client-Id": options.clientId
@@ -464,6 +595,9 @@ function createTransport(options) {
464
595
  if (session) {
465
596
  headers.Authorization = `Bearer ${session.accessToken}`;
466
597
  }
598
+ if (context.ifNoneMatch !== void 0) {
599
+ headers["If-None-Match"] = context.ifNoneMatch;
600
+ }
467
601
  return headers;
468
602
  },
469
603
  fetch: wrappedFetch
@@ -483,6 +617,7 @@ var CREDENTIAL_PROCEDURES = [
483
617
  "auth/requestPasswordReset",
484
618
  "auth/confirmPasswordReset",
485
619
  "auth/confirmEmail",
620
+ "auth/confirmEmailChange",
486
621
  "auth/verifyTotp",
487
622
  "auth/verifyBackupCode",
488
623
  "auth/requestEmailOtp",
@@ -550,9 +685,331 @@ function attachRefreshInterceptor(opts) {
550
685
  return retried;
551
686
  });
552
687
  }
688
+ var INACTIVE = {
689
+ kind: "not_found",
690
+ refusal: { reason: "join_code_inactive", data: {} }
691
+ };
692
+ var IGNORED_SEPARATORS = /[\s\-\u2010-\u2015\u2212]/g;
693
+ var PATH_SAFE_CODE = /^[A-Za-z0-9]{1,64}$/;
694
+ function pathSafeJoinCode(input) {
695
+ const candidate = input.replace(IGNORED_SEPARATORS, "");
696
+ return PATH_SAFE_CODE.test(candidate) ? candidate.toUpperCase() : null;
697
+ }
698
+ async function readJson(response) {
699
+ try {
700
+ return await response.json();
701
+ } catch {
702
+ return void 0;
703
+ }
704
+ }
705
+ function refusalOf(response, body) {
706
+ const wait = () => retryAfterHeaderMs(response.headers.get("retry-after"), Date.now()) ?? 0;
707
+ if (isORPCErrorJson(body)) {
708
+ const error = normalizeError(createORPCErrorFromJson(body));
709
+ if (error.kind === "rate_limited" && error.retryAfter === 0) {
710
+ return { ...error, retryAfter: wait() };
711
+ }
712
+ return error;
713
+ }
714
+ if (response.status === 429) return { kind: "rate_limited", retryAfter: wait() };
715
+ return { kind: "server", status: response.status };
716
+ }
717
+ async function resolveJoinCode(code, options = {}) {
718
+ const canonical = pathSafeJoinCode(code);
719
+ if (canonical === null) throw INACTIVE;
720
+ const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
721
+ const doFetch = options.fetch ?? fetch.bind(globalThis);
722
+ let response;
723
+ try {
724
+ response = await doFetch(`${baseUrl}/api/v1/join/${canonical}`, {
725
+ method: "GET",
726
+ headers: { Accept: "application/json" }
727
+ });
728
+ } catch (error) {
729
+ throw normalizeError(error);
730
+ }
731
+ const body = await readJson(response);
732
+ if (response.ok) {
733
+ if (isRecord(body) && isRecord(body.data)) {
734
+ return body.data;
735
+ }
736
+ throw { kind: "server", status: response.status };
737
+ }
738
+ throw refusalOf(response, body);
739
+ }
740
+
741
+ // src/payment-policy.ts
742
+ var PLAN_INFO = { mode: "plan_info" };
743
+ function resolvePaymentMode(policy, options) {
744
+ if (!policy || !Array.isArray(policy.linkOut)) return PLAN_INFO;
745
+ const storefront = options.storefront?.trim().toUpperCase() ?? "";
746
+ if (storefront === "") return PLAN_INFO;
747
+ const rule = policy.linkOut.find(
748
+ (entry) => entry?.platform === options.platform && typeof entry.storefront === "string" && entry.storefront.toUpperCase() === storefront
749
+ );
750
+ if (!rule || !Array.isArray(rule.conditions)) return PLAN_INFO;
751
+ const met = new Set(options.conditionsMet ?? []);
752
+ if (!rule.conditions.every((condition) => met.has(condition))) return PLAN_INFO;
753
+ return { mode: "link_out", conditions: rule.conditions };
754
+ }
755
+
756
+ // src/realtime.ts
757
+ var MESSAGES_FALLBACK_POLL_MS = {
758
+ conversation: 1e4,
759
+ unreadCount: 6e4
760
+ };
761
+ var THREAD_CHANGED_EVENT = "thread_changed";
762
+ var MEMBER_TOPIC_PREFIX = "member:";
763
+ var TOKEN_RENEW_BEFORE_MS = 6e4;
764
+ var TOKEN_MIN_DELAY_MS = 5e3;
765
+ var RETRY_MS = 6e4;
766
+ var REJOIN_DELAYS_MS = [5e3, 15e3, 6e4];
767
+ var SIGNED_OUT_EVENTS = /* @__PURE__ */ new Set([
768
+ "signed_out",
769
+ "signed_out_due_to_token_reuse"
770
+ ]);
771
+ var FINAL_ERROR_KINDS = /* @__PURE__ */ new Set([
772
+ "auth_required",
773
+ "forbidden",
774
+ "not_found",
775
+ "validation"
776
+ ]);
777
+ function isFinalError(error) {
778
+ if (typeof error !== "object" || error === null || !("kind" in error)) return false;
779
+ const kind = error.kind;
780
+ return typeof kind === "string" && FINAL_ERROR_KINDS.has(kind);
781
+ }
782
+ function isMemberTopic(topic) {
783
+ return typeof topic === "string" && topic.startsWith(MEMBER_TOPIC_PREFIX) && topic.length > MEMBER_TOPIC_PREFIX.length;
784
+ }
785
+ function isConnection(value) {
786
+ if (typeof value !== "object" || value === null) return false;
787
+ if (!("url" in value) || !("anonKey" in value)) return false;
788
+ return typeof value.url === "string" && value.url.length > 0 && typeof value.anonKey === "string" && value.anonKey.length > 0;
789
+ }
790
+ function renewalDelay(expiresAt, now) {
791
+ const expiry = Date.parse(expiresAt);
792
+ if (Number.isNaN(expiry)) return RETRY_MS;
793
+ return Math.max(TOKEN_MIN_DELAY_MS, expiry - TOKEN_RENEW_BEFORE_MS - now);
794
+ }
795
+ function isUsable(expiresAt, now) {
796
+ return Date.parse(expiresAt) - now > TOKEN_MIN_DELAY_MS;
797
+ }
798
+ function rejoinDelay(closures) {
799
+ const last = REJOIN_DELAYS_MS.length - 1;
800
+ return REJOIN_DELAYS_MS[Math.min(Math.max(closures - 1, 0), last)];
801
+ }
802
+ function ignore() {
803
+ }
804
+ function authorise(client, token) {
805
+ return new Promise((resolve) => {
806
+ resolve(client.realtime.setAuth(token));
807
+ }).then(ignore, ignore);
808
+ }
809
+ function subscribeToMessages(client, options) {
810
+ let closed = false;
811
+ let lastStatus = null;
812
+ let timer = null;
813
+ let renewing = false;
814
+ let connection = null;
815
+ let socket = null;
816
+ let held = null;
817
+ let channel = null;
818
+ let rejoinTimer = null;
819
+ let closures = 0;
820
+ let stopAuthListener = null;
821
+ const report = (status) => {
822
+ if (closed || status === lastStatus) return;
823
+ lastStatus = status;
824
+ options.onStatus?.(status);
825
+ };
826
+ const clearTimer = () => {
827
+ if (timer === null) return;
828
+ clearTimeout(timer);
829
+ timer = null;
830
+ };
831
+ const after = (delayMs, run) => {
832
+ clearTimer();
833
+ if (closed) return;
834
+ timer = setTimeout(() => {
835
+ timer = null;
836
+ void run();
837
+ }, delayMs);
838
+ };
839
+ const cancelRejoin = () => {
840
+ if (rejoinTimer !== null) clearTimeout(rejoinTimer);
841
+ rejoinTimer = null;
842
+ };
843
+ const drop = () => {
844
+ const open = socket;
845
+ const joined = channel;
846
+ socket = null;
847
+ held = null;
848
+ channel = null;
849
+ cancelRejoin();
850
+ closures = 0;
851
+ if (open === null) return;
852
+ if (joined !== null) Promise.resolve(open.removeChannel(joined)).then(ignore, ignore);
853
+ open.realtime.disconnect();
854
+ };
855
+ const close = () => {
856
+ if (closed) return;
857
+ closed = true;
858
+ clearTimer();
859
+ drop();
860
+ const stop = stopAuthListener;
861
+ stopAuthListener = null;
862
+ stop?.();
863
+ };
864
+ const finish = (status) => {
865
+ if (closed) return;
866
+ const changed = status !== lastStatus;
867
+ lastStatus = status;
868
+ close();
869
+ if (changed) options.onStatus?.(status);
870
+ };
871
+ const join = (joinTopic, open) => {
872
+ if (closed || socket !== open || channel !== null) return;
873
+ const joined = open.channel(joinTopic, { config: { private: true } });
874
+ channel = joined;
875
+ const current = () => !closed && channel === joined;
876
+ joined.on("broadcast", { event: THREAD_CHANGED_EVENT }, () => {
877
+ if (current()) options.onChange();
878
+ }).subscribe((status) => {
879
+ if (!current()) return;
880
+ if (status === "SUBSCRIBED") {
881
+ closures = 0;
882
+ report("live");
883
+ options.onChange();
884
+ return;
885
+ }
886
+ report("fallback");
887
+ if (status === "CLOSED") {
888
+ channel = null;
889
+ scheduleRejoin();
890
+ }
891
+ });
892
+ };
893
+ const authoriseAndJoin = (grant, open) => {
894
+ void authorise(open, grant.token).then(() => join(grant.topic, open));
895
+ };
896
+ const rejoin = () => {
897
+ const open = socket;
898
+ const grant = held;
899
+ if (closed || open === null || grant === null || channel !== null) return;
900
+ if (!isUsable(grant.expiresAt, Date.now())) {
901
+ void renew();
902
+ return;
903
+ }
904
+ authoriseAndJoin(grant, open);
905
+ };
906
+ const scheduleRejoin = () => {
907
+ if (closed || rejoinTimer !== null) return;
908
+ closures += 1;
909
+ rejoinTimer = setTimeout(() => {
910
+ rejoinTimer = null;
911
+ rejoin();
912
+ }, rejoinDelay(closures));
913
+ };
914
+ const connect = (grant, settings) => {
915
+ let opened;
916
+ try {
917
+ opened = options.realtime(settings);
918
+ } catch {
919
+ finish("fallback");
920
+ return;
921
+ }
922
+ socket = opened;
923
+ held = grant;
924
+ after(renewalDelay(grant.expiresAt, Date.now()), renew);
925
+ authoriseAndJoin(grant, opened);
926
+ };
927
+ const openGrant = async (grant) => {
928
+ if (!isMemberTopic(grant.topic)) {
929
+ finish("fallback");
930
+ return;
931
+ }
932
+ if (connection === null) {
933
+ let realtime;
934
+ try {
935
+ const bootstrap = await client.app.bootstrap();
936
+ realtime = bootstrap.status === "ok" ? bootstrap.data.realtime : void 0;
937
+ } catch (error) {
938
+ if (closed) return;
939
+ if (isFinalError(error)) {
940
+ finish("fallback");
941
+ return;
942
+ }
943
+ report("fallback");
944
+ after(RETRY_MS, start);
945
+ return;
946
+ }
947
+ if (closed) return;
948
+ if (!isConnection(realtime)) {
949
+ finish("fallback");
950
+ return;
951
+ }
952
+ connection = realtime;
953
+ }
954
+ connect(grant, connection);
955
+ };
956
+ const renew = async () => {
957
+ if (renewing) return;
958
+ renewing = true;
959
+ let grant;
960
+ try {
961
+ grant = (await client.messages.realtimeToken({})).data;
962
+ } catch (error) {
963
+ if (closed) return;
964
+ if (isFinalError(error)) finish("refused");
965
+ else after(RETRY_MS, renew);
966
+ return;
967
+ } finally {
968
+ renewing = false;
969
+ }
970
+ const current = socket;
971
+ if (closed || current === null || held === null) return;
972
+ if (grant.topic !== held.topic) {
973
+ drop();
974
+ report("connecting");
975
+ await openGrant(grant);
976
+ return;
977
+ }
978
+ held = grant;
979
+ after(renewalDelay(grant.expiresAt, Date.now()), renew);
980
+ if (channel !== null) {
981
+ void authorise(current, grant.token);
982
+ return;
983
+ }
984
+ cancelRejoin();
985
+ authoriseAndJoin(grant, current);
986
+ };
987
+ const start = async () => {
988
+ let grant;
989
+ try {
990
+ grant = (await client.messages.realtimeToken({})).data;
991
+ } catch (error) {
992
+ if (closed) return;
993
+ if (isFinalError(error)) {
994
+ finish("refused");
995
+ return;
996
+ }
997
+ report("fallback");
998
+ after(RETRY_MS, start);
999
+ return;
1000
+ }
1001
+ if (closed) return;
1002
+ await openGrant(grant);
1003
+ };
1004
+ report("connecting");
1005
+ stopAuthListener = client.auth?.onAuthStateChange((event) => {
1006
+ if (SIGNED_OUT_EVENTS.has(event.type)) finish("refused");
1007
+ }) ?? null;
1008
+ void start();
1009
+ return close;
1010
+ }
553
1011
 
554
1012
  // src/index.ts
555
- var DEFAULT_BASE_URL = "https://api.fytkit.com";
556
1013
  function createFytkitClient(options) {
557
1014
  if (!options || typeof options.clientId !== "string" || options.clientId.length === 0) {
558
1015
  throw new Error("createFytkitClient: `clientId` is required");
@@ -571,6 +1028,7 @@ function createFytkitClient(options) {
571
1028
  attachRefreshInterceptor({ transport, auth: authInstance });
572
1029
  const data = createDataNamespaces(transport);
573
1030
  return {
1031
+ clientId: options.clientId,
574
1032
  auth: {
575
1033
  signUp: authInstance.signUp,
576
1034
  signIn: authInstance.signIn,
@@ -580,6 +1038,7 @@ function createFytkitClient(options) {
580
1038
  requestPasswordReset: authInstance.requestPasswordReset,
581
1039
  confirmPasswordReset: authInstance.confirmPasswordReset,
582
1040
  confirmEmail: authInstance.confirmEmail,
1041
+ resendVerification: authInstance.resendVerification,
583
1042
  verifyTotp: authInstance.verifyTotp,
584
1043
  verifyBackupCode: authInstance.verifyBackupCode,
585
1044
  requestEmailOtp: authInstance.requestEmailOtp,
@@ -591,15 +1050,17 @@ function createFytkitClient(options) {
591
1050
  regenerateBackupCodes: authInstance.regenerateBackupCodes,
592
1051
  changePassword: authInstance.changePassword,
593
1052
  changeEmail: authInstance.changeEmail,
1053
+ confirmEmailChange: authInstance.confirmEmailChange,
594
1054
  listSessions: authInstance.listSessions,
595
1055
  revokeSession: authInstance.revokeSession,
596
1056
  revokeOtherSessions: authInstance.revokeOtherSessions,
597
1057
  closeAccount: authInstance.closeAccount
598
1058
  },
599
- ...data
1059
+ ...data,
1060
+ app: createAppNamespace(transport)
600
1061
  };
601
1062
  }
602
1063
 
603
- export { createFytkitClient, createLocalStorageAdapter, createMemoryStorageAdapter };
1064
+ export { MESSAGES_FALLBACK_POLL_MS, createFytkitClient, createLocalStorageAdapter, createMemoryStorageAdapter, refusalData, resolveJoinCode, resolvePaymentMode, subscribeToMessages };
604
1065
  //# sourceMappingURL=index.js.map
605
1066
  //# sourceMappingURL=index.js.map