@fytkit/sdk 4.0.0 → 4.2.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
@@ -238,6 +238,34 @@ function createAuthNamespace(opts) {
238
238
  const _exhaustive = result.data;
239
239
  throw _exhaustive;
240
240
  };
241
+ const signInWithIdToken = async (input) => {
242
+ const result = await call(
243
+ () => opts.transport.client.auth.signInWithIdToken({
244
+ provider: input.provider,
245
+ idToken: input.idToken,
246
+ nonce: input.nonce,
247
+ name: input.name,
248
+ authorizationCode: input.authorizationCode
249
+ })
250
+ );
251
+ if (result.data.kind === "two_factor_required") {
252
+ const token = result.data.twoFactorToken;
253
+ return {
254
+ kind: "two_factor_required",
255
+ challenge: { token, availableMethods: result.data.availableMethods }
256
+ };
257
+ }
258
+ if (result.data.kind === "signed_in") {
259
+ const { user, session, memberCreated } = result.data;
260
+ const cached2 = applySession(
261
+ { accessToken: session.accessToken, expiresAt: session.expiresAt, user },
262
+ "signed_in"
263
+ );
264
+ return { kind: "signed_in", session: cached2, memberCreated };
265
+ }
266
+ const _exhaustive = result.data;
267
+ throw _exhaustive;
268
+ };
241
269
  const signOut = async () => {
242
270
  const current = cached;
243
271
  if (!current) return;
@@ -316,7 +344,8 @@ function createAuthNamespace(opts) {
316
344
  adoptRotatedToken(result.data.accessToken);
317
345
  };
318
346
  const disableTwoFactor = async (input) => {
319
- await call(() => opts.transport.client.auth.disableTwoFactor(input));
347
+ const result = await call(() => opts.transport.client.auth.disableTwoFactor(input));
348
+ adoptRotatedToken(result.data.accessToken);
320
349
  };
321
350
  const regenerateBackupCodes = async (input) => {
322
351
  const result = await call(() => opts.transport.client.auth.regenerateBackupCodes(input));
@@ -349,12 +378,16 @@ function createAuthNamespace(opts) {
349
378
  await call(() => opts.transport.client.auth.revokeOtherSessions());
350
379
  };
351
380
  const closeAccount = async (input) => {
352
- await call(
353
- () => opts.transport.client.auth.closeAccount({
354
- confirmEmail: input.confirmEmail,
355
- password: input.password
356
- })
357
- );
381
+ const body = input.identityToken !== void 0 ? {
382
+ confirmEmail: input.confirmEmail,
383
+ identityToken: {
384
+ provider: input.identityToken.provider,
385
+ idToken: input.identityToken.idToken,
386
+ nonce: input.identityToken.nonce,
387
+ authorizationCode: input.identityToken.authorizationCode
388
+ }
389
+ } : { confirmEmail: input.confirmEmail, password: input.password };
390
+ await call(() => opts.transport.client.auth.closeAccount(body));
358
391
  clearSession();
359
392
  };
360
393
  const _refresh = async () => {
@@ -388,6 +421,7 @@ function createAuthNamespace(opts) {
388
421
  return {
389
422
  signUp,
390
423
  signIn,
424
+ signInWithIdToken,
391
425
  signOut,
392
426
  getSession,
393
427
  onAuthStateChange,
@@ -451,6 +485,7 @@ function createDataNamespaces(transport) {
451
485
  equipment: wrapSlice(c.equipment),
452
486
  recipes: wrapSlice(c.recipe),
453
487
  nutrition: wrapSlice(c.nutrition),
488
+ nutritionFollows: wrapSlice(c.nutritionFollow),
454
489
  articles: wrapSlice(c.article),
455
490
  enrollments: wrapSlice(c.enrollment),
456
491
  favourites: wrapSlice(c.favourite),
@@ -613,6 +648,7 @@ function createTransport(options) {
613
648
  var REFRESH_HEADER = "X-Fytkit-Refresh";
614
649
  var CREDENTIAL_PROCEDURES = [
615
650
  "auth/signIn",
651
+ "auth/signInWithIdToken",
616
652
  "auth/signUp",
617
653
  "auth/requestPasswordReset",
618
654
  "auth/confirmPasswordReset",
@@ -754,11 +790,13 @@ function resolvePaymentMode(policy, options) {
754
790
  }
755
791
 
756
792
  // src/realtime.ts
793
+ var COACH_TYPING_EXPIRY_MS = 8e3;
757
794
  var MESSAGES_FALLBACK_POLL_MS = {
758
795
  conversation: 1e4,
759
796
  unreadCount: 6e4
760
797
  };
761
798
  var THREAD_CHANGED_EVENT = "thread_changed";
799
+ var COACH_TYPING_EVENT = "coach_typing";
762
800
  var MEMBER_TOPIC_PREFIX = "member:";
763
801
  var TOKEN_RENEW_BEFORE_MS = 6e4;
764
802
  var TOKEN_MIN_DELAY_MS = 5e3;
@@ -782,6 +820,17 @@ function isFinalError(error) {
782
820
  function isMemberTopic(topic) {
783
821
  return typeof topic === "string" && topic.startsWith(MEMBER_TOPIC_PREFIX) && topic.length > MEMBER_TOPIC_PREFIX.length;
784
822
  }
823
+ function coachTypingSign(message) {
824
+ if (typeof message !== "object" || message === null || !("payload" in message)) return null;
825
+ const payload = message.payload;
826
+ if (typeof payload !== "object" || payload === null) return null;
827
+ if (!("state" in payload) || !("name" in payload)) return null;
828
+ const { state, name } = payload;
829
+ if (state !== "typing" && state !== "stopped") return null;
830
+ if (typeof name !== "string" || name.length === 0) return null;
831
+ const key = "key" in payload && typeof payload.key === "string" ? payload.key : "";
832
+ return { state, name, key: key.length > 0 ? `key:${key}` : `name:${name}` };
833
+ }
785
834
  function isConnection(value) {
786
835
  if (typeof value !== "object" || value === null) return false;
787
836
  if (!("url" in value) || !("anonKey" in value)) return false;
@@ -818,9 +867,45 @@ function subscribeToMessages(client, options) {
818
867
  let rejoinTimer = null;
819
868
  let closures = 0;
820
869
  let stopAuthListener = null;
870
+ const writing = /* @__PURE__ */ new Map();
871
+ let reportedNames = [];
872
+ const reportTyping = () => {
873
+ if (closed) return;
874
+ const names = [...new Set([...writing.values()].map((writer) => writer.name))];
875
+ if (names.length === reportedNames.length && names.every((name, i) => name === reportedNames[i])) {
876
+ return;
877
+ }
878
+ reportedNames = names;
879
+ options.onCoachTyping?.(names.length === 0 ? { kind: "idle" } : { kind: "typing", names });
880
+ };
881
+ const clearTyping = () => {
882
+ if (writing.size === 0) return;
883
+ for (const writer of writing.values()) clearTimeout(writer.expiry);
884
+ writing.clear();
885
+ reportTyping();
886
+ };
887
+ const onTypingSign = (sign) => {
888
+ const known = writing.get(sign.key);
889
+ if (known !== void 0) clearTimeout(known.expiry);
890
+ if (sign.state === "stopped") {
891
+ if (known === void 0) return;
892
+ writing.delete(sign.key);
893
+ reportTyping();
894
+ return;
895
+ }
896
+ writing.set(sign.key, {
897
+ name: sign.name,
898
+ expiry: setTimeout(() => {
899
+ writing.delete(sign.key);
900
+ reportTyping();
901
+ }, COACH_TYPING_EXPIRY_MS)
902
+ });
903
+ reportTyping();
904
+ };
821
905
  const report = (status) => {
822
906
  if (closed || status === lastStatus) return;
823
907
  lastStatus = status;
908
+ if (status !== "live") clearTyping();
824
909
  options.onStatus?.(status);
825
910
  };
826
911
  const clearTimer = () => {
@@ -848,6 +933,7 @@ function subscribeToMessages(client, options) {
848
933
  channel = null;
849
934
  cancelRejoin();
850
935
  closures = 0;
936
+ clearTyping();
851
937
  if (open === null) return;
852
938
  if (joined !== null) Promise.resolve(open.removeChannel(joined)).then(ignore, ignore);
853
939
  open.realtime.disconnect();
@@ -864,8 +950,10 @@ function subscribeToMessages(client, options) {
864
950
  const finish = (status) => {
865
951
  if (closed) return;
866
952
  const changed = status !== lastStatus;
953
+ const wasTyping = writing.size > 0;
867
954
  lastStatus = status;
868
955
  close();
956
+ if (wasTyping) options.onCoachTyping?.({ kind: "idle" });
869
957
  if (changed) options.onStatus?.(status);
870
958
  };
871
959
  const join = (joinTopic, open) => {
@@ -875,6 +963,9 @@ function subscribeToMessages(client, options) {
875
963
  const current = () => !closed && channel === joined;
876
964
  joined.on("broadcast", { event: THREAD_CHANGED_EVENT }, () => {
877
965
  if (current()) options.onChange();
966
+ }).on("broadcast", { event: COACH_TYPING_EVENT }, (message) => {
967
+ const sign = coachTypingSign(message);
968
+ if (sign !== null && current()) onTypingSign(sign);
878
969
  }).subscribe((status) => {
879
970
  if (!current()) return;
880
971
  if (status === "SUBSCRIBED") {
@@ -1032,6 +1123,7 @@ function createFytkitClient(options) {
1032
1123
  auth: {
1033
1124
  signUp: authInstance.signUp,
1034
1125
  signIn: authInstance.signIn,
1126
+ signInWithIdToken: authInstance.signInWithIdToken,
1035
1127
  signOut: authInstance.signOut,
1036
1128
  getSession: authInstance.getSession,
1037
1129
  onAuthStateChange: authInstance.onAuthStateChange,
@@ -1061,6 +1153,6 @@ function createFytkitClient(options) {
1061
1153
  };
1062
1154
  }
1063
1155
 
1064
- export { MESSAGES_FALLBACK_POLL_MS, createFytkitClient, createLocalStorageAdapter, createMemoryStorageAdapter, refusalData, resolveJoinCode, resolvePaymentMode, subscribeToMessages };
1156
+ export { COACH_TYPING_EXPIRY_MS, MESSAGES_FALLBACK_POLL_MS, createFytkitClient, createLocalStorageAdapter, createMemoryStorageAdapter, refusalData, resolveJoinCode, resolvePaymentMode, subscribeToMessages };
1065
1157
  //# sourceMappingURL=index.js.map
1066
1158
  //# sourceMappingURL=index.js.map