@dragonmastery/dragoncore-vue 0.0.21 → 0.0.22

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.
Files changed (143) hide show
  1. package/dist/ChangePasswordPage-DVBkBcm9.js +6 -0
  2. package/dist/{ChangePasswordPage--3XwluwE.js → ChangePasswordPage-ePeFkv_6.js} +2 -2
  3. package/dist/{ChangePasswordPage--3XwluwE.js.map → ChangePasswordPage-ePeFkv_6.js.map} +1 -1
  4. package/dist/{ConsentRequired-C4IRMA0c.js → ConsentRequired-e7DEOGNg.js} +5 -5
  5. package/dist/{ConsentRequired-C4IRMA0c.js.map → ConsentRequired-e7DEOGNg.js.map} +1 -1
  6. package/dist/CreateTeamForm-CV9Y00tD.js +35 -0
  7. package/dist/CreateTeamMemberForm-BX1vUcdg.js +35 -0
  8. package/dist/{CreateUserPage-DLwXeLAq.js → CreateUserPage-Cdv-3U5M.js} +2 -2
  9. package/dist/{CreateUserPage-DLwXeLAq.js.map → CreateUserPage-Cdv-3U5M.js.map} +1 -1
  10. package/dist/CreateUserPage-DQoEX-Er.js +6 -0
  11. package/dist/CreditBalanceDashboard-BZAnEjSz.js +35 -0
  12. package/dist/CreditManagement-C4-_c175.js +35 -0
  13. package/dist/CustomerCreateSupportTicketForm-3tIJKMnJ.js +35 -0
  14. package/dist/{CustomerSupportTicketDetailPage-BdyaKG1v.js → CustomerSupportTicketDetailPage-UGqVoV4j.js} +7 -7
  15. package/dist/{CustomerSupportTicketDetailPage-BdyaKG1v.js.map → CustomerSupportTicketDetailPage-UGqVoV4j.js.map} +1 -1
  16. package/dist/CustomerSupportTicketList-CFQEoXtm.js +35 -0
  17. package/dist/{CustomerSupportTicketParent-HIxwSVdu.js → CustomerSupportTicketParent-C2XdM5f7.js} +2 -2
  18. package/dist/{CustomerSupportTicketParent-HIxwSVdu.js.map → CustomerSupportTicketParent-C2XdM5f7.js.map} +1 -1
  19. package/dist/CustomerSupportTicketParent-Tnov1dEg.js +7 -0
  20. package/dist/CustomerSupportTicketSuccess-DLszUCsg.js +35 -0
  21. package/dist/EditTeamForm-Ww04P2M0.js +35 -0
  22. package/dist/{EditTeamMemberForm-CaS2GLjV.js → EditTeamMemberForm-BgjNP8MZ.js} +2 -2
  23. package/dist/{EditTeamMemberForm-CaS2GLjV.js.map → EditTeamMemberForm-BgjNP8MZ.js.map} +1 -1
  24. package/dist/EditTeamMemberForm-COfY-2FQ.js +6 -0
  25. package/dist/EditUserPage-BJHs3raG.js +7 -0
  26. package/dist/{EditUserPage-DURc5rmi.js → EditUserPage-uLPhRW5x.js} +3 -3
  27. package/dist/{EditUserPage-DURc5rmi.js.map → EditUserPage-uLPhRW5x.js.map} +1 -1
  28. package/dist/{ForgotPassword-OjIPi9s9.js → ForgotPassword-B8JG_n9D.js} +2 -2
  29. package/dist/{ForgotPassword-OjIPi9s9.js.map → ForgotPassword-B8JG_n9D.js.map} +1 -1
  30. package/dist/ForgotPassword-CzMPARbz.js +7 -0
  31. package/dist/{LoginForm-9UFnA-fO.js → LoginForm-C-_lBDyl.js} +3 -3
  32. package/dist/{LoginForm-9UFnA-fO.js.map → LoginForm-C-_lBDyl.js.map} +1 -1
  33. package/dist/LoginForm-DdzRn8nU.js +7 -0
  34. package/dist/Logout-3_Ns09Vy.js +7 -0
  35. package/dist/{Logout-YgTgOFUH.js → Logout-CIAoXyOg.js} +3 -3
  36. package/dist/{Logout-YgTgOFUH.js.map → Logout-CIAoXyOg.js.map} +1 -1
  37. package/dist/{MfaSetup-RtFMY_dj.js → MfaSetup-9qdTKQ0m.js} +2 -2
  38. package/dist/{MfaSetup-RtFMY_dj.js.map → MfaSetup-9qdTKQ0m.js.map} +1 -1
  39. package/dist/MfaSetup-BE_NP70B.js +8 -0
  40. package/dist/{MfaVerify-Cvhe8bEM.js → MfaVerify-Cgta1nE9.js} +3 -3
  41. package/dist/{MfaVerify-Cvhe8bEM.js.map → MfaVerify-Cgta1nE9.js.map} +1 -1
  42. package/dist/MfaVerify-CyiJ9A3L.js +8 -0
  43. package/dist/{ResetPassword-BE4mXK9q.js → ResetPassword-DHUfERyS.js} +2 -2
  44. package/dist/{ResetPassword-BE4mXK9q.js.map → ResetPassword-DHUfERyS.js.map} +1 -1
  45. package/dist/ResetPassword-DXHunZVp.js +7 -0
  46. package/dist/{SavedFiltersPage-DQt6uc8m.js → SavedFiltersPage-CjFv4fI_.js} +26 -26
  47. package/dist/{SavedFiltersPage-DQt6uc8m.js.map → SavedFiltersPage-CjFv4fI_.js.map} +1 -1
  48. package/dist/Signup-Cy1puoqh.js +9 -0
  49. package/dist/{Signup-9TjMMnU4.js → Signup-DfG7Xmkx.js} +4 -4
  50. package/dist/{Signup-9TjMMnU4.js.map → Signup-DfG7Xmkx.js.map} +1 -1
  51. package/dist/{SignupConsentFlow-QUZGKjdB.js → SignupConsentFlow-YGWhF7tj.js} +4 -4
  52. package/dist/{SignupConsentFlow-QUZGKjdB.js.map → SignupConsentFlow-YGWhF7tj.js.map} +1 -1
  53. package/dist/{SignupRequirementsPage-DfbYmpQD.js → SignupRequirementsPage-Sm3vgkhC.js} +5 -5
  54. package/dist/{SignupRequirementsPage-DfbYmpQD.js.map → SignupRequirementsPage-Sm3vgkhC.js.map} +1 -1
  55. package/dist/StaffCreateSupportTicketForm-C5tRPz95.js +35 -0
  56. package/dist/{StaffSupportTicketDetailPage-DQdfh6H1.js → StaffSupportTicketDetailPage-ePkLJU12.js} +7 -7
  57. package/dist/{StaffSupportTicketDetailPage-DQdfh6H1.js.map → StaffSupportTicketDetailPage-ePkLJU12.js.map} +1 -1
  58. package/dist/StaffSupportTicketList-BbiPTm54.js +35 -0
  59. package/dist/{StaffSupportTicketParent-CilR4RGM.js → StaffSupportTicketParent-Bz-SH6-k.js} +2 -2
  60. package/dist/{StaffSupportTicketParent-CilR4RGM.js.map → StaffSupportTicketParent-Bz-SH6-k.js.map} +1 -1
  61. package/dist/StaffSupportTicketParent-D2onnMqe.js +7 -0
  62. package/dist/StaffSupportTicketSuccess-DLVRTvr1.js +35 -0
  63. package/dist/{SupportStaffPage-KKugAnFm.js → SupportStaffPage-0X1VMovT.js} +5 -5
  64. package/dist/{SupportStaffPage-KKugAnFm.js.map → SupportStaffPage-0X1VMovT.js.map} +1 -1
  65. package/dist/{SupportTicketMaintenancePage-smItdkrD.js → SupportTicketMaintenancePage-CLDqc4Pb.js} +4 -4
  66. package/dist/{SupportTicketMaintenancePage-smItdkrD.js.map → SupportTicketMaintenancePage-CLDqc4Pb.js.map} +1 -1
  67. package/dist/TeamAttachmentsTab-B-xXmvOy.js +35 -0
  68. package/dist/TeamHistoryTab-Bb7mq4Dc.js +4 -0
  69. package/dist/{TeamHistoryTab-D5biUPmq.js → TeamHistoryTab-D0zW5wjj.js} +2 -2
  70. package/dist/{TeamHistoryTab-D5biUPmq.js.map → TeamHistoryTab-D0zW5wjj.js.map} +1 -1
  71. package/dist/TeamList-B-cFoclM.js +35 -0
  72. package/dist/TeamMemberList-D3GNHlXH.js +35 -0
  73. package/dist/TeamMemberParent-BKfPMX05.js +35 -0
  74. package/dist/TeamNotesTab-BbODx7wS.js +7 -0
  75. package/dist/{TeamNotesTab-BzGZZ1h8.js → TeamNotesTab-DImzeVPk.js} +4 -4
  76. package/dist/{TeamNotesTab-BzGZZ1h8.js.map → TeamNotesTab-DImzeVPk.js.map} +1 -1
  77. package/dist/TeamParent-5lokhztw.js +35 -0
  78. package/dist/{TimelineNoteInput-0p-M4Qie.js → TimelineNoteInput-Cpnwnx7B.js} +2 -2
  79. package/dist/{TimelineNoteInput-0p-M4Qie.js.map → TimelineNoteInput-Cpnwnx7B.js.map} +1 -1
  80. package/dist/{TimelineSystemEvent-BHzFr46C.js → TimelineSystemEvent-BGG9WkQw.js} +4 -4
  81. package/dist/{TimelineSystemEvent-BHzFr46C.js.map → TimelineSystemEvent-BGG9WkQw.js.map} +1 -1
  82. package/dist/UserListPage-4hZll_PC.js +4 -0
  83. package/dist/{UserListPage-DUE5gJTo.js → UserListPage-DpkOdR1U.js} +2 -2
  84. package/dist/{UserListPage-DUE5gJTo.js.map → UserListPage-DpkOdR1U.js.map} +1 -1
  85. package/dist/{UserProfilePage-C3b93Keh.js → UserProfilePage-CWRgwGQH.js} +4 -4
  86. package/dist/{UserProfilePage-C3b93Keh.js.map → UserProfilePage-CWRgwGQH.js.map} +1 -1
  87. package/dist/UserProfilePage-qFrg3PiC.js +7 -0
  88. package/dist/VerifyEmail-C5EO8OFo.js +9 -0
  89. package/dist/{VerifyEmail-DlOmWGG-.js → VerifyEmail-DXZ4T5eN.js} +5 -5
  90. package/dist/{VerifyEmail-DlOmWGG-.js.map → VerifyEmail-DXZ4T5eN.js.map} +1 -1
  91. package/dist/ViewTeam-Die0SWa_.js +35 -0
  92. package/dist/ViewTeamMember-_sqrqGit.js +35 -0
  93. package/dist/index.d.ts +757 -757
  94. package/dist/index.js +25 -25
  95. package/dist/{src-QZJyMfGX.js → src-_IeDZXH6.js} +51 -51
  96. package/dist/{src-QZJyMfGX.js.map → src-_IeDZXH6.js.map} +1 -1
  97. package/dist/{useEmailVerificationChannel-BNi926Ho.js → useEmailVerificationChannel-BiiuuTUM.js} +2 -2
  98. package/dist/{useEmailVerificationChannel-BNi926Ho.js.map → useEmailVerificationChannel-BiiuuTUM.js.map} +1 -1
  99. package/dist/{useMutation-BTsyHKyn.js → useMutation-BMZJLpgx.js} +3 -3
  100. package/dist/{useMutation-BTsyHKyn.js.map → useMutation-BMZJLpgx.js.map} +1 -1
  101. package/dist/{useQuery-BggIE52P.js → useQuery-qpXzBuVg.js} +3 -3
  102. package/dist/{useQuery-BggIE52P.js.map → useQuery-qpXzBuVg.js.map} +1 -1
  103. package/dist/{useQueryCache-Bjm-S8v5.js → useQueryCache-DkRwK5Gz.js} +2 -2
  104. package/dist/{useQueryCache-Bjm-S8v5.js.map → useQueryCache-DkRwK5Gz.js.map} +1 -1
  105. package/dist/{useRpcAuth-rmHf7bYx.js → useRpcAuth-x5Gn5gR0.js} +17 -3
  106. package/dist/{useRpcAuth-rmHf7bYx.js.map → useRpcAuth-x5Gn5gR0.js.map} +1 -1
  107. package/package.json +2 -2
  108. package/dist/ChangePasswordPage-CpDPmEml.js +0 -6
  109. package/dist/CreateTeamForm-B4cIuYAf.js +0 -35
  110. package/dist/CreateTeamMemberForm-Chrw1y00.js +0 -35
  111. package/dist/CreateUserPage-WruMs7WP.js +0 -6
  112. package/dist/CreditBalanceDashboard-CkcsrZ_e.js +0 -35
  113. package/dist/CreditManagement-Ddvu9dMw.js +0 -35
  114. package/dist/CustomerCreateSupportTicketForm-BKperKGS.js +0 -35
  115. package/dist/CustomerSupportTicketList-DcbrjDa9.js +0 -35
  116. package/dist/CustomerSupportTicketParent-BeNzUwuP.js +0 -7
  117. package/dist/CustomerSupportTicketSuccess-CC967u3y.js +0 -35
  118. package/dist/EditTeamForm-B5Tee5wL.js +0 -35
  119. package/dist/EditTeamMemberForm-OtcS8QWt.js +0 -6
  120. package/dist/EditUserPage-T4DQlKhf.js +0 -7
  121. package/dist/ForgotPassword-CUifhmqP.js +0 -7
  122. package/dist/LoginForm-Bg7GoZEA.js +0 -7
  123. package/dist/Logout-Bs92csWH.js +0 -7
  124. package/dist/MfaSetup-BACX5XP-.js +0 -8
  125. package/dist/MfaVerify-ak4iSdQ2.js +0 -8
  126. package/dist/ResetPassword-pY1uhTdl.js +0 -7
  127. package/dist/Signup-Bq-G3D-s.js +0 -9
  128. package/dist/StaffCreateSupportTicketForm-D0ZuisDk.js +0 -35
  129. package/dist/StaffSupportTicketList-CiqC05XB.js +0 -35
  130. package/dist/StaffSupportTicketParent-DkV329NI.js +0 -7
  131. package/dist/StaffSupportTicketSuccess-CUYnimaI.js +0 -35
  132. package/dist/TeamAttachmentsTab-DUtCD1Yi.js +0 -35
  133. package/dist/TeamHistoryTab-BsUoH4VK.js +0 -4
  134. package/dist/TeamList-BkPIqZ8V.js +0 -35
  135. package/dist/TeamMemberList-1mxUGCNa.js +0 -35
  136. package/dist/TeamMemberParent-DzeBIElY.js +0 -35
  137. package/dist/TeamNotesTab-ClHl2nXd.js +0 -7
  138. package/dist/TeamParent-DJa9UZTP.js +0 -35
  139. package/dist/UserListPage-BTLE4J0s.js +0 -4
  140. package/dist/UserProfilePage-CVTORtSx.js +0 -7
  141. package/dist/VerifyEmail-DCP4DWIw.js +0 -9
  142. package/dist/ViewTeam-DVfnLMhV.js +0 -35
  143. package/dist/ViewTeamMember-L4v3gCIn.js +0 -35
@@ -1,4 +1,4 @@
1
- import { l as useUserSessionStore } from "./useRpcAuth-rmHf7bYx.js";
1
+ import { l as useUserSessionStore } from "./useRpcAuth-x5Gn5gR0.js";
2
2
  import { t as getAndClearEmailVerificationReturnUrl } from "./useReturnUrl-qFeazn-G.js";
3
3
  import { onUnmounted, watch } from "vue";
4
4
 
@@ -34,4 +34,4 @@ function useEmailVerificationChannel(awaitingVerification, onRedirect, getDefaul
34
34
 
35
35
  //#endregion
36
36
  export { useEmailVerificationChannel as t };
37
- //# sourceMappingURL=useEmailVerificationChannel-BNi926Ho.js.map
37
+ //# sourceMappingURL=useEmailVerificationChannel-BiiuuTUM.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEmailVerificationChannel-BNi926Ho.js","names":["authChannel: BroadcastChannel | null"],"sources":["../src/slices/auth/useEmailVerificationChannel.ts"],"sourcesContent":["import { useUserSessionStore } from '../../composables/useUserSessionStore';\nimport { getAndClearEmailVerificationReturnUrl } from '../../utils/useReturnUrl';\nimport { onUnmounted, watch } from 'vue';\nimport type { Ref } from 'vue';\n\nconst AUTH_CHANNEL = 'auth';\n\n/**\n * Listens for cross-tab email verification completion via BroadcastChannel.\n * When the user verifies their email in another tab, refreshes the session so this tab\n * has the updated email_verified state, then redirects to the stored return URL.\n * Call this when the signup form is showing \"awaiting verification\" state.\n */\nexport function useEmailVerificationChannel(\n awaitingVerification: Ref<boolean>,\n onRedirect: (targetUrl: string) => void,\n getDefaultRedirect: () => string,\n) {\n const sessionStore = useUserSessionStore();\n let authChannel: BroadcastChannel | null = null;\n\n watch(\n awaitingVerification,\n (isAwaiting) => {\n authChannel?.close();\n authChannel = null;\n if (!isAwaiting) return;\n authChannel = new BroadcastChannel(AUTH_CHANNEL);\n authChannel.onmessage = (event: MessageEvent<{ type: string }>) => {\n if (event.data?.type === 'email_verified') {\n const targetUrl =\n getAndClearEmailVerificationReturnUrl() ?? getDefaultRedirect();\n // Sync from localStorage so this tab has email_verified: true before redirect.\n // Tab B already wrote the new tokens; we just need to read them.\n sessionStore.syncFromStorage();\n onRedirect(targetUrl);\n }\n };\n },\n { immediate: true },\n );\n\n onUnmounted(() => {\n authChannel?.close();\n authChannel = null;\n });\n}\n"],"mappings":";;;;;AAKA,MAAM,eAAe;;;;;;;AAQrB,SAAgB,4BACd,sBACA,YACA,oBACA;CACA,MAAM,eAAe,qBAAqB;CAC1C,IAAIA,cAAuC;AAE3C,OACE,uBACC,eAAe;AACd,eAAa,OAAO;AACpB,gBAAc;AACd,MAAI,CAAC,WAAY;AACjB,gBAAc,IAAI,iBAAiB,aAAa;AAChD,cAAY,aAAa,UAA0C;AACjE,OAAI,MAAM,MAAM,SAAS,kBAAkB;IACzC,MAAM,YACJ,uCAAuC,IAAI,oBAAoB;AAGjE,iBAAa,iBAAiB;AAC9B,eAAW,UAAU;;;IAI3B,EAAE,WAAW,MAAM,CACpB;AAED,mBAAkB;AAChB,eAAa,OAAO;AACpB,gBAAc;GACd"}
1
+ {"version":3,"file":"useEmailVerificationChannel-BiiuuTUM.js","names":["authChannel: BroadcastChannel | null"],"sources":["../src/slices/auth/useEmailVerificationChannel.ts"],"sourcesContent":["import { useUserSessionStore } from '../../composables/useUserSessionStore';\nimport { getAndClearEmailVerificationReturnUrl } from '../../utils/useReturnUrl';\nimport { onUnmounted, watch } from 'vue';\nimport type { Ref } from 'vue';\n\nconst AUTH_CHANNEL = 'auth';\n\n/**\n * Listens for cross-tab email verification completion via BroadcastChannel.\n * When the user verifies their email in another tab, refreshes the session so this tab\n * has the updated email_verified state, then redirects to the stored return URL.\n * Call this when the signup form is showing \"awaiting verification\" state.\n */\nexport function useEmailVerificationChannel(\n awaitingVerification: Ref<boolean>,\n onRedirect: (targetUrl: string) => void,\n getDefaultRedirect: () => string,\n) {\n const sessionStore = useUserSessionStore();\n let authChannel: BroadcastChannel | null = null;\n\n watch(\n awaitingVerification,\n (isAwaiting) => {\n authChannel?.close();\n authChannel = null;\n if (!isAwaiting) return;\n authChannel = new BroadcastChannel(AUTH_CHANNEL);\n authChannel.onmessage = (event: MessageEvent<{ type: string }>) => {\n if (event.data?.type === 'email_verified') {\n const targetUrl =\n getAndClearEmailVerificationReturnUrl() ?? getDefaultRedirect();\n // Sync from localStorage so this tab has email_verified: true before redirect.\n // Tab B already wrote the new tokens; we just need to read them.\n sessionStore.syncFromStorage();\n onRedirect(targetUrl);\n }\n };\n },\n { immediate: true },\n );\n\n onUnmounted(() => {\n authChannel?.close();\n authChannel = null;\n });\n}\n"],"mappings":";;;;;AAKA,MAAM,eAAe;;;;;;;AAQrB,SAAgB,4BACd,sBACA,YACA,oBACA;CACA,MAAM,eAAe,qBAAqB;CAC1C,IAAIA,cAAuC;AAE3C,OACE,uBACC,eAAe;AACd,eAAa,OAAO;AACpB,gBAAc;AACd,MAAI,CAAC,WAAY;AACjB,gBAAc,IAAI,iBAAiB,aAAa;AAChD,cAAY,aAAa,UAA0C;AACjE,OAAI,MAAM,MAAM,SAAS,kBAAkB;IACzC,MAAM,YACJ,uCAAuC,IAAI,oBAAoB;AAGjE,iBAAa,iBAAiB;AAC9B,eAAW,UAAU;;;IAI3B,EAAE,WAAW,MAAM,CACpB;AAED,mBAAkB;AAChB,eAAa,OAAO;AACpB,gBAAc;GACd"}
@@ -1,5 +1,5 @@
1
- import { r as executeWithAuth, s as getRefreshTokenHandler } from "./useRpcAuth-rmHf7bYx.js";
2
- import { t as queryCache } from "./useQueryCache-Bjm-S8v5.js";
1
+ import { r as executeWithAuth, s as getRefreshTokenHandler } from "./useRpcAuth-x5Gn5gR0.js";
2
+ import { t as queryCache } from "./useQueryCache-DkRwK5Gz.js";
3
3
  import { shallowRef } from "vue";
4
4
 
5
5
  //#region src/composables/useMutation.ts
@@ -47,4 +47,4 @@ function useMutation(mutationFn, options) {
47
47
 
48
48
  //#endregion
49
49
  export { useMutation as t };
50
- //# sourceMappingURL=useMutation-BTsyHKyn.js.map
50
+ //# sourceMappingURL=useMutation-BMZJLpgx.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useMutation-BTsyHKyn.js","names":[],"sources":["../src/composables/useMutation.ts"],"sourcesContent":["import type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport { shallowRef, type ShallowRef } from 'vue';\nimport { getRefreshTokenHandler } from '../utils/EnhancedRefreshTokenHandler';\nimport type { MutationFunction, UseMutationOptions } from './types';\nimport { queryCache } from './useQueryCache';\nimport { executeWithAuth } from './useRpcAuth';\n\nexport interface UseMutationReturn<TInput, TOutput> {\n data: ShallowRef<TOutput | null>;\n loading: ShallowRef<boolean>;\n error: ShallowRef<Error | null>;\n mutate: (input: TInput) => Promise<TOutput>;\n reset: () => void;\n}\n\nexport function useMutation<\n TApi extends Record<string, any> = DragoncoreApi,\n TInput = any,\n TOutput = any,\n>(\n mutationFn: MutationFunction<TApi, TInput, TOutput>,\n options?: UseMutationOptions<TInput, TOutput>,\n): UseMutationReturn<TInput, TOutput> {\n // Get the global refresh token handler - Dragoncore handles this automatically\n const refreshTokenHandler = getRefreshTokenHandler();\n const loading = shallowRef(false);\n const error = shallowRef<Error | null>(null);\n const data = shallowRef<TOutput | null>(null);\n\n const mutate = async (input: TInput): Promise<TOutput> => {\n loading.value = true;\n error.value = null;\n\n try {\n // Skip auth check for public endpoints (signup) or login/logout operations\n const skipAuthCheck = options?.skipAuthCheck || options?.credentials === 'include';\n const result = await executeWithAuth<TApi, TOutput>(\n (batch) => mutationFn(batch, input),\n {\n credentials: options?.credentials,\n skipAuthCheck,\n refreshTokenHandler,\n },\n );\n data.value = result;\n\n // Invalidate related queries\n if (options?.invalidate) {\n if (Array.isArray(options.invalidate)) {\n options.invalidate.forEach((key) => queryCache.invalidate(key));\n } else {\n queryCache.invalidate(options.invalidate);\n }\n }\n\n // Call success callback\n if (options?.onSuccess) {\n options.onSuccess(result, input);\n }\n\n return result;\n } catch (e) {\n error.value = e instanceof Error ? e : new Error('Unknown error');\n\n // Call error callback\n if (options?.onError) {\n options.onError(error.value, input);\n }\n\n throw e;\n } finally {\n loading.value = false;\n }\n };\n\n const reset = () => {\n data.value = null;\n error.value = null;\n loading.value = false;\n };\n\n return { mutate, loading, error, data, reset };\n}\n"],"mappings":";;;;;AAeA,SAAgB,YAKd,YACA,SACoC;CAEpC,MAAM,sBAAsB,wBAAwB;CACpD,MAAM,UAAU,WAAW,MAAM;CACjC,MAAM,QAAQ,WAAyB,KAAK;CAC5C,MAAM,OAAO,WAA2B,KAAK;CAE7C,MAAM,SAAS,OAAO,UAAoC;AACxD,UAAQ,QAAQ;AAChB,QAAM,QAAQ;AAEd,MAAI;GAEF,MAAM,gBAAgB,SAAS,iBAAiB,SAAS,gBAAgB;GACzE,MAAM,SAAS,MAAM,iBAClB,UAAU,WAAW,OAAO,MAAM,EACnC;IACE,aAAa,SAAS;IACtB;IACA;IACD,CACF;AACD,QAAK,QAAQ;AAGb,OAAI,SAAS,WACX,KAAI,MAAM,QAAQ,QAAQ,WAAW,CACnC,SAAQ,WAAW,SAAS,QAAQ,WAAW,WAAW,IAAI,CAAC;OAE/D,YAAW,WAAW,QAAQ,WAAW;AAK7C,OAAI,SAAS,UACX,SAAQ,UAAU,QAAQ,MAAM;AAGlC,UAAO;WACA,GAAG;AACV,SAAM,QAAQ,aAAa,QAAQ,oBAAI,IAAI,MAAM,gBAAgB;AAGjE,OAAI,SAAS,QACX,SAAQ,QAAQ,MAAM,OAAO,MAAM;AAGrC,SAAM;YACE;AACR,WAAQ,QAAQ;;;CAIpB,MAAM,cAAc;AAClB,OAAK,QAAQ;AACb,QAAM,QAAQ;AACd,UAAQ,QAAQ;;AAGlB,QAAO;EAAE;EAAQ;EAAS;EAAO;EAAM;EAAO"}
1
+ {"version":3,"file":"useMutation-BMZJLpgx.js","names":[],"sources":["../src/composables/useMutation.ts"],"sourcesContent":["import type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport { shallowRef, type ShallowRef } from 'vue';\nimport { getRefreshTokenHandler } from '../utils/EnhancedRefreshTokenHandler';\nimport type { MutationFunction, UseMutationOptions } from './types';\nimport { queryCache } from './useQueryCache';\nimport { executeWithAuth } from './useRpcAuth';\n\nexport interface UseMutationReturn<TInput, TOutput> {\n data: ShallowRef<TOutput | null>;\n loading: ShallowRef<boolean>;\n error: ShallowRef<Error | null>;\n mutate: (input: TInput) => Promise<TOutput>;\n reset: () => void;\n}\n\nexport function useMutation<\n TApi extends Record<string, any> = DragoncoreApi,\n TInput = any,\n TOutput = any,\n>(\n mutationFn: MutationFunction<TApi, TInput, TOutput>,\n options?: UseMutationOptions<TInput, TOutput>,\n): UseMutationReturn<TInput, TOutput> {\n // Get the global refresh token handler - Dragoncore handles this automatically\n const refreshTokenHandler = getRefreshTokenHandler();\n const loading = shallowRef(false);\n const error = shallowRef<Error | null>(null);\n const data = shallowRef<TOutput | null>(null);\n\n const mutate = async (input: TInput): Promise<TOutput> => {\n loading.value = true;\n error.value = null;\n\n try {\n // Skip auth check for public endpoints (signup) or login/logout operations\n const skipAuthCheck = options?.skipAuthCheck || options?.credentials === 'include';\n const result = await executeWithAuth<TApi, TOutput>(\n (batch) => mutationFn(batch, input),\n {\n credentials: options?.credentials,\n skipAuthCheck,\n refreshTokenHandler,\n },\n );\n data.value = result;\n\n // Invalidate related queries\n if (options?.invalidate) {\n if (Array.isArray(options.invalidate)) {\n options.invalidate.forEach((key) => queryCache.invalidate(key));\n } else {\n queryCache.invalidate(options.invalidate);\n }\n }\n\n // Call success callback\n if (options?.onSuccess) {\n options.onSuccess(result, input);\n }\n\n return result;\n } catch (e) {\n error.value = e instanceof Error ? e : new Error('Unknown error');\n\n // Call error callback\n if (options?.onError) {\n options.onError(error.value, input);\n }\n\n throw e;\n } finally {\n loading.value = false;\n }\n };\n\n const reset = () => {\n data.value = null;\n error.value = null;\n loading.value = false;\n };\n\n return { mutate, loading, error, data, reset };\n}\n"],"mappings":";;;;;AAeA,SAAgB,YAKd,YACA,SACoC;CAEpC,MAAM,sBAAsB,wBAAwB;CACpD,MAAM,UAAU,WAAW,MAAM;CACjC,MAAM,QAAQ,WAAyB,KAAK;CAC5C,MAAM,OAAO,WAA2B,KAAK;CAE7C,MAAM,SAAS,OAAO,UAAoC;AACxD,UAAQ,QAAQ;AAChB,QAAM,QAAQ;AAEd,MAAI;GAEF,MAAM,gBAAgB,SAAS,iBAAiB,SAAS,gBAAgB;GACzE,MAAM,SAAS,MAAM,iBAClB,UAAU,WAAW,OAAO,MAAM,EACnC;IACE,aAAa,SAAS;IACtB;IACA;IACD,CACF;AACD,QAAK,QAAQ;AAGb,OAAI,SAAS,WACX,KAAI,MAAM,QAAQ,QAAQ,WAAW,CACnC,SAAQ,WAAW,SAAS,QAAQ,WAAW,WAAW,IAAI,CAAC;OAE/D,YAAW,WAAW,QAAQ,WAAW;AAK7C,OAAI,SAAS,UACX,SAAQ,UAAU,QAAQ,MAAM;AAGlC,UAAO;WACA,GAAG;AACV,SAAM,QAAQ,aAAa,QAAQ,oBAAI,IAAI,MAAM,gBAAgB;AAGjE,OAAI,SAAS,QACX,SAAQ,QAAQ,MAAM,OAAO,MAAM;AAGrC,SAAM;YACE;AACR,WAAQ,QAAQ;;;CAIpB,MAAM,cAAc;AAClB,OAAK,QAAQ;AACb,QAAM,QAAQ;AACd,UAAQ,QAAQ;;AAGlB,QAAO;EAAE;EAAQ;EAAS;EAAO;EAAM;EAAO"}
@@ -1,5 +1,5 @@
1
- import { f as logIfEnabled, r as executeWithAuth, s as getRefreshTokenHandler } from "./useRpcAuth-rmHf7bYx.js";
2
- import { t as queryCache } from "./useQueryCache-Bjm-S8v5.js";
1
+ import { f as logIfEnabled, r as executeWithAuth, s as getRefreshTokenHandler } from "./useRpcAuth-x5Gn5gR0.js";
2
+ import { t as queryCache } from "./useQueryCache-DkRwK5Gz.js";
3
3
  import { onMounted, onUnmounted, shallowRef, watch } from "vue";
4
4
 
5
5
  //#region src/composables/useQuery.ts
@@ -104,4 +104,4 @@ function useQuery(queryFn, options) {
104
104
 
105
105
  //#endregion
106
106
  export { useQuery as t };
107
- //# sourceMappingURL=useQuery-BggIE52P.js.map
107
+ //# sourceMappingURL=useQuery-qpXzBuVg.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useQuery-BggIE52P.js","names":[],"sources":["../src/composables/useQuery.ts"],"sourcesContent":["import type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport { onMounted, onUnmounted, shallowRef, type ShallowRef, watch } from 'vue';\nimport { getRefreshTokenHandler } from '../utils/EnhancedRefreshTokenHandler';\nimport { logIfEnabled } from '../utils/logger';\nimport type { QueryFunction, UseQueryOptions } from './types';\nimport { queryCache } from './useQueryCache';\nimport { executeWithAuth } from './useRpcAuth';\n\nexport interface UseQueryReturn<T> {\n data: ShallowRef<T | null>;\n loading: ShallowRef<boolean>;\n error: ShallowRef<Error | null>;\n dataUpdatedAt: ShallowRef<number>;\n execute: () => Promise<void>;\n refetch: () => Promise<void>;\n}\n\nexport function useQuery<TApi extends Record<string, any> = DragoncoreApi, T = any>(\n queryFn: QueryFunction<TApi, T>,\n options?: UseQueryOptions,\n): UseQueryReturn<T> {\n // Get the global refresh token handler - Dragoncore handles this automatically\n const refreshTokenHandler = getRefreshTokenHandler();\n\n const data = shallowRef<T | null>(null);\n const loading = shallowRef(options?.immediate !== false);\n const error = shallowRef<Error | null>(null);\n const dataUpdatedAt = shallowRef<number>(0);\n // Internal flag to prevent duplicate background fetches (not exposed to consumers)\n let isBackgroundFetching = false;\n // Default debug to false if not specified\n const debug = options?.debug ?? false;\n // Default persist to true when cacheKey is provided (localStorage persistence is default)\n // Set persist: false to disable localStorage persistence (in-memory caching still works)\n const persist = options?.persist ?? (options?.cacheKey ? true : false);\n\n const execute = async (skipCache = false) => {\n const isEnabled =\n typeof options?.enabled === 'boolean'\n ? options?.enabled\n : (options?.enabled?.value ?? true);\n\n if (!isEnabled) {\n loading.value = false;\n return;\n }\n\n loading.value = true;\n error.value = null;\n\n // Check cache first (unless explicitly skipping)\n if (options?.cacheKey && !skipCache) {\n const cached = queryCache.get<T>(options.cacheKey, {\n staleTime: options?.staleTime,\n persist: persist,\n debug: debug,\n });\n\n if (cached !== null) {\n logIfEnabled('debug', `[Query] Cache HIT: ${options.cacheKey}`, debug);\n data.value = cached;\n loading.value = false;\n\n // Optionally fetch fresh data in background if refetchOnWindowFocus\n if (options?.refetchOnWindowFocus) {\n executeInBackground();\n }\n return;\n }\n logIfEnabled('debug', `[Query] Cache MISS: ${options.cacheKey}`, debug);\n }\n\n try {\n const result = await executeWithAuth<TApi, T>((batch) => queryFn(batch), {\n credentials: options?.credentials,\n skipAuthCheck: options?.skipAuthCheck ?? false,\n mode: options?.batchMode,\n trackedSegment: options?.trackedSegment, // Pass through the tracked segment\n refreshTokenHandler,\n });\n data.value = result;\n dataUpdatedAt.value = Date.now();\n\n // Cache the result\n if (options?.cacheKey) {\n queryCache.set(options.cacheKey, result, {\n staleTime: options?.staleTime,\n persist: persist,\n debug: options?.debug,\n });\n }\n } catch (e) {\n error.value = e instanceof Error ? e : new Error('Unknown error');\n data.value = null;\n } finally {\n loading.value = false;\n }\n };\n\n const executeInBackground = async () => {\n if (isBackgroundFetching || loading.value) return; // Don't fetch if already fetching\n\n isBackgroundFetching = true;\n try {\n const result = await executeWithAuth<TApi, T>((batch) => queryFn(batch), {\n credentials: options?.credentials,\n skipAuthCheck: options?.skipAuthCheck ?? false,\n mode: options?.batchMode ? 'batch' : 'tracked',\n trackedSegment: options?.trackedSegment, // Pass through the tracked segment\n refreshTokenHandler,\n });\n data.value = result;\n dataUpdatedAt.value = Date.now();\n\n if (options?.cacheKey) {\n queryCache.set(options.cacheKey, result, {\n staleTime: options?.staleTime,\n persist: persist,\n debug: debug,\n });\n }\n } catch (e) {\n // Silent failure for background refetch\n logIfEnabled('error', '[Query] Background refetch failed:', debug, e);\n } finally {\n isBackgroundFetching = false;\n }\n };\n\n // Auto-execute on mount\n if (options?.immediate !== false) {\n onMounted(execute);\n }\n\n // Refetch on window focus\n if (options?.refetchOnWindowFocus) {\n const handleFocus = () => {\n if (data.value !== null) {\n executeInBackground();\n }\n };\n onMounted(() => window.addEventListener('focus', handleFocus));\n onUnmounted(() => window.removeEventListener('focus', handleFocus));\n }\n\n // Watch for changes\n if (options?.watch) {\n const watchTargets = Array.isArray(options.watch) ? options.watch : [options.watch];\n watch(watchTargets, () => execute());\n }\n\n // Watch enabled state\n if (options?.enabled && typeof options?.enabled !== 'boolean') {\n watch(options?.enabled, (isEnabled) => {\n if (isEnabled) execute();\n });\n }\n\n return {\n data,\n loading,\n error,\n dataUpdatedAt,\n execute: () => execute(),\n refetch: () => execute(true), // Skip cache on manual refetch\n };\n}\n"],"mappings":";;;;;AAiBA,SAAgB,SACd,SACA,SACmB;CAEnB,MAAM,sBAAsB,wBAAwB;CAEpD,MAAM,OAAO,WAAqB,KAAK;CACvC,MAAM,UAAU,WAAW,SAAS,cAAc,MAAM;CACxD,MAAM,QAAQ,WAAyB,KAAK;CAC5C,MAAM,gBAAgB,WAAmB,EAAE;CAE3C,IAAI,uBAAuB;CAE3B,MAAM,QAAQ,SAAS,SAAS;CAGhC,MAAM,UAAU,SAAS,YAAY,SAAS,WAAW,OAAO;CAEhE,MAAM,UAAU,OAAO,YAAY,UAAU;AAM3C,MAAI,EAJF,OAAO,SAAS,YAAY,YACxB,SAAS,UACR,SAAS,SAAS,SAAS,OAElB;AACd,WAAQ,QAAQ;AAChB;;AAGF,UAAQ,QAAQ;AAChB,QAAM,QAAQ;AAGd,MAAI,SAAS,YAAY,CAAC,WAAW;GACnC,MAAM,SAAS,WAAW,IAAO,QAAQ,UAAU;IACjD,WAAW,SAAS;IACX;IACF;IACR,CAAC;AAEF,OAAI,WAAW,MAAM;AACnB,iBAAa,SAAS,sBAAsB,QAAQ,YAAY,MAAM;AACtE,SAAK,QAAQ;AACb,YAAQ,QAAQ;AAGhB,QAAI,SAAS,qBACX,sBAAqB;AAEvB;;AAEF,gBAAa,SAAS,uBAAuB,QAAQ,YAAY,MAAM;;AAGzE,MAAI;GACF,MAAM,SAAS,MAAM,iBAA0B,UAAU,QAAQ,MAAM,EAAE;IACvE,aAAa,SAAS;IACtB,eAAe,SAAS,iBAAiB;IACzC,MAAM,SAAS;IACf,gBAAgB,SAAS;IACzB;IACD,CAAC;AACF,QAAK,QAAQ;AACb,iBAAc,QAAQ,KAAK,KAAK;AAGhC,OAAI,SAAS,SACX,YAAW,IAAI,QAAQ,UAAU,QAAQ;IACvC,WAAW,SAAS;IACX;IACT,OAAO,SAAS;IACjB,CAAC;WAEG,GAAG;AACV,SAAM,QAAQ,aAAa,QAAQ,oBAAI,IAAI,MAAM,gBAAgB;AACjE,QAAK,QAAQ;YACL;AACR,WAAQ,QAAQ;;;CAIpB,MAAM,sBAAsB,YAAY;AACtC,MAAI,wBAAwB,QAAQ,MAAO;AAE3C,yBAAuB;AACvB,MAAI;GACF,MAAM,SAAS,MAAM,iBAA0B,UAAU,QAAQ,MAAM,EAAE;IACvE,aAAa,SAAS;IACtB,eAAe,SAAS,iBAAiB;IACzC,MAAM,SAAS,YAAY,UAAU;IACrC,gBAAgB,SAAS;IACzB;IACD,CAAC;AACF,QAAK,QAAQ;AACb,iBAAc,QAAQ,KAAK,KAAK;AAEhC,OAAI,SAAS,SACX,YAAW,IAAI,QAAQ,UAAU,QAAQ;IACvC,WAAW,SAAS;IACX;IACF;IACR,CAAC;WAEG,GAAG;AAEV,gBAAa,SAAS,sCAAsC,OAAO,EAAE;YAC7D;AACR,0BAAuB;;;AAK3B,KAAI,SAAS,cAAc,MACzB,WAAU,QAAQ;AAIpB,KAAI,SAAS,sBAAsB;EACjC,MAAM,oBAAoB;AACxB,OAAI,KAAK,UAAU,KACjB,sBAAqB;;AAGzB,kBAAgB,OAAO,iBAAiB,SAAS,YAAY,CAAC;AAC9D,oBAAkB,OAAO,oBAAoB,SAAS,YAAY,CAAC;;AAIrE,KAAI,SAAS,MAEX,OADqB,MAAM,QAAQ,QAAQ,MAAM,GAAG,QAAQ,QAAQ,CAAC,QAAQ,MAAM,QACzD,SAAS,CAAC;AAItC,KAAI,SAAS,WAAW,OAAO,SAAS,YAAY,UAClD,OAAM,SAAS,UAAU,cAAc;AACrC,MAAI,UAAW,UAAS;GACxB;AAGJ,QAAO;EACL;EACA;EACA;EACA;EACA,eAAe,SAAS;EACxB,eAAe,QAAQ,KAAK;EAC7B"}
1
+ {"version":3,"file":"useQuery-qpXzBuVg.js","names":[],"sources":["../src/composables/useQuery.ts"],"sourcesContent":["import type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport { onMounted, onUnmounted, shallowRef, type ShallowRef, watch } from 'vue';\nimport { getRefreshTokenHandler } from '../utils/EnhancedRefreshTokenHandler';\nimport { logIfEnabled } from '../utils/logger';\nimport type { QueryFunction, UseQueryOptions } from './types';\nimport { queryCache } from './useQueryCache';\nimport { executeWithAuth } from './useRpcAuth';\n\nexport interface UseQueryReturn<T> {\n data: ShallowRef<T | null>;\n loading: ShallowRef<boolean>;\n error: ShallowRef<Error | null>;\n dataUpdatedAt: ShallowRef<number>;\n execute: () => Promise<void>;\n refetch: () => Promise<void>;\n}\n\nexport function useQuery<TApi extends Record<string, any> = DragoncoreApi, T = any>(\n queryFn: QueryFunction<TApi, T>,\n options?: UseQueryOptions,\n): UseQueryReturn<T> {\n // Get the global refresh token handler - Dragoncore handles this automatically\n const refreshTokenHandler = getRefreshTokenHandler();\n\n const data = shallowRef<T | null>(null);\n const loading = shallowRef(options?.immediate !== false);\n const error = shallowRef<Error | null>(null);\n const dataUpdatedAt = shallowRef<number>(0);\n // Internal flag to prevent duplicate background fetches (not exposed to consumers)\n let isBackgroundFetching = false;\n // Default debug to false if not specified\n const debug = options?.debug ?? false;\n // Default persist to true when cacheKey is provided (localStorage persistence is default)\n // Set persist: false to disable localStorage persistence (in-memory caching still works)\n const persist = options?.persist ?? (options?.cacheKey ? true : false);\n\n const execute = async (skipCache = false) => {\n const isEnabled =\n typeof options?.enabled === 'boolean'\n ? options?.enabled\n : (options?.enabled?.value ?? true);\n\n if (!isEnabled) {\n loading.value = false;\n return;\n }\n\n loading.value = true;\n error.value = null;\n\n // Check cache first (unless explicitly skipping)\n if (options?.cacheKey && !skipCache) {\n const cached = queryCache.get<T>(options.cacheKey, {\n staleTime: options?.staleTime,\n persist: persist,\n debug: debug,\n });\n\n if (cached !== null) {\n logIfEnabled('debug', `[Query] Cache HIT: ${options.cacheKey}`, debug);\n data.value = cached;\n loading.value = false;\n\n // Optionally fetch fresh data in background if refetchOnWindowFocus\n if (options?.refetchOnWindowFocus) {\n executeInBackground();\n }\n return;\n }\n logIfEnabled('debug', `[Query] Cache MISS: ${options.cacheKey}`, debug);\n }\n\n try {\n const result = await executeWithAuth<TApi, T>((batch) => queryFn(batch), {\n credentials: options?.credentials,\n skipAuthCheck: options?.skipAuthCheck ?? false,\n mode: options?.batchMode,\n trackedSegment: options?.trackedSegment, // Pass through the tracked segment\n refreshTokenHandler,\n });\n data.value = result;\n dataUpdatedAt.value = Date.now();\n\n // Cache the result\n if (options?.cacheKey) {\n queryCache.set(options.cacheKey, result, {\n staleTime: options?.staleTime,\n persist: persist,\n debug: options?.debug,\n });\n }\n } catch (e) {\n error.value = e instanceof Error ? e : new Error('Unknown error');\n data.value = null;\n } finally {\n loading.value = false;\n }\n };\n\n const executeInBackground = async () => {\n if (isBackgroundFetching || loading.value) return; // Don't fetch if already fetching\n\n isBackgroundFetching = true;\n try {\n const result = await executeWithAuth<TApi, T>((batch) => queryFn(batch), {\n credentials: options?.credentials,\n skipAuthCheck: options?.skipAuthCheck ?? false,\n mode: options?.batchMode ? 'batch' : 'tracked',\n trackedSegment: options?.trackedSegment, // Pass through the tracked segment\n refreshTokenHandler,\n });\n data.value = result;\n dataUpdatedAt.value = Date.now();\n\n if (options?.cacheKey) {\n queryCache.set(options.cacheKey, result, {\n staleTime: options?.staleTime,\n persist: persist,\n debug: debug,\n });\n }\n } catch (e) {\n // Silent failure for background refetch\n logIfEnabled('error', '[Query] Background refetch failed:', debug, e);\n } finally {\n isBackgroundFetching = false;\n }\n };\n\n // Auto-execute on mount\n if (options?.immediate !== false) {\n onMounted(execute);\n }\n\n // Refetch on window focus\n if (options?.refetchOnWindowFocus) {\n const handleFocus = () => {\n if (data.value !== null) {\n executeInBackground();\n }\n };\n onMounted(() => window.addEventListener('focus', handleFocus));\n onUnmounted(() => window.removeEventListener('focus', handleFocus));\n }\n\n // Watch for changes\n if (options?.watch) {\n const watchTargets = Array.isArray(options.watch) ? options.watch : [options.watch];\n watch(watchTargets, () => execute());\n }\n\n // Watch enabled state\n if (options?.enabled && typeof options?.enabled !== 'boolean') {\n watch(options?.enabled, (isEnabled) => {\n if (isEnabled) execute();\n });\n }\n\n return {\n data,\n loading,\n error,\n dataUpdatedAt,\n execute: () => execute(),\n refetch: () => execute(true), // Skip cache on manual refetch\n };\n}\n"],"mappings":";;;;;AAiBA,SAAgB,SACd,SACA,SACmB;CAEnB,MAAM,sBAAsB,wBAAwB;CAEpD,MAAM,OAAO,WAAqB,KAAK;CACvC,MAAM,UAAU,WAAW,SAAS,cAAc,MAAM;CACxD,MAAM,QAAQ,WAAyB,KAAK;CAC5C,MAAM,gBAAgB,WAAmB,EAAE;CAE3C,IAAI,uBAAuB;CAE3B,MAAM,QAAQ,SAAS,SAAS;CAGhC,MAAM,UAAU,SAAS,YAAY,SAAS,WAAW,OAAO;CAEhE,MAAM,UAAU,OAAO,YAAY,UAAU;AAM3C,MAAI,EAJF,OAAO,SAAS,YAAY,YACxB,SAAS,UACR,SAAS,SAAS,SAAS,OAElB;AACd,WAAQ,QAAQ;AAChB;;AAGF,UAAQ,QAAQ;AAChB,QAAM,QAAQ;AAGd,MAAI,SAAS,YAAY,CAAC,WAAW;GACnC,MAAM,SAAS,WAAW,IAAO,QAAQ,UAAU;IACjD,WAAW,SAAS;IACX;IACF;IACR,CAAC;AAEF,OAAI,WAAW,MAAM;AACnB,iBAAa,SAAS,sBAAsB,QAAQ,YAAY,MAAM;AACtE,SAAK,QAAQ;AACb,YAAQ,QAAQ;AAGhB,QAAI,SAAS,qBACX,sBAAqB;AAEvB;;AAEF,gBAAa,SAAS,uBAAuB,QAAQ,YAAY,MAAM;;AAGzE,MAAI;GACF,MAAM,SAAS,MAAM,iBAA0B,UAAU,QAAQ,MAAM,EAAE;IACvE,aAAa,SAAS;IACtB,eAAe,SAAS,iBAAiB;IACzC,MAAM,SAAS;IACf,gBAAgB,SAAS;IACzB;IACD,CAAC;AACF,QAAK,QAAQ;AACb,iBAAc,QAAQ,KAAK,KAAK;AAGhC,OAAI,SAAS,SACX,YAAW,IAAI,QAAQ,UAAU,QAAQ;IACvC,WAAW,SAAS;IACX;IACT,OAAO,SAAS;IACjB,CAAC;WAEG,GAAG;AACV,SAAM,QAAQ,aAAa,QAAQ,oBAAI,IAAI,MAAM,gBAAgB;AACjE,QAAK,QAAQ;YACL;AACR,WAAQ,QAAQ;;;CAIpB,MAAM,sBAAsB,YAAY;AACtC,MAAI,wBAAwB,QAAQ,MAAO;AAE3C,yBAAuB;AACvB,MAAI;GACF,MAAM,SAAS,MAAM,iBAA0B,UAAU,QAAQ,MAAM,EAAE;IACvE,aAAa,SAAS;IACtB,eAAe,SAAS,iBAAiB;IACzC,MAAM,SAAS,YAAY,UAAU;IACrC,gBAAgB,SAAS;IACzB;IACD,CAAC;AACF,QAAK,QAAQ;AACb,iBAAc,QAAQ,KAAK,KAAK;AAEhC,OAAI,SAAS,SACX,YAAW,IAAI,QAAQ,UAAU,QAAQ;IACvC,WAAW,SAAS;IACX;IACF;IACR,CAAC;WAEG,GAAG;AAEV,gBAAa,SAAS,sCAAsC,OAAO,EAAE;YAC7D;AACR,0BAAuB;;;AAK3B,KAAI,SAAS,cAAc,MACzB,WAAU,QAAQ;AAIpB,KAAI,SAAS,sBAAsB;EACjC,MAAM,oBAAoB;AACxB,OAAI,KAAK,UAAU,KACjB,sBAAqB;;AAGzB,kBAAgB,OAAO,iBAAiB,SAAS,YAAY,CAAC;AAC9D,oBAAkB,OAAO,oBAAoB,SAAS,YAAY,CAAC;;AAIrE,KAAI,SAAS,MAEX,OADqB,MAAM,QAAQ,QAAQ,MAAM,GAAG,QAAQ,QAAQ,CAAC,QAAQ,MAAM,QACzD,SAAS,CAAC;AAItC,KAAI,SAAS,WAAW,OAAO,SAAS,YAAY,UAClD,OAAM,SAAS,UAAU,cAAc;AACrC,MAAI,UAAW,UAAS;GACxB;AAGJ,QAAO;EACL;EACA;EACA;EACA;EACA,eAAe,SAAS;EACxB,eAAe,QAAQ,KAAK;EAC7B"}
@@ -1,4 +1,4 @@
1
- import { f as logIfEnabled, p as logger } from "./useRpcAuth-rmHf7bYx.js";
1
+ import { f as logIfEnabled, p as logger } from "./useRpcAuth-x5Gn5gR0.js";
2
2
 
3
3
  //#region src/composables/useQueryCache.ts
4
4
  var QueryCache = class {
@@ -251,4 +251,4 @@ if (import.meta.env.DEV) {
251
251
 
252
252
  //#endregion
253
253
  export { queryCache as t };
254
- //# sourceMappingURL=useQueryCache-Bjm-S8v5.js.map
254
+ //# sourceMappingURL=useQueryCache-DkRwK5Gz.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useQueryCache-Bjm-S8v5.js","names":["keysToRemove: string[]","entry: CacheEntry<T>","entries: Record<\n string,\n {\n data: any;\n ageMs: number;\n expiresInMs: number;\n isExpired: boolean;\n source: 'memory' | 'storage';\n }\n >","entries: [string, number][]"],"sources":["../src/composables/useQueryCache.ts"],"sourcesContent":["import { logger, logIfEnabled } from '../utils/logger';\n\ninterface CacheEntry<T> {\n data: T;\n timestamp: number;\n expiresAt: number;\n}\n\ninterface CacheOptions {\n staleTime?: number; // How long data is fresh (ms), default 5 minutes\n persist?: boolean; // Save to localStorage\n debug?: boolean; // Enable/disable debug logging for this cache operation (default: false)\n}\n\nclass QueryCache {\n private memoryCache = new Map<string, CacheEntry<any>>();\n private readonly BUILD_TAG = import.meta.env.VITE_BUILD_TAG || 'dev';\n private readonly STORAGE_PREFIX = `rpc-cache:${this.BUILD_TAG}:`;\n private readonly BUILD_TAG_KEY = 'rpc-cache-build-tag';\n private cleanupTimers = new Map<string, number>();\n\n constructor() {\n // Check if this is a new deployment and clear old cache\n this.handleDeploymentChange();\n\n // Clean up expired localStorage entries on init\n this.cleanExpiredStorage();\n }\n\n /**\n * Detect deployment changes and clear old cache\n */\n private handleDeploymentChange() {\n const lastBuildTag = localStorage.getItem(this.BUILD_TAG_KEY);\n\n // If build tag is missing, clear all cache (first load or manual clear)\n if (!lastBuildTag) {\n // Use global log level for deployment change detection\n logger.debug('[Cache] Build tag missing - clearing all cache');\n this.clearAllStorage();\n }\n // If deployment changed, clear old cache from previous build\n else if (lastBuildTag !== this.BUILD_TAG) {\n // Use global log level for deployment change detection\n logger.debug(`[Cache] New deployment detected: ${lastBuildTag} → ${this.BUILD_TAG}`);\n logger.debug('[Cache] Clearing old cache from previous deployment');\n\n // Clear all old cache entries (from previous build tag)\n this.clearAllOldDeploymentCache(lastBuildTag);\n }\n\n // Store current build tag\n localStorage.setItem(this.BUILD_TAG_KEY, this.BUILD_TAG);\n }\n\n /**\n * Clear cache from previous deployment\n */\n private clearAllOldDeploymentCache(oldBuildTag: string) {\n const oldPrefix = `rpc-cache:${oldBuildTag}:`;\n const keysToRemove: string[] = [];\n\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(oldPrefix)) {\n keysToRemove.push(key);\n }\n }\n\n keysToRemove.forEach((key) => localStorage.removeItem(key));\n\n if (keysToRemove.length > 0) {\n // Use global log level for deployment change detection\n logger.debug(`[Cache] Removed ${keysToRemove.length} entries from previous deployment`);\n }\n }\n\n /**\n * Get data from cache (memory first, then localStorage if persist enabled)\n */\n get<T>(key: string, options: CacheOptions = {}): T | null {\n const now = Date.now();\n const debug = options.debug ?? false;\n\n // 1. Try memory cache first\n const memoryEntry = this.memoryCache.get(key);\n if (memoryEntry) {\n if (now < memoryEntry.expiresAt) {\n return memoryEntry.data as T;\n }\n // Expired in memory\n this.memoryCache.delete(key);\n }\n\n // 2. Try localStorage if persist is enabled\n if (options.persist) {\n const storageEntry = this.getFromStorage<T>(key, debug);\n if (storageEntry) {\n if (now < storageEntry.expiresAt) {\n // Rehydrate to memory cache\n this.memoryCache.set(key, storageEntry);\n return storageEntry.data;\n }\n // Expired in storage\n this.removeFromStorage(key);\n }\n }\n\n return null;\n }\n\n /**\n * Set data in cache (memory and optionally localStorage)\n */\n set<T>(key: string, data: T, options: CacheOptions = {}) {\n const staleTime = options.staleTime ?? 300000; // Default 5 minutes\n const debug = options.debug ?? false;\n const entry: CacheEntry<T> = {\n data,\n timestamp: Date.now(),\n expiresAt: Date.now() + staleTime,\n };\n\n // 1. Set in memory\n this.memoryCache.set(key, entry);\n\n // 2. Persist to localStorage if enabled\n if (options.persist) {\n this.setInStorage(key, entry, debug);\n }\n\n // 3. Schedule automatic cleanup\n this.scheduleCleanup(key, staleTime);\n }\n\n /**\n * Invalidate cache entries matching a pattern\n */\n invalidate(pattern: string | RegExp, debug: boolean = false) {\n const keysToRemove: string[] = [];\n\n // Find matching keys in memory\n for (const key of this.memoryCache.keys()) {\n if (this.matchesPattern(key, pattern)) {\n keysToRemove.push(key);\n }\n }\n\n // Remove from memory and storage\n keysToRemove.forEach((key) => {\n this.memoryCache.delete(key);\n this.removeFromStorage(key);\n this.cancelCleanup(key);\n });\n\n logIfEnabled(\n 'debug',\n `[Cache] Invalidated ${keysToRemove.length} entries matching:`,\n debug,\n pattern,\n );\n }\n\n /**\n * Clear all cache entries\n */\n clear(debug: boolean = false) {\n // Clear memory\n this.memoryCache.clear();\n\n // Clear all cleanup timers\n for (const timer of this.cleanupTimers.values()) {\n clearTimeout(timer);\n }\n this.cleanupTimers.clear();\n\n // Clear localStorage\n this.clearAllStorage();\n\n logIfEnabled('debug', '[Cache] Cleared all entries', debug);\n }\n\n /**\n * Get cache statistics (for debugging)\n */\n inspect() {\n const entries: Record<\n string,\n {\n data: any;\n ageMs: number;\n expiresInMs: number;\n isExpired: boolean;\n source: 'memory' | 'storage';\n }\n > = {};\n\n const now = Date.now();\n\n // Memory entries\n for (const [key, value] of this.memoryCache.entries()) {\n entries[key] = {\n data: value.data,\n ageMs: now - value.timestamp,\n expiresInMs: value.expiresAt - now,\n isExpired: now > value.expiresAt,\n source: 'memory',\n };\n }\n\n // Storage entries not in memory\n for (let i = 0; i < localStorage.length; i++) {\n const storageKey = localStorage.key(i);\n if (storageKey?.startsWith(this.STORAGE_PREFIX)) {\n const key = storageKey.substring(this.STORAGE_PREFIX.length);\n if (!entries[key]) {\n try {\n const entry = JSON.parse(localStorage.getItem(storageKey)!) as CacheEntry<any>;\n entries[key] = {\n data: entry.data,\n ageMs: now - entry.timestamp,\n expiresInMs: entry.expiresAt - now,\n isExpired: now > entry.expiresAt,\n source: 'storage',\n };\n } catch {\n // Ignore parse errors\n }\n }\n }\n }\n\n return {\n totalEntries: Object.keys(entries).length,\n memoryEntries: Array.from(this.memoryCache.keys()).length,\n storageEntries: this.countStorageEntries(),\n entries,\n };\n }\n\n /**\n * Get size of cache in localStorage (approximate)\n */\n getStorageSize(): number {\n let size = 0;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(this.STORAGE_PREFIX)) {\n const value = localStorage.getItem(key);\n if (value) {\n size += key.length + value.length;\n }\n }\n }\n return size;\n }\n\n // Private methods\n\n private getFromStorage<T>(key: string, debug: boolean = false): CacheEntry<T> | null {\n try {\n const stored = localStorage.getItem(this.STORAGE_PREFIX + key);\n if (!stored) return null;\n\n const entry = JSON.parse(stored) as CacheEntry<T>;\n return entry;\n } catch (error) {\n logIfEnabled('error', '[Cache] Error reading from storage:', debug, error);\n return null;\n }\n }\n\n private setInStorage<T>(key: string, entry: CacheEntry<T>, debug: boolean = false) {\n try {\n localStorage.setItem(this.STORAGE_PREFIX + key, JSON.stringify(entry));\n } catch (error) {\n // Handle quota exceeded\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n logIfEnabled('warn', '[Cache] Storage quota exceeded, clearing old entries', debug);\n this.clearOldestStorageEntries(debug);\n // Try again\n try {\n localStorage.setItem(this.STORAGE_PREFIX + key, JSON.stringify(entry));\n } catch (retryError) {\n logIfEnabled('error', '[Cache] Still cannot write to storage after cleanup', debug);\n }\n } else {\n logIfEnabled('error', '[Cache] Error writing to storage:', debug, error);\n }\n }\n }\n\n private removeFromStorage(key: string) {\n localStorage.removeItem(this.STORAGE_PREFIX + key);\n }\n\n private clearAllStorage() {\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(this.STORAGE_PREFIX)) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach((key) => localStorage.removeItem(key));\n }\n\n private cleanExpiredStorage() {\n const now = Date.now();\n const keysToRemove: string[] = [];\n\n for (let i = 0; i < localStorage.length; i++) {\n const storageKey = localStorage.key(i);\n if (storageKey?.startsWith(this.STORAGE_PREFIX)) {\n try {\n const entry = JSON.parse(localStorage.getItem(storageKey)!) as CacheEntry<any>;\n if (now > entry.expiresAt) {\n keysToRemove.push(storageKey);\n }\n } catch {\n // Remove corrupted entries\n keysToRemove.push(storageKey);\n }\n }\n }\n\n keysToRemove.forEach((key) => localStorage.removeItem(key));\n if (keysToRemove.length > 0) {\n // Use global log level for internal cleanup operations\n logger.debug(`[Cache] Cleaned up ${keysToRemove.length} expired storage entries`);\n }\n }\n\n private clearOldestStorageEntries(debug: boolean = false) {\n const entries: [string, number][] = [];\n\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(this.STORAGE_PREFIX)) {\n try {\n const entry = JSON.parse(localStorage.getItem(key)!) as CacheEntry<any>;\n entries.push([key, entry.timestamp]);\n } catch {\n // Remove corrupted entries\n localStorage.removeItem(key);\n }\n }\n }\n\n // Sort by timestamp (oldest first) and remove oldest 25%\n entries.sort((a, b) => a[1] - b[1]);\n const toRemove = Math.ceil(entries.length * 0.25);\n entries.slice(0, toRemove).forEach(([key]) => {\n localStorage.removeItem(key);\n });\n\n logIfEnabled('debug', `[Cache] Removed ${toRemove} oldest entries to free space`, debug);\n }\n\n private scheduleCleanup(key: string, delay: number) {\n // Cancel existing cleanup if any\n this.cancelCleanup(key);\n\n // Schedule new cleanup\n const timer = setTimeout(() => {\n this.memoryCache.delete(key);\n this.cleanupTimers.delete(key);\n }, delay);\n\n this.cleanupTimers.set(key, timer);\n }\n\n private cancelCleanup(key: string) {\n const timer = this.cleanupTimers.get(key);\n if (timer) {\n clearTimeout(timer);\n this.cleanupTimers.delete(key);\n }\n }\n\n private matchesPattern(key: string, pattern: string | RegExp): boolean {\n if (typeof pattern === 'string') {\n // Exact match or prefix match\n return key === pattern || key.startsWith(pattern);\n }\n return pattern.test(key);\n }\n\n private countStorageEntries(): number {\n let count = 0;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(this.STORAGE_PREFIX)) {\n count++;\n }\n }\n return count;\n }\n}\n\n// Singleton instance\nexport const queryCache = new QueryCache();\n\n// Expose for debugging in dev mode\nif (import.meta.env.DEV) {\n (window as any).__queryCache = queryCache;\n // Always log this in dev mode\n logger.debug('[Cache] Debug available: window.__queryCache');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useQueryCache-DkRwK5Gz.js","names":["keysToRemove: string[]","entry: CacheEntry<T>","entries: Record<\n string,\n {\n data: any;\n ageMs: number;\n expiresInMs: number;\n isExpired: boolean;\n source: 'memory' | 'storage';\n }\n >","entries: [string, number][]"],"sources":["../src/composables/useQueryCache.ts"],"sourcesContent":["import { logger, logIfEnabled } from '../utils/logger';\n\ninterface CacheEntry<T> {\n data: T;\n timestamp: number;\n expiresAt: number;\n}\n\ninterface CacheOptions {\n staleTime?: number; // How long data is fresh (ms), default 5 minutes\n persist?: boolean; // Save to localStorage\n debug?: boolean; // Enable/disable debug logging for this cache operation (default: false)\n}\n\nclass QueryCache {\n private memoryCache = new Map<string, CacheEntry<any>>();\n private readonly BUILD_TAG = import.meta.env.VITE_BUILD_TAG || 'dev';\n private readonly STORAGE_PREFIX = `rpc-cache:${this.BUILD_TAG}:`;\n private readonly BUILD_TAG_KEY = 'rpc-cache-build-tag';\n private cleanupTimers = new Map<string, number>();\n\n constructor() {\n // Check if this is a new deployment and clear old cache\n this.handleDeploymentChange();\n\n // Clean up expired localStorage entries on init\n this.cleanExpiredStorage();\n }\n\n /**\n * Detect deployment changes and clear old cache\n */\n private handleDeploymentChange() {\n const lastBuildTag = localStorage.getItem(this.BUILD_TAG_KEY);\n\n // If build tag is missing, clear all cache (first load or manual clear)\n if (!lastBuildTag) {\n // Use global log level for deployment change detection\n logger.debug('[Cache] Build tag missing - clearing all cache');\n this.clearAllStorage();\n }\n // If deployment changed, clear old cache from previous build\n else if (lastBuildTag !== this.BUILD_TAG) {\n // Use global log level for deployment change detection\n logger.debug(`[Cache] New deployment detected: ${lastBuildTag} → ${this.BUILD_TAG}`);\n logger.debug('[Cache] Clearing old cache from previous deployment');\n\n // Clear all old cache entries (from previous build tag)\n this.clearAllOldDeploymentCache(lastBuildTag);\n }\n\n // Store current build tag\n localStorage.setItem(this.BUILD_TAG_KEY, this.BUILD_TAG);\n }\n\n /**\n * Clear cache from previous deployment\n */\n private clearAllOldDeploymentCache(oldBuildTag: string) {\n const oldPrefix = `rpc-cache:${oldBuildTag}:`;\n const keysToRemove: string[] = [];\n\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(oldPrefix)) {\n keysToRemove.push(key);\n }\n }\n\n keysToRemove.forEach((key) => localStorage.removeItem(key));\n\n if (keysToRemove.length > 0) {\n // Use global log level for deployment change detection\n logger.debug(`[Cache] Removed ${keysToRemove.length} entries from previous deployment`);\n }\n }\n\n /**\n * Get data from cache (memory first, then localStorage if persist enabled)\n */\n get<T>(key: string, options: CacheOptions = {}): T | null {\n const now = Date.now();\n const debug = options.debug ?? false;\n\n // 1. Try memory cache first\n const memoryEntry = this.memoryCache.get(key);\n if (memoryEntry) {\n if (now < memoryEntry.expiresAt) {\n return memoryEntry.data as T;\n }\n // Expired in memory\n this.memoryCache.delete(key);\n }\n\n // 2. Try localStorage if persist is enabled\n if (options.persist) {\n const storageEntry = this.getFromStorage<T>(key, debug);\n if (storageEntry) {\n if (now < storageEntry.expiresAt) {\n // Rehydrate to memory cache\n this.memoryCache.set(key, storageEntry);\n return storageEntry.data;\n }\n // Expired in storage\n this.removeFromStorage(key);\n }\n }\n\n return null;\n }\n\n /**\n * Set data in cache (memory and optionally localStorage)\n */\n set<T>(key: string, data: T, options: CacheOptions = {}) {\n const staleTime = options.staleTime ?? 300000; // Default 5 minutes\n const debug = options.debug ?? false;\n const entry: CacheEntry<T> = {\n data,\n timestamp: Date.now(),\n expiresAt: Date.now() + staleTime,\n };\n\n // 1. Set in memory\n this.memoryCache.set(key, entry);\n\n // 2. Persist to localStorage if enabled\n if (options.persist) {\n this.setInStorage(key, entry, debug);\n }\n\n // 3. Schedule automatic cleanup\n this.scheduleCleanup(key, staleTime);\n }\n\n /**\n * Invalidate cache entries matching a pattern\n */\n invalidate(pattern: string | RegExp, debug: boolean = false) {\n const keysToRemove: string[] = [];\n\n // Find matching keys in memory\n for (const key of this.memoryCache.keys()) {\n if (this.matchesPattern(key, pattern)) {\n keysToRemove.push(key);\n }\n }\n\n // Remove from memory and storage\n keysToRemove.forEach((key) => {\n this.memoryCache.delete(key);\n this.removeFromStorage(key);\n this.cancelCleanup(key);\n });\n\n logIfEnabled(\n 'debug',\n `[Cache] Invalidated ${keysToRemove.length} entries matching:`,\n debug,\n pattern,\n );\n }\n\n /**\n * Clear all cache entries\n */\n clear(debug: boolean = false) {\n // Clear memory\n this.memoryCache.clear();\n\n // Clear all cleanup timers\n for (const timer of this.cleanupTimers.values()) {\n clearTimeout(timer);\n }\n this.cleanupTimers.clear();\n\n // Clear localStorage\n this.clearAllStorage();\n\n logIfEnabled('debug', '[Cache] Cleared all entries', debug);\n }\n\n /**\n * Get cache statistics (for debugging)\n */\n inspect() {\n const entries: Record<\n string,\n {\n data: any;\n ageMs: number;\n expiresInMs: number;\n isExpired: boolean;\n source: 'memory' | 'storage';\n }\n > = {};\n\n const now = Date.now();\n\n // Memory entries\n for (const [key, value] of this.memoryCache.entries()) {\n entries[key] = {\n data: value.data,\n ageMs: now - value.timestamp,\n expiresInMs: value.expiresAt - now,\n isExpired: now > value.expiresAt,\n source: 'memory',\n };\n }\n\n // Storage entries not in memory\n for (let i = 0; i < localStorage.length; i++) {\n const storageKey = localStorage.key(i);\n if (storageKey?.startsWith(this.STORAGE_PREFIX)) {\n const key = storageKey.substring(this.STORAGE_PREFIX.length);\n if (!entries[key]) {\n try {\n const entry = JSON.parse(localStorage.getItem(storageKey)!) as CacheEntry<any>;\n entries[key] = {\n data: entry.data,\n ageMs: now - entry.timestamp,\n expiresInMs: entry.expiresAt - now,\n isExpired: now > entry.expiresAt,\n source: 'storage',\n };\n } catch {\n // Ignore parse errors\n }\n }\n }\n }\n\n return {\n totalEntries: Object.keys(entries).length,\n memoryEntries: Array.from(this.memoryCache.keys()).length,\n storageEntries: this.countStorageEntries(),\n entries,\n };\n }\n\n /**\n * Get size of cache in localStorage (approximate)\n */\n getStorageSize(): number {\n let size = 0;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(this.STORAGE_PREFIX)) {\n const value = localStorage.getItem(key);\n if (value) {\n size += key.length + value.length;\n }\n }\n }\n return size;\n }\n\n // Private methods\n\n private getFromStorage<T>(key: string, debug: boolean = false): CacheEntry<T> | null {\n try {\n const stored = localStorage.getItem(this.STORAGE_PREFIX + key);\n if (!stored) return null;\n\n const entry = JSON.parse(stored) as CacheEntry<T>;\n return entry;\n } catch (error) {\n logIfEnabled('error', '[Cache] Error reading from storage:', debug, error);\n return null;\n }\n }\n\n private setInStorage<T>(key: string, entry: CacheEntry<T>, debug: boolean = false) {\n try {\n localStorage.setItem(this.STORAGE_PREFIX + key, JSON.stringify(entry));\n } catch (error) {\n // Handle quota exceeded\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n logIfEnabled('warn', '[Cache] Storage quota exceeded, clearing old entries', debug);\n this.clearOldestStorageEntries(debug);\n // Try again\n try {\n localStorage.setItem(this.STORAGE_PREFIX + key, JSON.stringify(entry));\n } catch (retryError) {\n logIfEnabled('error', '[Cache] Still cannot write to storage after cleanup', debug);\n }\n } else {\n logIfEnabled('error', '[Cache] Error writing to storage:', debug, error);\n }\n }\n }\n\n private removeFromStorage(key: string) {\n localStorage.removeItem(this.STORAGE_PREFIX + key);\n }\n\n private clearAllStorage() {\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(this.STORAGE_PREFIX)) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach((key) => localStorage.removeItem(key));\n }\n\n private cleanExpiredStorage() {\n const now = Date.now();\n const keysToRemove: string[] = [];\n\n for (let i = 0; i < localStorage.length; i++) {\n const storageKey = localStorage.key(i);\n if (storageKey?.startsWith(this.STORAGE_PREFIX)) {\n try {\n const entry = JSON.parse(localStorage.getItem(storageKey)!) as CacheEntry<any>;\n if (now > entry.expiresAt) {\n keysToRemove.push(storageKey);\n }\n } catch {\n // Remove corrupted entries\n keysToRemove.push(storageKey);\n }\n }\n }\n\n keysToRemove.forEach((key) => localStorage.removeItem(key));\n if (keysToRemove.length > 0) {\n // Use global log level for internal cleanup operations\n logger.debug(`[Cache] Cleaned up ${keysToRemove.length} expired storage entries`);\n }\n }\n\n private clearOldestStorageEntries(debug: boolean = false) {\n const entries: [string, number][] = [];\n\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(this.STORAGE_PREFIX)) {\n try {\n const entry = JSON.parse(localStorage.getItem(key)!) as CacheEntry<any>;\n entries.push([key, entry.timestamp]);\n } catch {\n // Remove corrupted entries\n localStorage.removeItem(key);\n }\n }\n }\n\n // Sort by timestamp (oldest first) and remove oldest 25%\n entries.sort((a, b) => a[1] - b[1]);\n const toRemove = Math.ceil(entries.length * 0.25);\n entries.slice(0, toRemove).forEach(([key]) => {\n localStorage.removeItem(key);\n });\n\n logIfEnabled('debug', `[Cache] Removed ${toRemove} oldest entries to free space`, debug);\n }\n\n private scheduleCleanup(key: string, delay: number) {\n // Cancel existing cleanup if any\n this.cancelCleanup(key);\n\n // Schedule new cleanup\n const timer = setTimeout(() => {\n this.memoryCache.delete(key);\n this.cleanupTimers.delete(key);\n }, delay);\n\n this.cleanupTimers.set(key, timer);\n }\n\n private cancelCleanup(key: string) {\n const timer = this.cleanupTimers.get(key);\n if (timer) {\n clearTimeout(timer);\n this.cleanupTimers.delete(key);\n }\n }\n\n private matchesPattern(key: string, pattern: string | RegExp): boolean {\n if (typeof pattern === 'string') {\n // Exact match or prefix match\n return key === pattern || key.startsWith(pattern);\n }\n return pattern.test(key);\n }\n\n private countStorageEntries(): number {\n let count = 0;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(this.STORAGE_PREFIX)) {\n count++;\n }\n }\n return count;\n }\n}\n\n// Singleton instance\nexport const queryCache = new QueryCache();\n\n// Expose for debugging in dev mode\nif (import.meta.env.DEV) {\n (window as any).__queryCache = queryCache;\n // Always log this in dev mode\n logger.debug('[Cache] Debug available: window.__queryCache');\n}\n"],"mappings":"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"}
@@ -589,7 +589,10 @@ const AUTH_ERROR_CODES = [
589
589
  "NO_REFRESH_TOKEN"
590
590
  ];
591
591
  /** Business error codes for frontend handling (e.g. redirects) */
592
- const BusinessErrorCode = { EMAIL_VERIFICATION_REQUIRED: "EMAIL_VERIFICATION_REQUIRED" };
592
+ const BusinessErrorCode = {
593
+ EMAIL_VERIFICATION_REQUIRED: "EMAIL_VERIFICATION_REQUIRED",
594
+ CONSENT_REQUIRED: "CONSENT_REQUIRED"
595
+ };
593
596
  const BATCH_MODE = {
594
597
  batch: "batch",
595
598
  tracked: "tracked"
@@ -731,7 +734,8 @@ async function executeWithAuth(fn, options) {
731
734
  }
732
735
  return await fn(createAppBatch(options));
733
736
  } catch (error) {
734
- if ((error?.code ?? error?.originalError?.code) === BusinessErrorCode.EMAIL_VERIFICATION_REQUIRED) {
737
+ const errorCode = error?.code ?? error?.originalError?.code;
738
+ if (errorCode === BusinessErrorCode.EMAIL_VERIFICATION_REQUIRED) {
735
739
  const router = getRouter();
736
740
  const currentPath = router.currentRoute.value.fullPath;
737
741
  const returnUrl = currentPath.startsWith("/") && !currentPath.startsWith("/auth/") ? currentPath : void 0;
@@ -741,6 +745,16 @@ async function executeWithAuth(fn, options) {
741
745
  });
742
746
  throw error;
743
747
  }
748
+ if (errorCode === BusinessErrorCode.CONSENT_REQUIRED) {
749
+ const router = getRouter();
750
+ const currentPath = router.currentRoute.value.fullPath;
751
+ const returnUrl = currentPath.startsWith("/") && !currentPath.startsWith("/auth/") ? currentPath : void 0;
752
+ await router.push({
753
+ path: "/auth/consent-required",
754
+ query: returnUrl ? { returnUrl } : {}
755
+ });
756
+ throw error;
757
+ }
744
758
  if (isAuthError(error)) {
745
759
  if (await attemptRefresh(userStore, options.refreshTokenHandler)) return await fn(createAppBatch(options));
746
760
  await pushToLogout();
@@ -781,4 +795,4 @@ function createTrackedSession(request, trackedSegment) {
781
795
 
782
796
  //#endregion
783
797
  export { EnhancedRefreshTokenHandler as a, setRefreshTokenHandler as c, Logger as d, logIfEnabled as f, setRouter as i, useUserSessionStore as l, useEnv as m, createAppBatch as n, createRefreshTokenHandler as o, logger as p, executeWithAuth as r, getRefreshTokenHandler as s, BATCH_MODE as t, LOG_LEVEL as u };
784
- //# sourceMappingURL=useRpcAuth-rmHf7bYx.js.map
798
+ //# sourceMappingURL=useRpcAuth-x5Gn5gR0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useRpcAuth-rmHf7bYx.js","names":["createAppBatch","refreshError: any","createAppBatch","headers: HeadersInit","lastError: Error | undefined","createAppBatch","error: any","globalRefreshTokenHandler: EnhancedRefreshTokenHandler<any> | null","globalRouter: Router | null","error: any","headers: HeadersInit","method: any"],"sources":["../src/composables/useEnv.ts","../src/utils/logger.ts","../src/composables/useUserSessionStore.ts","../src/composables/useRpc.ts","../src/utils/EnhancedRefreshTokenHandler.ts","../src/composables/useRpcAuth.ts"],"sourcesContent":["import { readonly } from 'vue';\n\nexport function useEnv() {\n const env = {\n restApiClient: {\n apiUrl: import.meta.env.VITE_API_CLIENT_URL as string,\n authOptions: {\n userDetails: import.meta.env.VITE_CF_APP_USER_DETAILS as string,\n accessToken: import.meta.env.VITE_CF_APP_ACCESS_TOKEN as string,\n decodedToken: import.meta.env.VITE_CF_APP_DECODED_TOKEN as string,\n },\n },\n allowUserSignup: import.meta.env.VITE_ALLOW_USER_SIGNUP === 'true',\n /** 'disabled' | 'soft' | 'strict' - undefined treated as 'disabled' */\n emailVerificationMode: (import.meta.env.VITE_EMAIL_VERIFICATION_MODE as\n | 'disabled'\n | 'soft'\n | 'strict'\n | undefined) ?? 'disabled',\n maxAttachmentFileSize: import.meta.env.VITE_MAX_ATTACHMENT_FILE_SIZE_MB\n ? parseInt(import.meta.env.VITE_MAX_ATTACHMENT_FILE_SIZE_MB, 10) * 1024 * 1024\n : 50 * 1024 * 1024, // Default: 50MB (convert MB to bytes)\n /** When true and consent feature enabled, redirect users with consents_complete=false to /auth/consent-required */\n requireConsentForExistingUsers: import.meta.env.VITE_REQUIRE_CONSENT_FOR_EXISTING_USERS === 'true',\n };\n\n return readonly(env);\n}\n","/**\n * Log levels as string literals\n */\nexport const LOG_LEVEL = {\n NONE: 'NONE',\n ERROR: 'ERROR',\n WARN: 'WARN',\n INFO: 'INFO',\n DEBUG: 'DEBUG',\n TRACE: 'TRACE',\n} as const;\n\nexport type LogLevel = (typeof LOG_LEVEL)[keyof typeof LOG_LEVEL];\n\n/**\n * Logger utility that conditionally logs based on configured log level\n */\nexport class Logger {\n private static instance: Logger;\n private logLevel: LogLevel = LOG_LEVEL.INFO; // Default log level\n\n private constructor() {\n this.setLogLevelFromEnv();\n }\n\n /**\n * Get the singleton logger instance\n */\n public static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n return Logger.instance;\n }\n\n /**\n * Set the log level from environment variables\n */\n private setLogLevelFromEnv(): void {\n // Check for explicit log level setting\n const logLevelStr = (import.meta.env.VITE_LOG_LEVEL as string) || '';\n\n if (logLevelStr) {\n switch (logLevelStr.toUpperCase()) {\n case 'NONE':\n this.logLevel = LOG_LEVEL.NONE;\n break;\n case 'ERROR':\n this.logLevel = LOG_LEVEL.ERROR;\n break;\n case 'WARN':\n this.logLevel = LOG_LEVEL.WARN;\n break;\n case 'INFO':\n this.logLevel = LOG_LEVEL.INFO;\n break;\n case 'DEBUG':\n this.logLevel = LOG_LEVEL.DEBUG;\n break;\n case 'TRACE':\n this.logLevel = LOG_LEVEL.TRACE;\n break;\n }\n } else {\n // If no explicit log level, set based on environment\n const isDev =\n import.meta.env.DEV === true ||\n import.meta.env.MODE === 'development' ||\n import.meta.env.VITE_APP_ENV === 'local' ||\n import.meta.env.VITE_APP_ENV === 'dev';\n\n this.logLevel = isDev ? LOG_LEVEL.DEBUG : LOG_LEVEL.INFO;\n }\n\n console.log(`[Logger] Log level set to: ${this.logLevel.toUpperCase()}`);\n }\n\n /**\n * Set the log level programmatically\n */\n public setLogLevel(level: LogLevel): void {\n this.logLevel = level;\n console.log(`[Logger] Log level changed to: ${this.logLevel.toUpperCase()}`);\n }\n\n /**\n * Get the current log level\n */\n public getLogLevel(): LogLevel {\n return this.logLevel;\n }\n\n /**\n * Determine if a message at the given level should be logged\n * based on the current log level setting\n */\n private shouldLog(level: LogLevel): boolean {\n // Define log level hierarchy (higher number = more verbose)\n const levelPriority = {\n [LOG_LEVEL.NONE]: 0,\n [LOG_LEVEL.ERROR]: 1,\n [LOG_LEVEL.WARN]: 2,\n [LOG_LEVEL.INFO]: 3,\n [LOG_LEVEL.DEBUG]: 4,\n [LOG_LEVEL.TRACE]: 5,\n };\n\n // Compare current log level with requested level\n // Only log if the current level is equal to or higher than the requested level\n return levelPriority[this.logLevel] >= levelPriority[level];\n }\n\n /**\n * Log a trace message (most verbose)\n */\n public trace(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.TRACE)) {\n console.log(`[TRACE] ${message}`, ...args);\n }\n }\n\n /**\n * Log a debug message\n */\n public debug(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.DEBUG)) {\n console.debug(`[DEBUG] ${message}`, ...args);\n }\n }\n\n /**\n * Log an info message\n */\n public info(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.INFO)) {\n console.log(`[INFO] ${message}`, ...args);\n }\n }\n\n /**\n * Log a warning message\n */\n public warn(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.WARN)) {\n console.warn(`[WARN] ${message}`, ...args);\n }\n }\n\n /**\n * Log an error message\n */\n public error(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.ERROR)) {\n console.error(`[ERROR] ${message}`, ...args);\n }\n }\n}\n\n// Export a singleton instance for easy use throughout the app\nexport const logger = Logger.getInstance();\n\n/**\n * Conditionally log based on per-instance debug flag and global log level\n * - If debug === false: never log (explicitly disabled)\n * - If debug === true: always log (bypasses global log level)\n * - If debug === undefined: use global log level (default behavior)\n */\nexport function logIfEnabled(\n level: 'debug' | 'error' | 'warn' | 'info',\n message: string,\n debug: boolean | undefined,\n ...args: any[]\n): void {\n if (debug === false) return; // Explicitly disabled\n if (debug === true) {\n // Explicitly enabled - log directly bypassing global log level\n const prefix = `[${level.toUpperCase()}]`;\n if (level === 'error') console.error(prefix, message, ...args);\n else if (level === 'warn') console.warn(prefix, message, ...args);\n else console.log(prefix, message, ...args);\n return;\n }\n // Otherwise use logger which respects global log level\n if (level === 'debug') logger.debug(message, ...args);\n else if (level === 'error') logger.error(message, ...args);\n else if (level === 'warn') logger.warn(message, ...args);\n else logger.info(message, ...args);\n}\n","import { jwtDecode } from 'jwt-decode';\nimport { defineStore } from 'pinia';\nimport { computed, ref, watchEffect } from 'vue';\nimport type { UserAppSession, UserDetailsTokenPayload } from '../lib/models/userSession';\nimport { logIfEnabled, logger } from '../utils/logger';\nimport { useEnv } from './useEnv';\nimport { createAppBatch } from './useRpc';\n\n/**\n * Generic user session store for Dragoncore applications.\n *\n * Responsibilities:\n * - Store and manage user session state (accessToken, userSession)\n * - Sync with localStorage\n * - Provide token refresh capability\n * - Provide token expiration checking\n *\n * Note: This store is intentionally NOT generic on TApi.\n * The refresh method uses createAppBatch which can be typed on a per-call basis.\n */\nexport const useUserSessionStore = defineStore('userSession', () => {\n const env = useEnv().restApiClient;\n const userSession = ref<UserAppSession | null>(null);\n const accessToken = ref<string | null>(null);\n const decodedToken = ref<any | null>(null);\n const isRefreshing = ref(false);\n const debug = ref<boolean>(false);\n\n // Watch localStorage for external changes and update our reactive refs\n watchEffect(() => {\n // Check if localStorage keys are properly defined\n if (!env.authOptions.accessToken || !env.authOptions.userDetails) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] localStorage keys are undefined - check environment variables',\n debug.value,\n );\n return;\n }\n\n const storedAccessToken = localStorage.getItem(env.authOptions.accessToken);\n if (storedAccessToken !== accessToken.value) {\n accessToken.value = storedAccessToken;\n try {\n decodedToken.value = storedAccessToken ? jwtDecode(storedAccessToken) : null;\n } catch (error) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] Failed to decode access token:',\n debug.value,\n error,\n );\n decodedToken.value = null;\n }\n }\n\n const storedUserSession = localStorage.getItem(env.authOptions.userDetails);\n if (storedUserSession) {\n try {\n const decoded = jwtDecode<UserDetailsTokenPayload>(storedUserSession);\n // Extract the actual session data from the nested 'details' field\n const sessionData = decoded.details;\n if (JSON.stringify(sessionData) !== JSON.stringify(userSession.value)) {\n userSession.value = sessionData;\n }\n } catch (error) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] Failed to decode user session:',\n debug.value,\n error,\n );\n if (userSession.value !== null) {\n userSession.value = null;\n }\n }\n } else if (userSession.value !== null) {\n userSession.value = null;\n }\n });\n\n const currentSession = computed(() => {\n if (!userSession.value) {\n return null;\n }\n return userSession.value;\n });\n\n const clientHeaders = computed(() => ({\n 'Content-Type': 'application/json',\n ...(accessToken.value ? { Authorization: `Bearer ${accessToken.value}` } : {}),\n }));\n\n /**\n * Refresh the access token using the refresh token (from HTTP-only cookie).\n * This method uses createAppBatch directly to avoid circular dependencies.\n *\n * @returns true if refresh was successful, false otherwise\n */\n async function refreshToken<\n TApi extends {\n userSessions: {\n refreshToken(): Promise<{ access_token: string; user_details_token: string }>;\n };\n },\n >(): Promise<boolean> {\n try {\n if (isRefreshing.value) {\n logIfEnabled('debug', '[RefreshToken] Token refresh already in progress', debug.value);\n return false;\n }\n\n isRefreshing.value = true;\n logIfEnabled('debug', '[RefreshToken] Starting token refresh', debug.value);\n\n // Check if refresh token is expired (if we have session data)\n if (userSession.value) {\n const tokenStatus = isTokenExpired();\n if (tokenStatus.refreshTokenExpired) {\n logIfEnabled(\n 'warn',\n '[RefreshToken] Refresh token is already expired, cannot refresh',\n debug.value,\n );\n return false;\n }\n }\n\n // Use createAppBatch directly - refresh endpoint is public and doesn't need auth wrapper\n // credentials: 'include' allows the HTTP-only refresh token cookie to be sent\n const batch = createAppBatch<TApi>({\n credentials: 'include',\n trackedSegment: 'userSessions.refreshToken',\n });\n const tokens = await batch.userSessions.refreshToken();\n\n if (!tokens || !tokens.access_token || !tokens.user_details_token) {\n logIfEnabled(\n 'error',\n '[RefreshToken] Invalid response from refresh endpoint',\n debug.value,\n );\n return false;\n }\n\n // Set both tokens using existing validation logic\n setSession(tokens.user_details_token);\n setAccessToken(tokens.access_token);\n\n // Verify that both components of the session were properly updated\n const sessionUpdated = !!userSession.value && !!accessToken.value;\n if (!sessionUpdated) {\n logIfEnabled(\n 'error',\n '[RefreshToken] Failed to update all session components',\n debug.value,\n );\n return false;\n }\n\n // Verify the new tokens are not expired\n const newTokenStatus = isTokenExpired();\n if (newTokenStatus.accessTokenExpired) {\n logIfEnabled(\n 'error',\n '[RefreshToken] New access token is already expired!',\n debug.value,\n );\n return false;\n }\n\n logIfEnabled('debug', '[RefreshToken] Token refresh successful', debug.value);\n return true;\n } catch (refreshError: any) {\n logIfEnabled('error', '[RefreshToken] Token refresh failed:', debug.value, refreshError);\n return false;\n } finally {\n isRefreshing.value = false;\n }\n }\n\n /**\n * Check if tokens are expired\n */\n function isTokenExpired(): { accessTokenExpired: boolean; refreshTokenExpired: boolean } {\n const now = Date.now() / 1000;\n\n // Access token expiration check\n const accessTokenExpired = decodedToken.value?.exp ? decodedToken.value.exp < now : true;\n\n // Refresh token expiration check\n const refreshTokenExpired = userSession.value?.expires_at\n ? new Date(userSession.value.expires_at).getTime() / 1000 < now\n : true;\n\n return { accessTokenExpired, refreshTokenExpired };\n }\n\n /**\n * Set the user session (stored in localStorage as JWT)\n */\n function setSession(token: string | null) {\n if (token) {\n try {\n const decoded = jwtDecode<UserDetailsTokenPayload>(token);\n // Extract the actual session data from the nested 'details' field\n userSession.value = decoded.details;\n localStorage.setItem(env.authOptions.userDetails, token);\n logIfEnabled('debug', '[SetSession] User session set successfully', debug.value);\n } catch (error) {\n logger.error('[SetSession] Failed to decode user session token:', error);\n userSession.value = null;\n localStorage.removeItem(env.authOptions.userDetails);\n }\n } else {\n userSession.value = null;\n localStorage.removeItem(env.authOptions.userDetails);\n logIfEnabled('debug', '[SetSession] User session cleared', debug.value);\n }\n }\n\n /**\n * Set the access token (stored in localStorage as JWT string)\n */\n function setAccessToken(token: string | null) {\n if (token) {\n try {\n const decoded = jwtDecode(token);\n accessToken.value = token;\n decodedToken.value = decoded;\n localStorage.setItem(env.authOptions.accessToken, token);\n logIfEnabled('debug', '[SetAccessToken] Access token set successfully', debug.value);\n } catch (error) {\n logger.error('[SetAccessToken] Failed to decode access token:', error);\n accessToken.value = null;\n decodedToken.value = null;\n localStorage.removeItem(env.authOptions.accessToken);\n // Also clear user session if we're clearing the access token\n if (userSession.value) {\n userSession.value = null;\n localStorage.removeItem(env.authOptions.userDetails);\n }\n }\n } else {\n accessToken.value = null;\n decodedToken.value = null;\n localStorage.removeItem(env.authOptions.accessToken);\n logIfEnabled('debug', '[SetAccessToken] Access token cleared', debug.value);\n }\n }\n\n /**\n * Clear all session data\n */\n function clearSession() {\n setSession(null);\n setAccessToken(null);\n }\n\n /**\n * Re-read session from localStorage and update in-memory state.\n * Use when another tab may have updated localStorage (e.g. after email verification).\n */\n function syncFromStorage() {\n if (!env.authOptions.accessToken || !env.authOptions.userDetails) return;\n\n const storedAccessToken = localStorage.getItem(env.authOptions.accessToken);\n if (storedAccessToken !== accessToken.value) {\n accessToken.value = storedAccessToken;\n try {\n decodedToken.value = storedAccessToken ? jwtDecode(storedAccessToken) : null;\n } catch (error) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] Failed to decode access token:',\n debug.value,\n error,\n );\n decodedToken.value = null;\n }\n }\n\n const storedUserSession = localStorage.getItem(env.authOptions.userDetails);\n if (storedUserSession) {\n try {\n const decoded = jwtDecode<UserDetailsTokenPayload>(storedUserSession);\n const sessionData = decoded.details;\n if (JSON.stringify(sessionData) !== JSON.stringify(userSession.value)) {\n userSession.value = sessionData;\n }\n } catch (error) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] Failed to decode user session:',\n debug.value,\n error,\n );\n if (userSession.value !== null) {\n userSession.value = null;\n }\n }\n } else if (userSession.value !== null) {\n userSession.value = null;\n }\n }\n\n return {\n // State\n userSession,\n currentSession,\n accessToken,\n clientHeaders,\n debug,\n // Methods\n setSession,\n setAccessToken,\n clearSession,\n refreshToken,\n syncFromStorage,\n isTokenExpired,\n };\n});\n","import { newHttpBatchRpcSession, type RpcStub } from 'capnweb';\nimport type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport { useEnv } from './useEnv';\nimport { useUserSessionStore } from './useUserSessionStore';\n\n/**\n * Creates a fresh RPC batch session with authentication headers.\n * Each call creates a new session, which is the correct pattern for Cap'n Web RPC.\n *\n * This is the simple version - just creates a batch with auth headers.\n * For advanced features (token refresh, retry, tracked sessions), use executeWithAuth from useRpcAuth.\n *\n * @param options - Optional configuration for the RPC batch\n * @param options.credentials - Credentials mode for the request. Use 'include' for login/logout/refreshToken to allow cookies.\n * @param options.trackedSegment - Path segment to append to /rpc for metrics/tracking (e.g. 'userSessions.refreshToken').\n */\nexport function createAppBatch<TApi extends Record<string, any> = DragoncoreApi>(options?: {\n credentials?: RequestCredentials;\n trackedSegment?: string;\n}): RpcStub<TApi> {\n const userStore = useUserSessionStore();\n const env = useEnv();\n\n const headers: HeadersInit = {};\n // Pinia stores auto-unwrap refs, so accessToken is already string | null\n const accessToken = userStore.accessToken;\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`;\n }\n\n const baseUrl = env.restApiClient.apiUrl + '/rpc';\n const url = options?.trackedSegment ? `${baseUrl}/${options.trackedSegment}` : baseUrl;\n\n // Create a Request object with headers (capnweb accepts Request objects)\n const request = new Request(url, {\n method: 'POST', // Will be overridden by capnweb, but required for Request constructor\n headers,\n credentials: options?.credentials ?? 'omit', // Use 'include' for login/logout/refreshToken\n });\n\n return newHttpBatchRpcSession<TApi>(request);\n}\n","import { useEnv } from '../composables/useEnv';\nimport { createAppBatch } from '../composables/useRpc';\nimport { logger } from './logger';\n\ninterface AuthTokens {\n access_token: string;\n user_details_token: string;\n}\n\ninterface RefreshState {\n isRefreshing: boolean;\n pendingPromise: Promise<AuthTokens> | null;\n lastAttempt: number;\n failureCount: number;\n}\n\n/**\n * Minimum API shape required for authentication.\n * Your API must have a userSessions service with a refreshToken method.\n */\nexport interface AuthenticatableApi {\n userSessions: {\n refreshToken(): Promise<{\n access_token: string;\n user_details_token: string;\n }>;\n };\n}\n\nexport class EnhancedRefreshTokenHandler<TApi extends AuthenticatableApi> {\n private refreshState: RefreshState = {\n isRefreshing: false,\n pendingPromise: null,\n lastAttempt: 0,\n failureCount: 0,\n };\n\n async performRefreshWithStrategies(): Promise<AuthTokens> {\n // Prevent duplicate refresh attempts\n if (this.refreshState.isRefreshing && this.refreshState.pendingPromise) {\n logger.debug(\n '[EnhancedRefresh] Refresh already in progress, returning existing promise',\n );\n return this.refreshState.pendingPromise;\n }\n\n this.refreshState.isRefreshing = true;\n this.refreshState.pendingPromise = this.executeRefreshStrategies();\n\n try {\n const tokens = await this.refreshState.pendingPromise;\n this.refreshState.failureCount = 0;\n logger.debug('[EnhancedRefresh] Refresh completed successfully');\n return tokens;\n } catch (error) {\n this.refreshState.failureCount++;\n logger.error('[EnhancedRefresh] All refresh strategies failed:', error);\n throw error;\n } finally {\n this.refreshState.isRefreshing = false;\n this.refreshState.pendingPromise = null;\n this.refreshState.lastAttempt = Date.now();\n }\n }\n\n private async executeRefreshStrategies(): Promise<AuthTokens> {\n const strategies = [\n {\n name: 'Direct RefreshToken',\n execute: () => this.directRefreshToken(),\n },\n {\n name: 'Warmup + Retry RefreshToken',\n execute: () => this.warmupAndRetryRefresh(),\n },\n {\n name: 'Alternative Domain RefreshToken',\n execute: () => this.alternativeDomainRefresh(),\n },\n ];\n\n let lastError: Error | undefined;\n let partialSuccess = false;\n\n for (const [index, strategy] of strategies.entries()) {\n try {\n logger.debug(`[EnhancedRefresh] Attempting strategy ${index + 1}: ${strategy.name}`);\n const tokens = await strategy.execute();\n logger.debug(`[EnhancedRefresh] Strategy ${index + 1} (${strategy.name}) succeeded`);\n return tokens;\n } catch (error) {\n lastError = error as Error;\n logger.debug(\n `[EnhancedRefresh] Strategy ${index + 1} (${strategy.name}) failed:`,\n error,\n );\n\n // Check if we got a partial response or if this is a network/temporary issue\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (\n !errorMessage.includes('No refresh_token') &&\n !errorMessage.includes('REFRESH_TOKEN_EXPIRED')\n ) {\n // This might be a temporary failure, mark as partial success\n partialSuccess = true;\n }\n\n // Progressive backoff between strategies\n if (index < strategies.length - 1) {\n const backoffDelay = 100 * (index + 1); // 100ms, 200ms, etc.\n await this.delay(backoffDelay);\n }\n }\n }\n\n // Add context to error object for better handling\n if (lastError && partialSuccess) {\n const enhancedError = lastError;\n (enhancedError as any).partialSuccess = true;\n (enhancedError as any).isTemporaryFailure = true;\n }\n\n throw lastError!;\n }\n\n private async directRefreshToken(): Promise<AuthTokens> {\n try {\n // Create RPC batch directly - refresh endpoint is public, doesn't need auth check\n // Use credentials: 'include' to send cookies with refresh token\n const batch = createAppBatch<TApi>({\n credentials: 'include',\n trackedSegment: 'userSessions.refreshToken',\n });\n const tokens = await batch.userSessions.refreshToken();\n\n if (!tokens || !tokens.access_token || !tokens.user_details_token) {\n throw new Error('No refresh_token in response');\n }\n\n return {\n access_token: tokens.access_token,\n user_details_token: tokens.user_details_token,\n };\n } catch (error: any) {\n // Log the full error to help debug\n logger.error('[EnhancedRefresh] Refresh token call failed:', {\n error,\n name: error?.name,\n message: error?.message,\n code: error?.code,\n originalError: error?.originalError,\n stack: error?.stack,\n });\n\n // Re-throw with more context if it's an InternalServerError\n if (error?.name === 'InternalServerError' && error?.originalError) {\n throw error.originalError;\n }\n throw error;\n }\n }\n\n private async warmupAndRetryRefresh(): Promise<AuthTokens> {\n logger.debug('[EnhancedRefresh] Warming up cookie context');\n\n // First, make a lightweight request to restore cookie context\n await this.warmupCookieContext();\n\n // Wait briefly for browser to restore cookie state\n await this.delay(150);\n\n // Now attempt the refresh\n return this.directRefreshToken();\n }\n\n private async alternativeDomainRefresh(): Promise<AuthTokens> {\n // This strategy could use a different approach if backend supports it\n // For now, just retry with longer delay after warmup\n await this.warmupCookieContext();\n await this.delay(300);\n return this.directRefreshToken();\n }\n\n private async warmupCookieContext(): Promise<void> {\n const warmupStrategies = [\n // Strategy 1: Favicon request (lightweight)\n () =>\n fetch(window.location.origin + '/favicon.ico', {\n method: 'HEAD',\n credentials: 'include',\n cache: 'no-cache',\n mode: 'same-origin',\n }),\n\n // Strategy 2: OPTIONS request to RPC endpoint\n () => {\n const rpcEndpoint = useEnv().restApiClient.apiUrl + '/rpc';\n return fetch(rpcEndpoint, {\n method: 'OPTIONS',\n credentials: 'include',\n cache: 'no-cache',\n });\n },\n\n // Strategy 3: Root path request\n () =>\n fetch(window.location.origin + '/', {\n method: 'HEAD',\n credentials: 'include',\n cache: 'no-cache',\n mode: 'same-origin',\n }),\n ];\n\n // Try warmup strategies in parallel, use the fastest one\n try {\n await Promise.race(\n warmupStrategies.map((strategy) =>\n strategy().catch(() => {\n // Ignore individual strategy failures\n }),\n ),\n );\n logger.debug('[EnhancedRefresh] Cookie context warmed up');\n } catch (error) {\n // If all warmup strategies fail, continue anyway\n logger.debug('[EnhancedRefresh] Cookie warmup failed, continuing:', error);\n }\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // Utility method to check if we should attempt refresh based on recent failures\n shouldAttemptRefresh(): boolean {\n const timeSinceLastAttempt = Date.now() - this.refreshState.lastAttempt;\n const minRetryInterval = Math.min(\n 5000,\n 1000 * Math.pow(2, this.refreshState.failureCount),\n ); // Exponential backoff, max 5s\n\n return timeSinceLastAttempt > minRetryInterval;\n }\n\n // Get current refresh state for debugging\n getRefreshState(): RefreshState {\n return { ...this.refreshState };\n }\n}\n\n/**\n * Create an instance of the refresh token handler for your API type.\n * Your API must extend AuthenticatableApi (must have userSessions.refreshToken method).\n *\n * @example\n * ```typescript\n * // In your app's setup/config\n * import type { AppApi } from '@follow-zap/shared';\n * import { createRefreshTokenHandler, setRefreshTokenHandler } from '@dragonmastery/dragoncore-vue';\n *\n * // Initialize during app setup\n * setRefreshTokenHandler(createRefreshTokenHandler<AppApi>());\n * ```\n */\nexport function createRefreshTokenHandler<TApi extends AuthenticatableApi>() {\n return new EnhancedRefreshTokenHandler<TApi>();\n}\n\n/**\n * Global refresh token handler instance.\n * Set this once in your app's initialization.\n */\nlet globalRefreshTokenHandler: EnhancedRefreshTokenHandler<any> | null = null;\n\n/**\n * Set the global refresh token handler for your application.\n * Call this once during app initialization.\n */\nexport function setRefreshTokenHandler<TApi extends AuthenticatableApi>(\n handler: EnhancedRefreshTokenHandler<TApi>,\n): void {\n globalRefreshTokenHandler = handler;\n}\n\n/**\n * Get the global refresh token handler.\n * This is used internally by useQuery and useMutation.\n *\n * @throws Error if handler is not set\n */\nexport function getRefreshTokenHandler(): EnhancedRefreshTokenHandler<any> {\n if (!globalRefreshTokenHandler) {\n throw new Error(\n 'Refresh token handler not initialized. Call setRefreshTokenHandler() in your app initialization.',\n );\n }\n return globalRefreshTokenHandler as EnhancedRefreshTokenHandler<any>;\n}\n","import type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport { newHttpBatchRpcSession, type RpcStub } from 'capnweb';\nimport type { Router } from 'vue-router';\nimport { useEnv } from './useEnv';\nimport { useUserSessionStore } from './useUserSessionStore';\n\n/**\n * Auth error codes that should trigger token refresh\n */\nconst AUTH_ERROR_CODES = [\n 'ACCESS_TOKEN_EXPIRED',\n 'ACCESS_TOKEN_REVOKED',\n 'NO_ACCESS_TOKEN',\n 'NO_REFRESH_TOKEN',\n];\n\n/** Business error codes for frontend handling (e.g. redirects) */\nconst BusinessErrorCode = {\n EMAIL_VERIFICATION_REQUIRED: 'EMAIL_VERIFICATION_REQUIRED',\n} as const;\n\nexport const BATCH_MODE = {\n batch: 'batch',\n tracked: 'tracked',\n} as const;\n\nexport type BatchMode = (typeof BATCH_MODE)[keyof typeof BATCH_MODE];\n\n/**\n * Check if an error is an auth error that should trigger refresh\n */\nfunction isAuthError(error: any): boolean {\n if (!error) return false;\n\n // Unwrap InternalServerError to get original error\n let actualError = error;\n if (error.name === 'InternalServerError' && error.originalError) {\n actualError = error.originalError;\n }\n\n // Check for AuthenticationError class name\n if (actualError.name === 'AuthenticationError' || error.name === 'AuthenticationError') {\n return true;\n }\n\n // Check for error code property\n if (actualError.code && AUTH_ERROR_CODES.includes(actualError.code)) return true;\n if (error.code && AUTH_ERROR_CODES.includes(error.code)) return true;\n\n // Check error message for auth error patterns\n const errorMessage = actualError.message || error.message || String(error);\n if (AUTH_ERROR_CODES.some((code) => errorMessage.includes(code))) return true;\n\n // Check for common auth error strings\n if (\n errorMessage.includes('Unauthorized') ||\n errorMessage.includes('authentication') ||\n errorMessage.includes('token')\n ) {\n // Only treat as auth error if it's clearly an auth issue\n return (\n errorMessage.toLowerCase().includes('expired') ||\n errorMessage.toLowerCase().includes('revoked') ||\n errorMessage.toLowerCase().includes('invalid token') ||\n errorMessage.toLowerCase().includes('no refresh token')\n );\n }\n\n return false;\n}\n\n/**\n * Global router instance.\n * Set this once in your app's initialization.\n */\nlet globalRouter: Router | null = null;\n\n/**\n * Set the global router instance for your application.\n * Call this once during app initialization.\n */\nexport function setRouter(router: Router): void {\n globalRouter = router;\n}\n\n/**\n * Get the global router instance.\n * This is used internally by executeWithAuth for navigation.\n *\n * @throws Error if router is not set\n */\nfunction getRouter(): Router {\n if (!globalRouter) {\n throw new Error('Router not initialized. Call setRouter() in your app initialization.');\n }\n return globalRouter;\n}\n\n/**\n * Push to logout with returnUrl so user can return to their intended destination after re-login.\n * Validates path: must start with / and not /auth/ to avoid loops.\n */\nfunction pushToLogout() {\n const router = getRouter();\n const currentPath = router.currentRoute.value.fullPath;\n const returnUrl =\n currentPath.startsWith('/') && !currentPath.startsWith('/auth/') ? currentPath : undefined;\n const query = returnUrl ? { returnUrl } : {};\n return router.push({ path: '/auth/logout', query });\n}\n\n/**\n * Check if token needs refresh before making a request\n */\nfunction needsRefresh(userStore: ReturnType<typeof useUserSessionStore>): boolean {\n if (!userStore.accessToken) {\n return true;\n }\n const { accessTokenExpired, refreshTokenExpired } = userStore.isTokenExpired();\n return accessTokenExpired || refreshTokenExpired;\n}\n\n/**\n * Attempt to refresh the token using the provided handler\n */\nasync function attemptRefresh(\n userStore: ReturnType<typeof useUserSessionStore>,\n refreshTokenHandler: {\n shouldAttemptRefresh(): boolean;\n performRefreshWithStrategies(): Promise<{\n access_token: string;\n user_details_token: string;\n }>;\n },\n): Promise<boolean> {\n try {\n if (!userStore.currentSession && !userStore.accessToken) {\n return false;\n }\n\n if (userStore.currentSession) {\n const { refreshTokenExpired } = userStore.isTokenExpired();\n if (refreshTokenExpired) {\n await pushToLogout();\n return false;\n }\n }\n\n if (!refreshTokenHandler.shouldAttemptRefresh()) {\n return false;\n }\n\n const tokens = await refreshTokenHandler.performRefreshWithStrategies();\n userStore.setSession(tokens.user_details_token);\n userStore.setAccessToken(tokens.access_token);\n return true;\n } catch (error: any) {\n console.error('[RPC Auth] Refresh attempt failed:', {\n error,\n name: error?.name,\n message: error?.message,\n code: error?.code,\n originalError: error?.originalError,\n });\n\n // Unwrap InternalServerError to check original error\n const actualError = error?.originalError || error;\n const errorMessage = (actualError?.message || error?.message || '').toUpperCase();\n const originalErrorMessage = (error?.originalError?.message || '').toUpperCase();\n const combinedMessage = `${errorMessage} ${originalErrorMessage}`;\n\n const criticalError =\n combinedMessage.includes('NO_REFRESH_TOKEN') ||\n combinedMessage.includes('REFRESH_TOKEN_EXPIRED') ||\n combinedMessage.includes('REFRESH_TOKEN_REVOKED') ||\n combinedMessage.includes('INVALID REFRESH TOKEN') ||\n combinedMessage.includes('NO REFRESH TOKEN FOUND');\n\n if (criticalError) {\n await pushToLogout();\n }\n return false;\n }\n}\n\n/**\n * Create a base RPC batch with current auth token\n */\nexport function createAppBatch<TApi extends Record<string, any> = DragoncoreApi>(options?: {\n credentials?: RequestCredentials;\n mode?: BatchMode;\n trackedSegment?: string;\n}): RpcStub<TApi> {\n const userStore = useUserSessionStore();\n const env = useEnv();\n\n const headers: HeadersInit = {};\n const accessToken = userStore.accessToken;\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`;\n }\n\n const request = new Request(env.restApiClient.apiUrl + '/rpc', {\n method: 'POST',\n headers,\n credentials: options?.credentials ?? 'omit',\n });\n\n // If mode is batch and no tracked segment is provided then we can just return the batch\n if (options?.mode === BATCH_MODE.batch && !options?.trackedSegment) {\n return newHttpBatchRpcSession<TApi>(request);\n }\n\n // Use tracked session for metrics (creates separate HTTP request per method)\n return createTrackedSession<TApi>(request, options?.trackedSegment);\n}\n\n/**\n * Execute an RPC call with automatic auth handling\n * - Checks token expiration before call\n * - Handles auth errors and retries after refresh\n *\n * @param fn - Function that receives an RPC batch and returns a promise\n * @param options - Configuration options\n * @param options.refreshTokenHandler - Instance of refresh token handler for your API type\n */\nexport async function executeWithAuth<\n TApi extends Record<string, any> = DragoncoreApi,\n T = any,\n>(\n fn: (batch: RpcStub<TApi>) => Promise<T>,\n options: {\n credentials?: RequestCredentials;\n skipAuthCheck?: boolean;\n mode?: BatchMode;\n trackedSegment?: string;\n refreshTokenHandler: {\n shouldAttemptRefresh(): boolean;\n performRefreshWithStrategies(): Promise<{\n access_token: string;\n user_details_token: string;\n }>;\n };\n },\n): Promise<T> {\n const userStore = useUserSessionStore();\n\n // Skip auth for login/logout/refreshToken operations\n if (options?.skipAuthCheck) {\n const batch = createAppBatch<TApi>(options);\n return await fn(batch);\n }\n\n // Check if token needs refresh before making the request\n if (needsRefresh(userStore)) {\n const refreshed = await attemptRefresh(userStore, options.refreshTokenHandler);\n if (!refreshed) {\n // If refresh failed and we have no token, don't proceed\n if (!userStore.accessToken) {\n await pushToLogout();\n throw new Error('Authentication required');\n }\n // If we have a token but refresh failed, continue anyway (might be temporary)\n } else {\n // Verify the token is actually set\n if (!userStore.accessToken) {\n await pushToLogout();\n throw new Error('Token refresh failed to set access token');\n }\n }\n }\n\n // Execute the operation\n try {\n // Double-check we have a token before creating the batch\n if (!userStore.accessToken) {\n await pushToLogout();\n throw new Error('Authentication required');\n }\n const batch = createAppBatch<TApi>(options);\n return await fn(batch);\n } catch (error: any) {\n // If BusinessError with EMAIL_VERIFICATION_REQUIRED, redirect to verify-email\n const errorCode = error?.code ?? error?.originalError?.code;\n if (errorCode === BusinessErrorCode.EMAIL_VERIFICATION_REQUIRED) {\n const router = getRouter();\n const currentPath = router.currentRoute.value.fullPath;\n const returnUrl =\n currentPath.startsWith('/') && !currentPath.startsWith('/auth/') ? currentPath : undefined;\n await router.push({\n path: '/auth/verify-email',\n query: returnUrl ? { returnUrl } : {},\n });\n throw error;\n }\n\n // If auth error, refresh and retry once\n if (isAuthError(error)) {\n const refreshed = await attemptRefresh(userStore, options.refreshTokenHandler);\n if (refreshed) {\n const retryBatch = createAppBatch<TApi>(options);\n return await fn(retryBatch);\n }\n await pushToLogout();\n throw error;\n }\n throw error;\n }\n}\n\n/**\n * Create a tracked RPC session that appends method names to URL\n */\nfunction createTrackedSession<T extends Record<string, any> = DragoncoreApi>(\n request: Request,\n trackedSegment?: string,\n): RpcStub<T> {\n const baseUrl = request.url;\n // If trackedSegment is provided then we dont need to do any ofteh complex proxy stuff, append the segment to the url and return the batch\n if (trackedSegment) {\n return newHttpBatchRpcSession<T>(\n new Request(`${baseUrl}/${trackedSegment}`, {\n method: request.method,\n headers: request.headers,\n credentials: request.credentials,\n }),\n );\n }\n\n function createProxy(path: string[] = []): any {\n return new Proxy(() => {}, {\n get(_target, prop) {\n if (typeof prop === 'string') {\n return createProxy([...path, prop]);\n }\n return undefined;\n },\n\n apply(_target, _thisArg, args) {\n // Build the full method path (e.g., \"teams.getUserTeams\")\n const fullPath = path.join('.');\n\n // Clone the request with updated URL\n const trackedRequest = new Request(`${baseUrl}/${fullPath}`, {\n method: request.method,\n headers: request.headers,\n credentials: request.credentials,\n });\n\n // Create batch with the tracked URL\n const batch = newHttpBatchRpcSession<T>(trackedRequest);\n\n // Navigate to the right method on the batch\n let method: any = batch;\n for (const segment of path) {\n method = method[segment];\n }\n\n // Call with original arguments\n return method(...args);\n },\n });\n }\n\n return createProxy() as RpcStub<T>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useRpcAuth-x5Gn5gR0.js","names":["createAppBatch","refreshError: any","createAppBatch","headers: HeadersInit","lastError: Error | undefined","createAppBatch","error: any","globalRefreshTokenHandler: EnhancedRefreshTokenHandler<any> | null","globalRouter: Router | null","error: any","headers: HeadersInit","method: any"],"sources":["../src/composables/useEnv.ts","../src/utils/logger.ts","../src/composables/useUserSessionStore.ts","../src/composables/useRpc.ts","../src/utils/EnhancedRefreshTokenHandler.ts","../src/composables/useRpcAuth.ts"],"sourcesContent":["import { readonly } from 'vue';\n\nexport function useEnv() {\n const env = {\n restApiClient: {\n apiUrl: import.meta.env.VITE_API_CLIENT_URL as string,\n authOptions: {\n userDetails: import.meta.env.VITE_CF_APP_USER_DETAILS as string,\n accessToken: import.meta.env.VITE_CF_APP_ACCESS_TOKEN as string,\n decodedToken: import.meta.env.VITE_CF_APP_DECODED_TOKEN as string,\n },\n },\n allowUserSignup: import.meta.env.VITE_ALLOW_USER_SIGNUP === 'true',\n /** 'disabled' | 'soft' | 'strict' - undefined treated as 'disabled' */\n emailVerificationMode: (import.meta.env.VITE_EMAIL_VERIFICATION_MODE as\n | 'disabled'\n | 'soft'\n | 'strict'\n | undefined) ?? 'disabled',\n maxAttachmentFileSize: import.meta.env.VITE_MAX_ATTACHMENT_FILE_SIZE_MB\n ? parseInt(import.meta.env.VITE_MAX_ATTACHMENT_FILE_SIZE_MB, 10) * 1024 * 1024\n : 50 * 1024 * 1024, // Default: 50MB (convert MB to bytes)\n /** When true and consent feature enabled, redirect users with consents_complete=false to /auth/consent-required */\n requireConsentForExistingUsers: import.meta.env.VITE_REQUIRE_CONSENT_FOR_EXISTING_USERS === 'true',\n };\n\n return readonly(env);\n}\n","/**\n * Log levels as string literals\n */\nexport const LOG_LEVEL = {\n NONE: 'NONE',\n ERROR: 'ERROR',\n WARN: 'WARN',\n INFO: 'INFO',\n DEBUG: 'DEBUG',\n TRACE: 'TRACE',\n} as const;\n\nexport type LogLevel = (typeof LOG_LEVEL)[keyof typeof LOG_LEVEL];\n\n/**\n * Logger utility that conditionally logs based on configured log level\n */\nexport class Logger {\n private static instance: Logger;\n private logLevel: LogLevel = LOG_LEVEL.INFO; // Default log level\n\n private constructor() {\n this.setLogLevelFromEnv();\n }\n\n /**\n * Get the singleton logger instance\n */\n public static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n return Logger.instance;\n }\n\n /**\n * Set the log level from environment variables\n */\n private setLogLevelFromEnv(): void {\n // Check for explicit log level setting\n const logLevelStr = (import.meta.env.VITE_LOG_LEVEL as string) || '';\n\n if (logLevelStr) {\n switch (logLevelStr.toUpperCase()) {\n case 'NONE':\n this.logLevel = LOG_LEVEL.NONE;\n break;\n case 'ERROR':\n this.logLevel = LOG_LEVEL.ERROR;\n break;\n case 'WARN':\n this.logLevel = LOG_LEVEL.WARN;\n break;\n case 'INFO':\n this.logLevel = LOG_LEVEL.INFO;\n break;\n case 'DEBUG':\n this.logLevel = LOG_LEVEL.DEBUG;\n break;\n case 'TRACE':\n this.logLevel = LOG_LEVEL.TRACE;\n break;\n }\n } else {\n // If no explicit log level, set based on environment\n const isDev =\n import.meta.env.DEV === true ||\n import.meta.env.MODE === 'development' ||\n import.meta.env.VITE_APP_ENV === 'local' ||\n import.meta.env.VITE_APP_ENV === 'dev';\n\n this.logLevel = isDev ? LOG_LEVEL.DEBUG : LOG_LEVEL.INFO;\n }\n\n console.log(`[Logger] Log level set to: ${this.logLevel.toUpperCase()}`);\n }\n\n /**\n * Set the log level programmatically\n */\n public setLogLevel(level: LogLevel): void {\n this.logLevel = level;\n console.log(`[Logger] Log level changed to: ${this.logLevel.toUpperCase()}`);\n }\n\n /**\n * Get the current log level\n */\n public getLogLevel(): LogLevel {\n return this.logLevel;\n }\n\n /**\n * Determine if a message at the given level should be logged\n * based on the current log level setting\n */\n private shouldLog(level: LogLevel): boolean {\n // Define log level hierarchy (higher number = more verbose)\n const levelPriority = {\n [LOG_LEVEL.NONE]: 0,\n [LOG_LEVEL.ERROR]: 1,\n [LOG_LEVEL.WARN]: 2,\n [LOG_LEVEL.INFO]: 3,\n [LOG_LEVEL.DEBUG]: 4,\n [LOG_LEVEL.TRACE]: 5,\n };\n\n // Compare current log level with requested level\n // Only log if the current level is equal to or higher than the requested level\n return levelPriority[this.logLevel] >= levelPriority[level];\n }\n\n /**\n * Log a trace message (most verbose)\n */\n public trace(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.TRACE)) {\n console.log(`[TRACE] ${message}`, ...args);\n }\n }\n\n /**\n * Log a debug message\n */\n public debug(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.DEBUG)) {\n console.debug(`[DEBUG] ${message}`, ...args);\n }\n }\n\n /**\n * Log an info message\n */\n public info(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.INFO)) {\n console.log(`[INFO] ${message}`, ...args);\n }\n }\n\n /**\n * Log a warning message\n */\n public warn(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.WARN)) {\n console.warn(`[WARN] ${message}`, ...args);\n }\n }\n\n /**\n * Log an error message\n */\n public error(message: string, ...args: any[]): void {\n if (this.shouldLog(LOG_LEVEL.ERROR)) {\n console.error(`[ERROR] ${message}`, ...args);\n }\n }\n}\n\n// Export a singleton instance for easy use throughout the app\nexport const logger = Logger.getInstance();\n\n/**\n * Conditionally log based on per-instance debug flag and global log level\n * - If debug === false: never log (explicitly disabled)\n * - If debug === true: always log (bypasses global log level)\n * - If debug === undefined: use global log level (default behavior)\n */\nexport function logIfEnabled(\n level: 'debug' | 'error' | 'warn' | 'info',\n message: string,\n debug: boolean | undefined,\n ...args: any[]\n): void {\n if (debug === false) return; // Explicitly disabled\n if (debug === true) {\n // Explicitly enabled - log directly bypassing global log level\n const prefix = `[${level.toUpperCase()}]`;\n if (level === 'error') console.error(prefix, message, ...args);\n else if (level === 'warn') console.warn(prefix, message, ...args);\n else console.log(prefix, message, ...args);\n return;\n }\n // Otherwise use logger which respects global log level\n if (level === 'debug') logger.debug(message, ...args);\n else if (level === 'error') logger.error(message, ...args);\n else if (level === 'warn') logger.warn(message, ...args);\n else logger.info(message, ...args);\n}\n","import { jwtDecode } from 'jwt-decode';\nimport { defineStore } from 'pinia';\nimport { computed, ref, watchEffect } from 'vue';\nimport type { UserAppSession, UserDetailsTokenPayload } from '../lib/models/userSession';\nimport { logIfEnabled, logger } from '../utils/logger';\nimport { useEnv } from './useEnv';\nimport { createAppBatch } from './useRpc';\n\n/**\n * Generic user session store for Dragoncore applications.\n *\n * Responsibilities:\n * - Store and manage user session state (accessToken, userSession)\n * - Sync with localStorage\n * - Provide token refresh capability\n * - Provide token expiration checking\n *\n * Note: This store is intentionally NOT generic on TApi.\n * The refresh method uses createAppBatch which can be typed on a per-call basis.\n */\nexport const useUserSessionStore = defineStore('userSession', () => {\n const env = useEnv().restApiClient;\n const userSession = ref<UserAppSession | null>(null);\n const accessToken = ref<string | null>(null);\n const decodedToken = ref<any | null>(null);\n const isRefreshing = ref(false);\n const debug = ref<boolean>(false);\n\n // Watch localStorage for external changes and update our reactive refs\n watchEffect(() => {\n // Check if localStorage keys are properly defined\n if (!env.authOptions.accessToken || !env.authOptions.userDetails) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] localStorage keys are undefined - check environment variables',\n debug.value,\n );\n return;\n }\n\n const storedAccessToken = localStorage.getItem(env.authOptions.accessToken);\n if (storedAccessToken !== accessToken.value) {\n accessToken.value = storedAccessToken;\n try {\n decodedToken.value = storedAccessToken ? jwtDecode(storedAccessToken) : null;\n } catch (error) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] Failed to decode access token:',\n debug.value,\n error,\n );\n decodedToken.value = null;\n }\n }\n\n const storedUserSession = localStorage.getItem(env.authOptions.userDetails);\n if (storedUserSession) {\n try {\n const decoded = jwtDecode<UserDetailsTokenPayload>(storedUserSession);\n // Extract the actual session data from the nested 'details' field\n const sessionData = decoded.details;\n if (JSON.stringify(sessionData) !== JSON.stringify(userSession.value)) {\n userSession.value = sessionData;\n }\n } catch (error) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] Failed to decode user session:',\n debug.value,\n error,\n );\n if (userSession.value !== null) {\n userSession.value = null;\n }\n }\n } else if (userSession.value !== null) {\n userSession.value = null;\n }\n });\n\n const currentSession = computed(() => {\n if (!userSession.value) {\n return null;\n }\n return userSession.value;\n });\n\n const clientHeaders = computed(() => ({\n 'Content-Type': 'application/json',\n ...(accessToken.value ? { Authorization: `Bearer ${accessToken.value}` } : {}),\n }));\n\n /**\n * Refresh the access token using the refresh token (from HTTP-only cookie).\n * This method uses createAppBatch directly to avoid circular dependencies.\n *\n * @returns true if refresh was successful, false otherwise\n */\n async function refreshToken<\n TApi extends {\n userSessions: {\n refreshToken(): Promise<{ access_token: string; user_details_token: string }>;\n };\n },\n >(): Promise<boolean> {\n try {\n if (isRefreshing.value) {\n logIfEnabled('debug', '[RefreshToken] Token refresh already in progress', debug.value);\n return false;\n }\n\n isRefreshing.value = true;\n logIfEnabled('debug', '[RefreshToken] Starting token refresh', debug.value);\n\n // Check if refresh token is expired (if we have session data)\n if (userSession.value) {\n const tokenStatus = isTokenExpired();\n if (tokenStatus.refreshTokenExpired) {\n logIfEnabled(\n 'warn',\n '[RefreshToken] Refresh token is already expired, cannot refresh',\n debug.value,\n );\n return false;\n }\n }\n\n // Use createAppBatch directly - refresh endpoint is public and doesn't need auth wrapper\n // credentials: 'include' allows the HTTP-only refresh token cookie to be sent\n const batch = createAppBatch<TApi>({\n credentials: 'include',\n trackedSegment: 'userSessions.refreshToken',\n });\n const tokens = await batch.userSessions.refreshToken();\n\n if (!tokens || !tokens.access_token || !tokens.user_details_token) {\n logIfEnabled(\n 'error',\n '[RefreshToken] Invalid response from refresh endpoint',\n debug.value,\n );\n return false;\n }\n\n // Set both tokens using existing validation logic\n setSession(tokens.user_details_token);\n setAccessToken(tokens.access_token);\n\n // Verify that both components of the session were properly updated\n const sessionUpdated = !!userSession.value && !!accessToken.value;\n if (!sessionUpdated) {\n logIfEnabled(\n 'error',\n '[RefreshToken] Failed to update all session components',\n debug.value,\n );\n return false;\n }\n\n // Verify the new tokens are not expired\n const newTokenStatus = isTokenExpired();\n if (newTokenStatus.accessTokenExpired) {\n logIfEnabled(\n 'error',\n '[RefreshToken] New access token is already expired!',\n debug.value,\n );\n return false;\n }\n\n logIfEnabled('debug', '[RefreshToken] Token refresh successful', debug.value);\n return true;\n } catch (refreshError: any) {\n logIfEnabled('error', '[RefreshToken] Token refresh failed:', debug.value, refreshError);\n return false;\n } finally {\n isRefreshing.value = false;\n }\n }\n\n /**\n * Check if tokens are expired\n */\n function isTokenExpired(): { accessTokenExpired: boolean; refreshTokenExpired: boolean } {\n const now = Date.now() / 1000;\n\n // Access token expiration check\n const accessTokenExpired = decodedToken.value?.exp ? decodedToken.value.exp < now : true;\n\n // Refresh token expiration check\n const refreshTokenExpired = userSession.value?.expires_at\n ? new Date(userSession.value.expires_at).getTime() / 1000 < now\n : true;\n\n return { accessTokenExpired, refreshTokenExpired };\n }\n\n /**\n * Set the user session (stored in localStorage as JWT)\n */\n function setSession(token: string | null) {\n if (token) {\n try {\n const decoded = jwtDecode<UserDetailsTokenPayload>(token);\n // Extract the actual session data from the nested 'details' field\n userSession.value = decoded.details;\n localStorage.setItem(env.authOptions.userDetails, token);\n logIfEnabled('debug', '[SetSession] User session set successfully', debug.value);\n } catch (error) {\n logger.error('[SetSession] Failed to decode user session token:', error);\n userSession.value = null;\n localStorage.removeItem(env.authOptions.userDetails);\n }\n } else {\n userSession.value = null;\n localStorage.removeItem(env.authOptions.userDetails);\n logIfEnabled('debug', '[SetSession] User session cleared', debug.value);\n }\n }\n\n /**\n * Set the access token (stored in localStorage as JWT string)\n */\n function setAccessToken(token: string | null) {\n if (token) {\n try {\n const decoded = jwtDecode(token);\n accessToken.value = token;\n decodedToken.value = decoded;\n localStorage.setItem(env.authOptions.accessToken, token);\n logIfEnabled('debug', '[SetAccessToken] Access token set successfully', debug.value);\n } catch (error) {\n logger.error('[SetAccessToken] Failed to decode access token:', error);\n accessToken.value = null;\n decodedToken.value = null;\n localStorage.removeItem(env.authOptions.accessToken);\n // Also clear user session if we're clearing the access token\n if (userSession.value) {\n userSession.value = null;\n localStorage.removeItem(env.authOptions.userDetails);\n }\n }\n } else {\n accessToken.value = null;\n decodedToken.value = null;\n localStorage.removeItem(env.authOptions.accessToken);\n logIfEnabled('debug', '[SetAccessToken] Access token cleared', debug.value);\n }\n }\n\n /**\n * Clear all session data\n */\n function clearSession() {\n setSession(null);\n setAccessToken(null);\n }\n\n /**\n * Re-read session from localStorage and update in-memory state.\n * Use when another tab may have updated localStorage (e.g. after email verification).\n */\n function syncFromStorage() {\n if (!env.authOptions.accessToken || !env.authOptions.userDetails) return;\n\n const storedAccessToken = localStorage.getItem(env.authOptions.accessToken);\n if (storedAccessToken !== accessToken.value) {\n accessToken.value = storedAccessToken;\n try {\n decodedToken.value = storedAccessToken ? jwtDecode(storedAccessToken) : null;\n } catch (error) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] Failed to decode access token:',\n debug.value,\n error,\n );\n decodedToken.value = null;\n }\n }\n\n const storedUserSession = localStorage.getItem(env.authOptions.userDetails);\n if (storedUserSession) {\n try {\n const decoded = jwtDecode<UserDetailsTokenPayload>(storedUserSession);\n const sessionData = decoded.details;\n if (JSON.stringify(sessionData) !== JSON.stringify(userSession.value)) {\n userSession.value = sessionData;\n }\n } catch (error) {\n logIfEnabled(\n 'error',\n '[UserSessionStore] Failed to decode user session:',\n debug.value,\n error,\n );\n if (userSession.value !== null) {\n userSession.value = null;\n }\n }\n } else if (userSession.value !== null) {\n userSession.value = null;\n }\n }\n\n return {\n // State\n userSession,\n currentSession,\n accessToken,\n clientHeaders,\n debug,\n // Methods\n setSession,\n setAccessToken,\n clearSession,\n refreshToken,\n syncFromStorage,\n isTokenExpired,\n };\n});\n","import { newHttpBatchRpcSession, type RpcStub } from 'capnweb';\nimport type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport { useEnv } from './useEnv';\nimport { useUserSessionStore } from './useUserSessionStore';\n\n/**\n * Creates a fresh RPC batch session with authentication headers.\n * Each call creates a new session, which is the correct pattern for Cap'n Web RPC.\n *\n * This is the simple version - just creates a batch with auth headers.\n * For advanced features (token refresh, retry, tracked sessions), use executeWithAuth from useRpcAuth.\n *\n * @param options - Optional configuration for the RPC batch\n * @param options.credentials - Credentials mode for the request. Use 'include' for login/logout/refreshToken to allow cookies.\n * @param options.trackedSegment - Path segment to append to /rpc for metrics/tracking (e.g. 'userSessions.refreshToken').\n */\nexport function createAppBatch<TApi extends Record<string, any> = DragoncoreApi>(options?: {\n credentials?: RequestCredentials;\n trackedSegment?: string;\n}): RpcStub<TApi> {\n const userStore = useUserSessionStore();\n const env = useEnv();\n\n const headers: HeadersInit = {};\n // Pinia stores auto-unwrap refs, so accessToken is already string | null\n const accessToken = userStore.accessToken;\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`;\n }\n\n const baseUrl = env.restApiClient.apiUrl + '/rpc';\n const url = options?.trackedSegment ? `${baseUrl}/${options.trackedSegment}` : baseUrl;\n\n // Create a Request object with headers (capnweb accepts Request objects)\n const request = new Request(url, {\n method: 'POST', // Will be overridden by capnweb, but required for Request constructor\n headers,\n credentials: options?.credentials ?? 'omit', // Use 'include' for login/logout/refreshToken\n });\n\n return newHttpBatchRpcSession<TApi>(request);\n}\n","import { useEnv } from '../composables/useEnv';\nimport { createAppBatch } from '../composables/useRpc';\nimport { logger } from './logger';\n\ninterface AuthTokens {\n access_token: string;\n user_details_token: string;\n}\n\ninterface RefreshState {\n isRefreshing: boolean;\n pendingPromise: Promise<AuthTokens> | null;\n lastAttempt: number;\n failureCount: number;\n}\n\n/**\n * Minimum API shape required for authentication.\n * Your API must have a userSessions service with a refreshToken method.\n */\nexport interface AuthenticatableApi {\n userSessions: {\n refreshToken(): Promise<{\n access_token: string;\n user_details_token: string;\n }>;\n };\n}\n\nexport class EnhancedRefreshTokenHandler<TApi extends AuthenticatableApi> {\n private refreshState: RefreshState = {\n isRefreshing: false,\n pendingPromise: null,\n lastAttempt: 0,\n failureCount: 0,\n };\n\n async performRefreshWithStrategies(): Promise<AuthTokens> {\n // Prevent duplicate refresh attempts\n if (this.refreshState.isRefreshing && this.refreshState.pendingPromise) {\n logger.debug(\n '[EnhancedRefresh] Refresh already in progress, returning existing promise',\n );\n return this.refreshState.pendingPromise;\n }\n\n this.refreshState.isRefreshing = true;\n this.refreshState.pendingPromise = this.executeRefreshStrategies();\n\n try {\n const tokens = await this.refreshState.pendingPromise;\n this.refreshState.failureCount = 0;\n logger.debug('[EnhancedRefresh] Refresh completed successfully');\n return tokens;\n } catch (error) {\n this.refreshState.failureCount++;\n logger.error('[EnhancedRefresh] All refresh strategies failed:', error);\n throw error;\n } finally {\n this.refreshState.isRefreshing = false;\n this.refreshState.pendingPromise = null;\n this.refreshState.lastAttempt = Date.now();\n }\n }\n\n private async executeRefreshStrategies(): Promise<AuthTokens> {\n const strategies = [\n {\n name: 'Direct RefreshToken',\n execute: () => this.directRefreshToken(),\n },\n {\n name: 'Warmup + Retry RefreshToken',\n execute: () => this.warmupAndRetryRefresh(),\n },\n {\n name: 'Alternative Domain RefreshToken',\n execute: () => this.alternativeDomainRefresh(),\n },\n ];\n\n let lastError: Error | undefined;\n let partialSuccess = false;\n\n for (const [index, strategy] of strategies.entries()) {\n try {\n logger.debug(`[EnhancedRefresh] Attempting strategy ${index + 1}: ${strategy.name}`);\n const tokens = await strategy.execute();\n logger.debug(`[EnhancedRefresh] Strategy ${index + 1} (${strategy.name}) succeeded`);\n return tokens;\n } catch (error) {\n lastError = error as Error;\n logger.debug(\n `[EnhancedRefresh] Strategy ${index + 1} (${strategy.name}) failed:`,\n error,\n );\n\n // Check if we got a partial response or if this is a network/temporary issue\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (\n !errorMessage.includes('No refresh_token') &&\n !errorMessage.includes('REFRESH_TOKEN_EXPIRED')\n ) {\n // This might be a temporary failure, mark as partial success\n partialSuccess = true;\n }\n\n // Progressive backoff between strategies\n if (index < strategies.length - 1) {\n const backoffDelay = 100 * (index + 1); // 100ms, 200ms, etc.\n await this.delay(backoffDelay);\n }\n }\n }\n\n // Add context to error object for better handling\n if (lastError && partialSuccess) {\n const enhancedError = lastError;\n (enhancedError as any).partialSuccess = true;\n (enhancedError as any).isTemporaryFailure = true;\n }\n\n throw lastError!;\n }\n\n private async directRefreshToken(): Promise<AuthTokens> {\n try {\n // Create RPC batch directly - refresh endpoint is public, doesn't need auth check\n // Use credentials: 'include' to send cookies with refresh token\n const batch = createAppBatch<TApi>({\n credentials: 'include',\n trackedSegment: 'userSessions.refreshToken',\n });\n const tokens = await batch.userSessions.refreshToken();\n\n if (!tokens || !tokens.access_token || !tokens.user_details_token) {\n throw new Error('No refresh_token in response');\n }\n\n return {\n access_token: tokens.access_token,\n user_details_token: tokens.user_details_token,\n };\n } catch (error: any) {\n // Log the full error to help debug\n logger.error('[EnhancedRefresh] Refresh token call failed:', {\n error,\n name: error?.name,\n message: error?.message,\n code: error?.code,\n originalError: error?.originalError,\n stack: error?.stack,\n });\n\n // Re-throw with more context if it's an InternalServerError\n if (error?.name === 'InternalServerError' && error?.originalError) {\n throw error.originalError;\n }\n throw error;\n }\n }\n\n private async warmupAndRetryRefresh(): Promise<AuthTokens> {\n logger.debug('[EnhancedRefresh] Warming up cookie context');\n\n // First, make a lightweight request to restore cookie context\n await this.warmupCookieContext();\n\n // Wait briefly for browser to restore cookie state\n await this.delay(150);\n\n // Now attempt the refresh\n return this.directRefreshToken();\n }\n\n private async alternativeDomainRefresh(): Promise<AuthTokens> {\n // This strategy could use a different approach if backend supports it\n // For now, just retry with longer delay after warmup\n await this.warmupCookieContext();\n await this.delay(300);\n return this.directRefreshToken();\n }\n\n private async warmupCookieContext(): Promise<void> {\n const warmupStrategies = [\n // Strategy 1: Favicon request (lightweight)\n () =>\n fetch(window.location.origin + '/favicon.ico', {\n method: 'HEAD',\n credentials: 'include',\n cache: 'no-cache',\n mode: 'same-origin',\n }),\n\n // Strategy 2: OPTIONS request to RPC endpoint\n () => {\n const rpcEndpoint = useEnv().restApiClient.apiUrl + '/rpc';\n return fetch(rpcEndpoint, {\n method: 'OPTIONS',\n credentials: 'include',\n cache: 'no-cache',\n });\n },\n\n // Strategy 3: Root path request\n () =>\n fetch(window.location.origin + '/', {\n method: 'HEAD',\n credentials: 'include',\n cache: 'no-cache',\n mode: 'same-origin',\n }),\n ];\n\n // Try warmup strategies in parallel, use the fastest one\n try {\n await Promise.race(\n warmupStrategies.map((strategy) =>\n strategy().catch(() => {\n // Ignore individual strategy failures\n }),\n ),\n );\n logger.debug('[EnhancedRefresh] Cookie context warmed up');\n } catch (error) {\n // If all warmup strategies fail, continue anyway\n logger.debug('[EnhancedRefresh] Cookie warmup failed, continuing:', error);\n }\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // Utility method to check if we should attempt refresh based on recent failures\n shouldAttemptRefresh(): boolean {\n const timeSinceLastAttempt = Date.now() - this.refreshState.lastAttempt;\n const minRetryInterval = Math.min(\n 5000,\n 1000 * Math.pow(2, this.refreshState.failureCount),\n ); // Exponential backoff, max 5s\n\n return timeSinceLastAttempt > minRetryInterval;\n }\n\n // Get current refresh state for debugging\n getRefreshState(): RefreshState {\n return { ...this.refreshState };\n }\n}\n\n/**\n * Create an instance of the refresh token handler for your API type.\n * Your API must extend AuthenticatableApi (must have userSessions.refreshToken method).\n *\n * @example\n * ```typescript\n * // In your app's setup/config\n * import type { AppApi } from '@follow-zap/shared';\n * import { createRefreshTokenHandler, setRefreshTokenHandler } from '@dragonmastery/dragoncore-vue';\n *\n * // Initialize during app setup\n * setRefreshTokenHandler(createRefreshTokenHandler<AppApi>());\n * ```\n */\nexport function createRefreshTokenHandler<TApi extends AuthenticatableApi>() {\n return new EnhancedRefreshTokenHandler<TApi>();\n}\n\n/**\n * Global refresh token handler instance.\n * Set this once in your app's initialization.\n */\nlet globalRefreshTokenHandler: EnhancedRefreshTokenHandler<any> | null = null;\n\n/**\n * Set the global refresh token handler for your application.\n * Call this once during app initialization.\n */\nexport function setRefreshTokenHandler<TApi extends AuthenticatableApi>(\n handler: EnhancedRefreshTokenHandler<TApi>,\n): void {\n globalRefreshTokenHandler = handler;\n}\n\n/**\n * Get the global refresh token handler.\n * This is used internally by useQuery and useMutation.\n *\n * @throws Error if handler is not set\n */\nexport function getRefreshTokenHandler(): EnhancedRefreshTokenHandler<any> {\n if (!globalRefreshTokenHandler) {\n throw new Error(\n 'Refresh token handler not initialized. Call setRefreshTokenHandler() in your app initialization.',\n );\n }\n return globalRefreshTokenHandler as EnhancedRefreshTokenHandler<any>;\n}\n","import type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport { newHttpBatchRpcSession, type RpcStub } from 'capnweb';\nimport type { Router } from 'vue-router';\nimport { useEnv } from './useEnv';\nimport { useUserSessionStore } from './useUserSessionStore';\n\n/**\n * Auth error codes that should trigger token refresh\n */\nconst AUTH_ERROR_CODES = [\n 'ACCESS_TOKEN_EXPIRED',\n 'ACCESS_TOKEN_REVOKED',\n 'NO_ACCESS_TOKEN',\n 'NO_REFRESH_TOKEN',\n];\n\n/** Business error codes for frontend handling (e.g. redirects) */\nconst BusinessErrorCode = {\n EMAIL_VERIFICATION_REQUIRED: 'EMAIL_VERIFICATION_REQUIRED',\n CONSENT_REQUIRED: 'CONSENT_REQUIRED',\n} as const;\n\nexport const BATCH_MODE = {\n batch: 'batch',\n tracked: 'tracked',\n} as const;\n\nexport type BatchMode = (typeof BATCH_MODE)[keyof typeof BATCH_MODE];\n\n/**\n * Check if an error is an auth error that should trigger refresh\n */\nfunction isAuthError(error: any): boolean {\n if (!error) return false;\n\n // Unwrap InternalServerError to get original error\n let actualError = error;\n if (error.name === 'InternalServerError' && error.originalError) {\n actualError = error.originalError;\n }\n\n // Check for AuthenticationError class name\n if (actualError.name === 'AuthenticationError' || error.name === 'AuthenticationError') {\n return true;\n }\n\n // Check for error code property\n if (actualError.code && AUTH_ERROR_CODES.includes(actualError.code)) return true;\n if (error.code && AUTH_ERROR_CODES.includes(error.code)) return true;\n\n // Check error message for auth error patterns\n const errorMessage = actualError.message || error.message || String(error);\n if (AUTH_ERROR_CODES.some((code) => errorMessage.includes(code))) return true;\n\n // Check for common auth error strings\n if (\n errorMessage.includes('Unauthorized') ||\n errorMessage.includes('authentication') ||\n errorMessage.includes('token')\n ) {\n // Only treat as auth error if it's clearly an auth issue\n return (\n errorMessage.toLowerCase().includes('expired') ||\n errorMessage.toLowerCase().includes('revoked') ||\n errorMessage.toLowerCase().includes('invalid token') ||\n errorMessage.toLowerCase().includes('no refresh token')\n );\n }\n\n return false;\n}\n\n/**\n * Global router instance.\n * Set this once in your app's initialization.\n */\nlet globalRouter: Router | null = null;\n\n/**\n * Set the global router instance for your application.\n * Call this once during app initialization.\n */\nexport function setRouter(router: Router): void {\n globalRouter = router;\n}\n\n/**\n * Get the global router instance.\n * This is used internally by executeWithAuth for navigation.\n *\n * @throws Error if router is not set\n */\nfunction getRouter(): Router {\n if (!globalRouter) {\n throw new Error('Router not initialized. Call setRouter() in your app initialization.');\n }\n return globalRouter;\n}\n\n/**\n * Push to logout with returnUrl so user can return to their intended destination after re-login.\n * Validates path: must start with / and not /auth/ to avoid loops.\n */\nfunction pushToLogout() {\n const router = getRouter();\n const currentPath = router.currentRoute.value.fullPath;\n const returnUrl =\n currentPath.startsWith('/') && !currentPath.startsWith('/auth/') ? currentPath : undefined;\n const query = returnUrl ? { returnUrl } : {};\n return router.push({ path: '/auth/logout', query });\n}\n\n/**\n * Check if token needs refresh before making a request\n */\nfunction needsRefresh(userStore: ReturnType<typeof useUserSessionStore>): boolean {\n if (!userStore.accessToken) {\n return true;\n }\n const { accessTokenExpired, refreshTokenExpired } = userStore.isTokenExpired();\n return accessTokenExpired || refreshTokenExpired;\n}\n\n/**\n * Attempt to refresh the token using the provided handler\n */\nasync function attemptRefresh(\n userStore: ReturnType<typeof useUserSessionStore>,\n refreshTokenHandler: {\n shouldAttemptRefresh(): boolean;\n performRefreshWithStrategies(): Promise<{\n access_token: string;\n user_details_token: string;\n }>;\n },\n): Promise<boolean> {\n try {\n if (!userStore.currentSession && !userStore.accessToken) {\n return false;\n }\n\n if (userStore.currentSession) {\n const { refreshTokenExpired } = userStore.isTokenExpired();\n if (refreshTokenExpired) {\n await pushToLogout();\n return false;\n }\n }\n\n if (!refreshTokenHandler.shouldAttemptRefresh()) {\n return false;\n }\n\n const tokens = await refreshTokenHandler.performRefreshWithStrategies();\n userStore.setSession(tokens.user_details_token);\n userStore.setAccessToken(tokens.access_token);\n return true;\n } catch (error: any) {\n console.error('[RPC Auth] Refresh attempt failed:', {\n error,\n name: error?.name,\n message: error?.message,\n code: error?.code,\n originalError: error?.originalError,\n });\n\n // Unwrap InternalServerError to check original error\n const actualError = error?.originalError || error;\n const errorMessage = (actualError?.message || error?.message || '').toUpperCase();\n const originalErrorMessage = (error?.originalError?.message || '').toUpperCase();\n const combinedMessage = `${errorMessage} ${originalErrorMessage}`;\n\n const criticalError =\n combinedMessage.includes('NO_REFRESH_TOKEN') ||\n combinedMessage.includes('REFRESH_TOKEN_EXPIRED') ||\n combinedMessage.includes('REFRESH_TOKEN_REVOKED') ||\n combinedMessage.includes('INVALID REFRESH TOKEN') ||\n combinedMessage.includes('NO REFRESH TOKEN FOUND');\n\n if (criticalError) {\n await pushToLogout();\n }\n return false;\n }\n}\n\n/**\n * Create a base RPC batch with current auth token\n */\nexport function createAppBatch<TApi extends Record<string, any> = DragoncoreApi>(options?: {\n credentials?: RequestCredentials;\n mode?: BatchMode;\n trackedSegment?: string;\n}): RpcStub<TApi> {\n const userStore = useUserSessionStore();\n const env = useEnv();\n\n const headers: HeadersInit = {};\n const accessToken = userStore.accessToken;\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`;\n }\n\n const request = new Request(env.restApiClient.apiUrl + '/rpc', {\n method: 'POST',\n headers,\n credentials: options?.credentials ?? 'omit',\n });\n\n // If mode is batch and no tracked segment is provided then we can just return the batch\n if (options?.mode === BATCH_MODE.batch && !options?.trackedSegment) {\n return newHttpBatchRpcSession<TApi>(request);\n }\n\n // Use tracked session for metrics (creates separate HTTP request per method)\n return createTrackedSession<TApi>(request, options?.trackedSegment);\n}\n\n/**\n * Execute an RPC call with automatic auth handling\n * - Checks token expiration before call\n * - Handles auth errors and retries after refresh\n *\n * @param fn - Function that receives an RPC batch and returns a promise\n * @param options - Configuration options\n * @param options.refreshTokenHandler - Instance of refresh token handler for your API type\n */\nexport async function executeWithAuth<\n TApi extends Record<string, any> = DragoncoreApi,\n T = any,\n>(\n fn: (batch: RpcStub<TApi>) => Promise<T>,\n options: {\n credentials?: RequestCredentials;\n skipAuthCheck?: boolean;\n mode?: BatchMode;\n trackedSegment?: string;\n refreshTokenHandler: {\n shouldAttemptRefresh(): boolean;\n performRefreshWithStrategies(): Promise<{\n access_token: string;\n user_details_token: string;\n }>;\n };\n },\n): Promise<T> {\n const userStore = useUserSessionStore();\n\n // Skip auth for login/logout/refreshToken operations\n if (options?.skipAuthCheck) {\n const batch = createAppBatch<TApi>(options);\n return await fn(batch);\n }\n\n // Check if token needs refresh before making the request\n if (needsRefresh(userStore)) {\n const refreshed = await attemptRefresh(userStore, options.refreshTokenHandler);\n if (!refreshed) {\n // If refresh failed and we have no token, don't proceed\n if (!userStore.accessToken) {\n await pushToLogout();\n throw new Error('Authentication required');\n }\n // If we have a token but refresh failed, continue anyway (might be temporary)\n } else {\n // Verify the token is actually set\n if (!userStore.accessToken) {\n await pushToLogout();\n throw new Error('Token refresh failed to set access token');\n }\n }\n }\n\n // Execute the operation\n try {\n // Double-check we have a token before creating the batch\n if (!userStore.accessToken) {\n await pushToLogout();\n throw new Error('Authentication required');\n }\n const batch = createAppBatch<TApi>(options);\n return await fn(batch);\n } catch (error: any) {\n // If BusinessError with EMAIL_VERIFICATION_REQUIRED, redirect to verify-email\n const errorCode = error?.code ?? error?.originalError?.code;\n if (errorCode === BusinessErrorCode.EMAIL_VERIFICATION_REQUIRED) {\n const router = getRouter();\n const currentPath = router.currentRoute.value.fullPath;\n const returnUrl =\n currentPath.startsWith('/') && !currentPath.startsWith('/auth/') ? currentPath : undefined;\n await router.push({\n path: '/auth/verify-email',\n query: returnUrl ? { returnUrl } : {},\n });\n throw error;\n }\n\n // If BusinessError with CONSENT_REQUIRED, redirect to consent-required\n if (errorCode === BusinessErrorCode.CONSENT_REQUIRED) {\n const router = getRouter();\n const currentPath = router.currentRoute.value.fullPath;\n const returnUrl =\n currentPath.startsWith('/') && !currentPath.startsWith('/auth/') ? currentPath : undefined;\n await router.push({\n path: '/auth/consent-required',\n query: returnUrl ? { returnUrl } : {},\n });\n throw error;\n }\n\n // If auth error, refresh and retry once\n if (isAuthError(error)) {\n const refreshed = await attemptRefresh(userStore, options.refreshTokenHandler);\n if (refreshed) {\n const retryBatch = createAppBatch<TApi>(options);\n return await fn(retryBatch);\n }\n await pushToLogout();\n throw error;\n }\n throw error;\n }\n}\n\n/**\n * Create a tracked RPC session that appends method names to URL\n */\nfunction createTrackedSession<T extends Record<string, any> = DragoncoreApi>(\n request: Request,\n trackedSegment?: string,\n): RpcStub<T> {\n const baseUrl = request.url;\n // If trackedSegment is provided then we dont need to do any ofteh complex proxy stuff, append the segment to the url and return the batch\n if (trackedSegment) {\n return newHttpBatchRpcSession<T>(\n new Request(`${baseUrl}/${trackedSegment}`, {\n method: request.method,\n headers: request.headers,\n credentials: request.credentials,\n }),\n );\n }\n\n function createProxy(path: string[] = []): any {\n return new Proxy(() => {}, {\n get(_target, prop) {\n if (typeof prop === 'string') {\n return createProxy([...path, prop]);\n }\n return undefined;\n },\n\n apply(_target, _thisArg, args) {\n // Build the full method path (e.g., \"teams.getUserTeams\")\n const fullPath = path.join('.');\n\n // Clone the request with updated URL\n const trackedRequest = new Request(`${baseUrl}/${fullPath}`, {\n method: request.method,\n headers: request.headers,\n credentials: request.credentials,\n });\n\n // Create batch with the tracked URL\n const batch = newHttpBatchRpcSession<T>(trackedRequest);\n\n // Navigate to the right method on the batch\n let method: any = batch;\n for (const segment of path) {\n method = method[segment];\n }\n\n // Call with original arguments\n return method(...args);\n },\n });\n }\n\n return createProxy() as RpcStub<T>;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dragonmastery/dragoncore-vue",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "description": "Vue 3 components and composables for dragoncore",
5
5
  "author": "DragonMastery",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -41,7 +41,7 @@
41
41
  "vue3-toastify": "0.2.8"
42
42
  },
43
43
  "peerDependencies": {
44
- "@dragonmastery/dragoncore-shared": "^0.0.21",
44
+ "@dragonmastery/dragoncore-shared": "^0.0.22",
45
45
  "@dragonmastery/zinia-forms-core": ">=0.5.11",
46
46
  "@vueuse/core": ">=14.0.0",
47
47
  "pinia": ">=3.0.0",
@@ -1,6 +0,0 @@
1
- import "./useRpcAuth-rmHf7bYx.js";
2
- import "./useQueryCache-Bjm-S8v5.js";
3
- import "./useMutation-BTsyHKyn.js";
4
- import { t as ChangePasswordPage_default } from "./ChangePasswordPage--3XwluwE.js";
5
-
6
- export { ChangePasswordPage_default as default };
@@ -1,35 +0,0 @@
1
- import "./useRpcAuth-rmHf7bYx.js";
2
- import "./useQueryCache-Bjm-S8v5.js";
3
- import "./useMutation-BTsyHKyn.js";
4
- import "./useQuery-BggIE52P.js";
5
- import { mt as CreateTeamForm_default } from "./src-QZJyMfGX.js";
6
- import "./AppLink-CHMMrSFI.js";
7
- import "./TimelineSystemEvent-BHzFr46C.js";
8
- import "./TeamMembersTab-4gmnP9sD.js";
9
- import "./Appearance-DxWTyx1M.js";
10
- import "./useSignupPendingData-BWHwUHhL.js";
11
- import "./useBreadcrumbs-qB6ghsAf.js";
12
- import "./EditTeamMemberForm-CaS2GLjV.js";
13
- import "./RecordVersionViewer-BWZ78vvE.js";
14
- import "./TeamHistoryTab-D5biUPmq.js";
15
- import "./UserProfilePage-C3b93Keh.js";
16
- import "./ChangePasswordPage--3XwluwE.js";
17
- import "./TeamNotesTab-BzGZZ1h8.js";
18
- import "./CustomerSupportTicketParent-HIxwSVdu.js";
19
- import "./SupportTicketDevLifecycleBadge-EMrQHfyG.js";
20
- import "./StaffSupportTicketParent-CilR4RGM.js";
21
- import "./LoginForm-9UFnA-fO.js";
22
- import "./useEmailVerificationChannel-BNi926Ho.js";
23
- import "./Signup-9TjMMnU4.js";
24
- import "./ForgotPassword-OjIPi9s9.js";
25
- import "./ResetPassword-BE4mXK9q.js";
26
- import "./Logout-YgTgOFUH.js";
27
- import "./mfaSchema-BnRWf0ma.js";
28
- import "./MfaSetup-RtFMY_dj.js";
29
- import "./MfaVerify-Cvhe8bEM.js";
30
- import "./VerifyEmail-DlOmWGG-.js";
31
- import "./UserListPage-DUE5gJTo.js";
32
- import "./CreateUserPage-DLwXeLAq.js";
33
- import "./EditUserPage-DURc5rmi.js";
34
-
35
- export { CreateTeamForm_default as default };