@fytkit/sdk 3.5.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,4 +1,4 @@
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
4
  // src/error.ts
@@ -20,7 +20,8 @@ function pickRefusal(data) {
20
20
  if (!isRecord(data)) return {};
21
21
  const { reason, ...rest } = data;
22
22
  if (typeof reason === "string" && reason.length > 0) return { refusal: { reason, data: rest } };
23
- if (data.quotaCode === MEMBER_CAP_QUOTA) return { refusal: { reason: MEMBER_CAP_QUOTA, data: {} } };
23
+ if (data.quotaCode === MEMBER_CAP_QUOTA)
24
+ return { refusal: { reason: MEMBER_CAP_QUOTA, data: {} } };
24
25
  return {};
25
26
  }
26
27
 
@@ -95,6 +96,28 @@ function normalizeError(err) {
95
96
  return { kind: "server", status: 0 };
96
97
  }
97
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
+
98
121
  // src/events.ts
99
122
  function createEventBus() {
100
123
  const listeners = /* @__PURE__ */ new Set();
@@ -235,6 +258,10 @@ function createAuthNamespace(opts) {
235
258
  const confirmEmail = async (input) => {
236
259
  await call(() => opts.transport.client.auth.confirmEmail(input));
237
260
  };
261
+ const resendVerification = async () => {
262
+ const result = await call(() => opts.transport.client.auth.resendVerification({}));
263
+ return result.data;
264
+ };
238
265
  const verifyTotp = async (input) => {
239
266
  const result = await call(
240
267
  () => opts.transport.client.auth.verifyTotp({ token: input.challenge.token, code: input.code })
@@ -308,6 +335,9 @@ function createAuthNamespace(opts) {
308
335
  const changeEmail = async (input) => {
309
336
  await call(() => opts.transport.client.auth.changeEmail(input));
310
337
  };
338
+ const confirmEmailChange = async (input) => {
339
+ await call(() => opts.transport.client.auth.confirmEmailChange(input));
340
+ };
311
341
  const listSessions = async () => {
312
342
  const result = await call(() => opts.transport.client.auth.listSessions());
313
343
  return result.data;
@@ -364,6 +394,7 @@ function createAuthNamespace(opts) {
364
394
  requestPasswordReset,
365
395
  confirmPasswordReset,
366
396
  confirmEmail,
397
+ resendVerification,
367
398
  verifyTotp,
368
399
  verifyBackupCode,
369
400
  requestEmailOtp,
@@ -375,6 +406,7 @@ function createAuthNamespace(opts) {
375
406
  regenerateBackupCodes,
376
407
  changePassword,
377
408
  changeEmail,
409
+ confirmEmailChange,
378
410
  listSessions,
379
411
  revokeSession,
380
412
  revokeOtherSessions,
@@ -384,6 +416,9 @@ function createAuthNamespace(opts) {
384
416
  };
385
417
  }
386
418
 
419
+ // src/base-url.ts
420
+ var DEFAULT_BASE_URL = "https://api.fytkit.com";
421
+
387
422
  // src/data.ts
388
423
  function wrapSlice(slice) {
389
424
  const cache = /* @__PURE__ */ new Map();
@@ -422,11 +457,15 @@ function createDataNamespaces(transport) {
422
457
  sessionLogs: wrapSlice(c.sessionLog),
423
458
  progression: wrapSlice(c.progression),
424
459
  bodyMetrics: wrapSlice(c.bodyMetric),
460
+ bodyMeasurements: wrapSlice(c.bodyMeasurement),
461
+ progressPhotos: wrapSlice(c.progressPhoto),
425
462
  checkIns: wrapSlice(c.checkin),
426
463
  messages: wrapSlice(c.message),
464
+ timeline: wrapSlice(c.timeline),
465
+ health: wrapSlice(c.health),
466
+ habits: wrapSlice(c.habit),
427
467
  progress: wrapSlice(c.progress),
428
468
  media: wrapSlice(c.media),
429
- appConfig: wrapSlice(c.appConfig),
430
469
  subscription: wrapSlice(c.subscription),
431
470
  profile: wrapSlice(c.profile),
432
471
  nutritionLog: wrapSlice(c.nutritionLog),
@@ -548,7 +587,7 @@ function createTransport(options) {
548
587
  };
549
588
  const link = new RPCLink({
550
589
  url: () => `${options.baseUrl}/rpc`,
551
- headers: () => {
590
+ headers: ({ context }) => {
552
591
  const session = options.getSession();
553
592
  const headers = {
554
593
  "X-Fytkit-Client-Id": options.clientId
@@ -556,6 +595,9 @@ function createTransport(options) {
556
595
  if (session) {
557
596
  headers.Authorization = `Bearer ${session.accessToken}`;
558
597
  }
598
+ if (context.ifNoneMatch !== void 0) {
599
+ headers["If-None-Match"] = context.ifNoneMatch;
600
+ }
559
601
  return headers;
560
602
  },
561
603
  fetch: wrappedFetch
@@ -575,6 +617,7 @@ var CREDENTIAL_PROCEDURES = [
575
617
  "auth/requestPasswordReset",
576
618
  "auth/confirmPasswordReset",
577
619
  "auth/confirmEmail",
620
+ "auth/confirmEmailChange",
578
621
  "auth/verifyTotp",
579
622
  "auth/verifyBackupCode",
580
623
  "auth/requestEmailOtp",
@@ -642,6 +685,73 @@ function attachRefreshInterceptor(opts) {
642
685
  return retried;
643
686
  });
644
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
+ }
645
755
 
646
756
  // src/realtime.ts
647
757
  var MESSAGES_FALLBACK_POLL_MS = {
@@ -822,7 +932,8 @@ function subscribeToMessages(client, options) {
822
932
  if (connection === null) {
823
933
  let realtime;
824
934
  try {
825
- realtime = (await client.appConfig.get()).data.realtime;
935
+ const bootstrap = await client.app.bootstrap();
936
+ realtime = bootstrap.status === "ok" ? bootstrap.data.realtime : void 0;
826
937
  } catch (error) {
827
938
  if (closed) return;
828
939
  if (isFinalError(error)) {
@@ -899,7 +1010,6 @@ function subscribeToMessages(client, options) {
899
1010
  }
900
1011
 
901
1012
  // src/index.ts
902
- var DEFAULT_BASE_URL = "https://api.fytkit.com";
903
1013
  function createFytkitClient(options) {
904
1014
  if (!options || typeof options.clientId !== "string" || options.clientId.length === 0) {
905
1015
  throw new Error("createFytkitClient: `clientId` is required");
@@ -918,6 +1028,7 @@ function createFytkitClient(options) {
918
1028
  attachRefreshInterceptor({ transport, auth: authInstance });
919
1029
  const data = createDataNamespaces(transport);
920
1030
  return {
1031
+ clientId: options.clientId,
921
1032
  auth: {
922
1033
  signUp: authInstance.signUp,
923
1034
  signIn: authInstance.signIn,
@@ -927,6 +1038,7 @@ function createFytkitClient(options) {
927
1038
  requestPasswordReset: authInstance.requestPasswordReset,
928
1039
  confirmPasswordReset: authInstance.confirmPasswordReset,
929
1040
  confirmEmail: authInstance.confirmEmail,
1041
+ resendVerification: authInstance.resendVerification,
930
1042
  verifyTotp: authInstance.verifyTotp,
931
1043
  verifyBackupCode: authInstance.verifyBackupCode,
932
1044
  requestEmailOtp: authInstance.requestEmailOtp,
@@ -938,15 +1050,17 @@ function createFytkitClient(options) {
938
1050
  regenerateBackupCodes: authInstance.regenerateBackupCodes,
939
1051
  changePassword: authInstance.changePassword,
940
1052
  changeEmail: authInstance.changeEmail,
1053
+ confirmEmailChange: authInstance.confirmEmailChange,
941
1054
  listSessions: authInstance.listSessions,
942
1055
  revokeSession: authInstance.revokeSession,
943
1056
  revokeOtherSessions: authInstance.revokeOtherSessions,
944
1057
  closeAccount: authInstance.closeAccount
945
1058
  },
946
- ...data
1059
+ ...data,
1060
+ app: createAppNamespace(transport)
947
1061
  };
948
1062
  }
949
1063
 
950
- export { MESSAGES_FALLBACK_POLL_MS, createFytkitClient, createLocalStorageAdapter, createMemoryStorageAdapter, refusalData, subscribeToMessages };
1064
+ export { MESSAGES_FALLBACK_POLL_MS, createFytkitClient, createLocalStorageAdapter, createMemoryStorageAdapter, refusalData, resolveJoinCode, resolvePaymentMode, subscribeToMessages };
951
1065
  //# sourceMappingURL=index.js.map
952
1066
  //# sourceMappingURL=index.js.map