react-native-nitro-fetch 0.2.1 → 0.3.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/android/src/main/java/com/margelo/nitro/nitrofetch/AutoPrefetcher.kt +203 -45
  2. package/android/src/main/java/com/margelo/nitro/nitrofetch/NativeStorage.kt +173 -77
  3. package/ios/NativeStorage.swift +122 -28
  4. package/ios/NitroAutoPrefetcher.swift +170 -20
  5. package/ios/NitroBootstrap.mm +5 -5
  6. package/lib/module/fetch.js +10 -26
  7. package/lib/module/fetch.js.map +1 -1
  8. package/lib/module/index.js +1 -0
  9. package/lib/module/index.js.map +1 -1
  10. package/lib/module/tokenRefresh.js +105 -0
  11. package/lib/module/tokenRefresh.js.map +1 -0
  12. package/lib/typescript/src/NitroFetch.nitro.d.ts +4 -0
  13. package/lib/typescript/src/NitroFetch.nitro.d.ts.map +1 -1
  14. package/lib/typescript/src/fetch.d.ts +0 -2
  15. package/lib/typescript/src/fetch.d.ts.map +1 -1
  16. package/lib/typescript/src/index.d.ts +2 -0
  17. package/lib/typescript/src/index.d.ts.map +1 -1
  18. package/lib/typescript/src/tokenRefresh.d.ts +36 -0
  19. package/lib/typescript/src/tokenRefresh.d.ts.map +1 -0
  20. package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.cpp +13 -0
  21. package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.hpp +3 -0
  22. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNativeStorageSpec.kt +12 -0
  23. package/nitrogen/generated/ios/c++/HybridNativeStorageSpecSwift.hpp +20 -0
  24. package/nitrogen/generated/ios/swift/HybridNativeStorageSpec.swift +3 -0
  25. package/nitrogen/generated/ios/swift/HybridNativeStorageSpec_cxx.swift +34 -0
  26. package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.cpp +3 -0
  27. package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.hpp +3 -0
  28. package/package.json +2 -2
  29. package/src/NitroFetch.nitro.ts +4 -0
  30. package/src/fetch.ts +10 -27
  31. package/src/index.tsx +9 -0
  32. package/src/tokenRefresh.ts +160 -0
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+
3
+ import { NativeStorage as NativeStorageSingleton } from "./NitroInstances.js";
4
+
5
+ // Storage keys
6
+ const KEY_WS = 'nitro_token_refresh_websocket';
7
+ const KEY_FETCH = 'nitro_token_refresh_fetch';
8
+ const KEY_WS_CACHE = 'nitro_token_refresh_ws_cache';
9
+ const KEY_FETCH_CACHE = 'nitro_token_refresh_fetch_cache';
10
+ // — Helpers —
11
+
12
+ /**
13
+ * Resolve a dot-notation path inside a parsed JSON object.
14
+ */
15
+ export function getNestedField(obj, dotPath) {
16
+ const parts = dotPath.split('.');
17
+ let current = obj;
18
+ for (const part of parts) {
19
+ if (current == null || typeof current !== 'object') return undefined;
20
+ current = current[part];
21
+ }
22
+ return current != null ? String(current) : undefined;
23
+ }
24
+ export function applyTemplate(template, value) {
25
+ return template.replace(/\{\{value\}\}/g, value);
26
+ }
27
+ function applyCompositeTemplate(template, values) {
28
+ return template.replace(/\{\{(\w+)\}\}/g, (_, key) => values[key] ?? '');
29
+ }
30
+ export async function callRefreshEndpoint(config) {
31
+ const method = config.method ?? 'POST';
32
+ const response = await fetch(config.url, {
33
+ method,
34
+ headers: config.headers,
35
+ body: config.body
36
+ });
37
+ if (!response.ok) {
38
+ throw new Error(`Token refresh failed: ${response.status} ${response.statusText}`);
39
+ }
40
+ const headers = {};
41
+ if (config.responseType === 'text') {
42
+ const text = await response.text();
43
+ if (config.textHeader) {
44
+ headers[config.textHeader] = config.textTemplate ? applyTemplate(config.textTemplate, text) : text;
45
+ }
46
+ return headers;
47
+ }
48
+
49
+ // Default: json
50
+ const json = await response.json();
51
+ if (config.mappings) {
52
+ for (const mapping of config.mappings) {
53
+ const value = getNestedField(json, mapping.jsonPath);
54
+ if (value != null) {
55
+ headers[mapping.header] = mapping.valueTemplate ? applyTemplate(mapping.valueTemplate, value) : value;
56
+ }
57
+ }
58
+ }
59
+ if (config.compositeHeaders) {
60
+ for (const comp of config.compositeHeaders) {
61
+ const values = {};
62
+ for (const [placeholder, jsonPath] of Object.entries(comp.paths)) {
63
+ const val = getNestedField(json, jsonPath);
64
+ if (val != null) values[placeholder] = val;
65
+ }
66
+ headers[comp.header] = applyCompositeTemplate(comp.template, values);
67
+ }
68
+ }
69
+ return headers;
70
+ }
71
+ export function registerTokenRefresh(options) {
72
+ const {
73
+ target,
74
+ ...config
75
+ } = options;
76
+ const raw = JSON.stringify(config);
77
+ if (target === 'websocket' || target === 'all') {
78
+ NativeStorageSingleton.setSecureString(KEY_WS, raw);
79
+ }
80
+ if (target === 'fetch' || target === 'all') {
81
+ NativeStorageSingleton.setSecureString(KEY_FETCH, raw);
82
+ }
83
+ }
84
+ export function clearTokenRefresh(target) {
85
+ const t = target ?? 'all';
86
+ if (t === 'websocket' || t === 'all') {
87
+ NativeStorageSingleton.removeSecureString(KEY_WS);
88
+ NativeStorageSingleton.removeSecureString(KEY_WS_CACHE);
89
+ }
90
+ if (t === 'fetch' || t === 'all') {
91
+ NativeStorageSingleton.removeSecureString(KEY_FETCH);
92
+ NativeStorageSingleton.removeSecureString(KEY_FETCH_CACHE);
93
+ }
94
+ }
95
+ export function getStoredTokenRefreshConfig(target) {
96
+ const key = target === 'websocket' ? KEY_WS : KEY_FETCH;
97
+ try {
98
+ const raw = NativeStorageSingleton.getSecureString(key);
99
+ if (!raw) return null;
100
+ return JSON.parse(raw);
101
+ } catch {
102
+ return null;
103
+ }
104
+ }
105
+ //# sourceMappingURL=tokenRefresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeStorage","NativeStorageSingleton","KEY_WS","KEY_FETCH","KEY_WS_CACHE","KEY_FETCH_CACHE","getNestedField","obj","dotPath","parts","split","current","part","undefined","String","applyTemplate","template","value","replace","applyCompositeTemplate","values","_","key","callRefreshEndpoint","config","method","response","fetch","url","headers","body","ok","Error","status","statusText","responseType","text","textHeader","textTemplate","json","mappings","mapping","jsonPath","header","valueTemplate","compositeHeaders","comp","placeholder","Object","entries","paths","val","registerTokenRefresh","options","target","raw","JSON","stringify","setSecureString","clearTokenRefresh","t","removeSecureString","getStoredTokenRefreshConfig","getSecureString","parse"],"sourceRoot":"../../src","sources":["tokenRefresh.ts"],"mappings":"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","ignoreList":[]}
@@ -54,5 +54,9 @@ export interface NativeStorage extends HybridObject<{
54
54
  getString(key: string): string;
55
55
  setString(key: string, value: string): void;
56
56
  removeString(key: string): void;
57
+ /** AES-GCM at rest in the same prefs/suite as getString; key material in Keystore / Keychain. */
58
+ getSecureString(key: string): string;
59
+ setSecureString(key: string, value: string): void;
60
+ removeSecureString(key: string): void;
57
61
  }
58
62
  //# sourceMappingURL=NitroFetch.nitro.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NitroFetch.nitro.d.ts","sourceRoot":"","sources":["../../../src/NitroFetch.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG/D,MAAM,MAAM,kBAAkB,GAC1B,KAAK,GACL,MAAM,GACN,MAAM,GACN,KAAK,GACL,OAAO,GACP,QAAQ,GACR,SAAS,CAAC;AAEd,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAE5B,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IAExB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAEnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;IAEvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAiB,SAAQ,YAAY,CAAC;IACrD,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IAEA,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEnD,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG3C,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,aAAa,CAAC;IAG9C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,UAAW,SAAQ,YAAY,CAAC;IAC/C,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IAEA,YAAY,IAAI,gBAAgB,CAAC;CAIlC;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY,CAAC;IAClD,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IACA,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC"}
1
+ {"version":3,"file":"NitroFetch.nitro.d.ts","sourceRoot":"","sources":["../../../src/NitroFetch.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG/D,MAAM,MAAM,kBAAkB,GAC1B,KAAK,GACL,MAAM,GACN,MAAM,GACN,KAAK,GACL,OAAO,GACP,QAAQ,GACR,SAAS,CAAC;AAEd,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAE5B,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IAExB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAEnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;IAEvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAiB,SAAQ,YAAY,CAAC;IACrD,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IAEA,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEnD,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG3C,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,aAAa,CAAC;IAG9C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,UAAW,SAAQ,YAAY,CAAC;IAC/C,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IAEA,YAAY,IAAI,gBAAgB,CAAC;CAIlC;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY,CAAC;IAClD,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IACA,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,iGAAiG;IACjG,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAClD,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC"}
@@ -24,7 +24,5 @@ export declare function nitroFetchOnWorklet<T>(input: RequestInfo | URL, init: R
24
24
  preferBytes?: boolean;
25
25
  runtimeName?: string;
26
26
  }): Promise<T>;
27
- export declare const x: any;
28
- export declare const y: any;
29
27
  export type { NitroFormDataPart, NitroRequest, NitroResponse, } from './NitroFetch.nitro';
30
28
  //# sourceMappingURL=fetch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAGV,WAAW,EACX,YAAY,EAEb,MAAM,oBAAoB,CAAC;AAiS5B,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GACjB,YAAY,CAwCd;AAkND,wBAAsB,UAAU,CAC9B,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GACxC,OAAO,CAAC,QAAQ,CAAC,CA0BnB;AAGD,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAGD,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CAAC,IAAI,CAAC,CAkDf;AAGD,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAsBf;AAGD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAG/D;AAGD,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,KAAK,CAAC,CAAC;AA4BR,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC,EACjC,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD,OAAO,CAAC,CAAC,CAAC,CA8CZ;AAED,eAAO,MAAM,CAAC,KAAyB,CAAC;AACxC,eAAO,MAAM,CAAC,KAAgB,CAAC;AAE/B,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,aAAa,GACd,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAGV,WAAW,EACX,YAAY,EAEb,MAAM,oBAAoB,CAAC;AAiS5B,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GACjB,YAAY,CAwCd;AAkND,wBAAsB,UAAU,CAC9B,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GACxC,OAAO,CAAC,QAAQ,CAAC,CA0BnB;AAGD,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAGD,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CAAC,IAAI,CAAC,CAkDf;AAGD,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAsBf;AAGD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAG/D;AAGD,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,KAAK,CAAC,CAAC;AAcR,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC,EACjC,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD,OAAO,CAAC,CAAC,CAAC,CA8CZ;AAED,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,aAAa,GACd,MAAM,oBAAoB,CAAC"}
@@ -1,6 +1,8 @@
1
1
  export { nitroFetch as fetch, nitroFetchOnWorklet, prefetch, prefetchOnAppStart, removeFromAutoPrefetch, removeAllFromAutoprefetch, } from './fetch';
2
2
  export type { NitroFormDataPart, NitroRequest, NitroResponse } from './fetch';
3
3
  export { NitroFetch } from './NitroInstances';
4
+ export { registerTokenRefresh, clearTokenRefresh, callRefreshEndpoint, getStoredTokenRefreshConfig, getNestedField, applyTemplate, } from './tokenRefresh';
5
+ export type { TokenRefreshConfig } from './tokenRefresh';
4
6
  import './fetch';
5
7
  export declare function multiply(a: number, b: number): number;
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,IAAI,KAAK,EACnB,mBAAmB,EACnB,QAAQ,EACR,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,SAAS,CAAC;AAIjB,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAErD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,IAAI,KAAK,EACnB,mBAAmB,EACnB,QAAQ,EACR,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,2BAA2B,EAC3B,cAAc,EACd,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,SAAS,CAAC;AAIjB,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAErD"}
@@ -0,0 +1,36 @@
1
+ type TokenRefreshTarget = 'websocket' | 'fetch' | 'all';
2
+ type TokenRefreshJsonMapping = {
3
+ jsonPath: string;
4
+ header: string;
5
+ valueTemplate?: string;
6
+ };
7
+ type TokenRefreshCompositeHeader = {
8
+ header: string;
9
+ template: string;
10
+ paths: Record<string, string>;
11
+ };
12
+ export type TokenRefreshConfig = {
13
+ url: string;
14
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH';
15
+ headers?: Record<string, string>;
16
+ body?: string;
17
+ responseType?: 'json' | 'text';
18
+ mappings?: TokenRefreshJsonMapping[];
19
+ compositeHeaders?: TokenRefreshCompositeHeader[];
20
+ textHeader?: string;
21
+ textTemplate?: string;
22
+ onFailure?: 'skip' | 'useStoredHeaders';
23
+ };
24
+ /**
25
+ * Resolve a dot-notation path inside a parsed JSON object.
26
+ */
27
+ export declare function getNestedField(obj: unknown, dotPath: string): string | undefined;
28
+ export declare function applyTemplate(template: string, value: string): string;
29
+ export declare function callRefreshEndpoint(config: TokenRefreshConfig): Promise<Record<string, string>>;
30
+ export declare function registerTokenRefresh(options: {
31
+ target: TokenRefreshTarget;
32
+ } & TokenRefreshConfig): void;
33
+ export declare function clearTokenRefresh(target?: TokenRefreshTarget): void;
34
+ export declare function getStoredTokenRefreshConfig(target: 'websocket' | 'fetch'): TokenRefreshConfig | null;
35
+ export {};
36
+ //# sourceMappingURL=tokenRefresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenRefresh.d.ts","sourceRoot":"","sources":["../../../src/tokenRefresh.ts"],"names":[],"mappings":"AAQA,KAAK,kBAAkB,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,CAAC;AAExD,KAAK,uBAAuB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACrC,gBAAgB,CAAC,EAAE,2BAA2B,EAAE,CAAC;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAC;CACzC,CAAC;AAIF;;GAEG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAQpB;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAErE;AAYD,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAoDjC;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE;IAAE,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAAG,kBAAkB,GAC3D,IAAI,CASN;AAED,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAUnE;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,WAAW,GAAG,OAAO,GAC5B,kBAAkB,GAAG,IAAI,CAS3B"}
@@ -57,5 +57,18 @@ namespace margelo::nitro::nitrofetch {
57
57
  static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* key */)>("removeString");
58
58
  method(_javaPart, jni::make_jstring(key));
59
59
  }
60
+ std::string JHybridNativeStorageSpec::getSecureString(const std::string& key) {
61
+ static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>(jni::alias_ref<jni::JString> /* key */)>("getSecureString");
62
+ auto __result = method(_javaPart, jni::make_jstring(key));
63
+ return __result->toStdString();
64
+ }
65
+ void JHybridNativeStorageSpec::setSecureString(const std::string& key, const std::string& value) {
66
+ static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* key */, jni::alias_ref<jni::JString> /* value */)>("setSecureString");
67
+ method(_javaPart, jni::make_jstring(key), jni::make_jstring(value));
68
+ }
69
+ void JHybridNativeStorageSpec::removeSecureString(const std::string& key) {
70
+ static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* key */)>("removeSecureString");
71
+ method(_javaPart, jni::make_jstring(key));
72
+ }
60
73
 
61
74
  } // namespace margelo::nitro::nitrofetch
@@ -57,6 +57,9 @@ namespace margelo::nitro::nitrofetch {
57
57
  std::string getString(const std::string& key) override;
58
58
  void setString(const std::string& key, const std::string& value) override;
59
59
  void removeString(const std::string& key) override;
60
+ std::string getSecureString(const std::string& key) override;
61
+ void setSecureString(const std::string& key, const std::string& value) override;
62
+ void removeSecureString(const std::string& key) override;
60
63
 
61
64
  private:
62
65
  jni::global_ref<JHybridNativeStorageSpec::JavaPart> _javaPart;
@@ -39,6 +39,18 @@ abstract class HybridNativeStorageSpec: HybridObject() {
39
39
  @DoNotStrip
40
40
  @Keep
41
41
  abstract fun removeString(key: String): Unit
42
+
43
+ @DoNotStrip
44
+ @Keep
45
+ abstract fun getSecureString(key: String): String
46
+
47
+ @DoNotStrip
48
+ @Keep
49
+ abstract fun setSecureString(key: String, value: String): Unit
50
+
51
+ @DoNotStrip
52
+ @Keep
53
+ abstract fun removeSecureString(key: String): Unit
42
54
 
43
55
  // Default implementation of `HybridObject.toString()`
44
56
  override fun toString(): String {
@@ -86,6 +86,26 @@ namespace margelo::nitro::nitrofetch {
86
86
  std::rethrow_exception(__result.error());
87
87
  }
88
88
  }
89
+ inline std::string getSecureString(const std::string& key) override {
90
+ auto __result = _swiftPart.getSecureString(key);
91
+ if (__result.hasError()) [[unlikely]] {
92
+ std::rethrow_exception(__result.error());
93
+ }
94
+ auto __value = std::move(__result.value());
95
+ return __value;
96
+ }
97
+ inline void setSecureString(const std::string& key, const std::string& value) override {
98
+ auto __result = _swiftPart.setSecureString(key, value);
99
+ if (__result.hasError()) [[unlikely]] {
100
+ std::rethrow_exception(__result.error());
101
+ }
102
+ }
103
+ inline void removeSecureString(const std::string& key) override {
104
+ auto __result = _swiftPart.removeSecureString(key);
105
+ if (__result.hasError()) [[unlikely]] {
106
+ std::rethrow_exception(__result.error());
107
+ }
108
+ }
89
109
 
90
110
  private:
91
111
  NitroFetch::HybridNativeStorageSpec_cxx _swiftPart;
@@ -16,6 +16,9 @@ public protocol HybridNativeStorageSpec_protocol: HybridObject {
16
16
  func getString(key: String) throws -> String
17
17
  func setString(key: String, value: String) throws -> Void
18
18
  func removeString(key: String) throws -> Void
19
+ func getSecureString(key: String) throws -> String
20
+ func setSecureString(key: String, value: String) throws -> Void
21
+ func removeSecureString(key: String) throws -> Void
19
22
  }
20
23
 
21
24
  public extension HybridNativeStorageSpec_protocol {
@@ -157,4 +157,38 @@ open class HybridNativeStorageSpec_cxx {
157
157
  return bridge.create_Result_void_(__exceptionPtr)
158
158
  }
159
159
  }
160
+
161
+ @inline(__always)
162
+ public final func getSecureString(key: std.string) -> bridge.Result_std__string_ {
163
+ do {
164
+ let __result = try self.__implementation.getSecureString(key: String(key))
165
+ let __resultCpp = std.string(__result)
166
+ return bridge.create_Result_std__string_(__resultCpp)
167
+ } catch (let __error) {
168
+ let __exceptionPtr = __error.toCpp()
169
+ return bridge.create_Result_std__string_(__exceptionPtr)
170
+ }
171
+ }
172
+
173
+ @inline(__always)
174
+ public final func setSecureString(key: std.string, value: std.string) -> bridge.Result_void_ {
175
+ do {
176
+ try self.__implementation.setSecureString(key: String(key), value: String(value))
177
+ return bridge.create_Result_void_()
178
+ } catch (let __error) {
179
+ let __exceptionPtr = __error.toCpp()
180
+ return bridge.create_Result_void_(__exceptionPtr)
181
+ }
182
+ }
183
+
184
+ @inline(__always)
185
+ public final func removeSecureString(key: std.string) -> bridge.Result_void_ {
186
+ do {
187
+ try self.__implementation.removeSecureString(key: String(key))
188
+ return bridge.create_Result_void_()
189
+ } catch (let __error) {
190
+ let __exceptionPtr = __error.toCpp()
191
+ return bridge.create_Result_void_(__exceptionPtr)
192
+ }
193
+ }
160
194
  }
@@ -17,6 +17,9 @@ namespace margelo::nitro::nitrofetch {
17
17
  prototype.registerHybridMethod("getString", &HybridNativeStorageSpec::getString);
18
18
  prototype.registerHybridMethod("setString", &HybridNativeStorageSpec::setString);
19
19
  prototype.registerHybridMethod("removeString", &HybridNativeStorageSpec::removeString);
20
+ prototype.registerHybridMethod("getSecureString", &HybridNativeStorageSpec::getSecureString);
21
+ prototype.registerHybridMethod("setSecureString", &HybridNativeStorageSpec::setSecureString);
22
+ prototype.registerHybridMethod("removeSecureString", &HybridNativeStorageSpec::removeSecureString);
20
23
  });
21
24
  }
22
25
 
@@ -51,6 +51,9 @@ namespace margelo::nitro::nitrofetch {
51
51
  virtual std::string getString(const std::string& key) = 0;
52
52
  virtual void setString(const std::string& key, const std::string& value) = 0;
53
53
  virtual void removeString(const std::string& key) = 0;
54
+ virtual std::string getSecureString(const std::string& key) = 0;
55
+ virtual void setSecureString(const std::string& key, const std::string& value) = 0;
56
+ virtual void removeSecureString(const std::string& key) = 0;
54
57
 
55
58
  protected:
56
59
  // Hybrid Setup
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-fetch",
3
- "version": "0.2.1",
3
+ "version": "0.3.0-beta.0",
4
4
  "description": "Awesome Fetch :)",
5
5
  "main": "./lib/module/index.js",
6
6
  "module": "./lib/module/index.js",
@@ -94,7 +94,7 @@
94
94
  "react": "*",
95
95
  "react-native": "*",
96
96
  "react-native-nitro-modules": "^0.35.2",
97
- "react-native-worklets-core": "^1.6.0"
97
+ "react-native-worklets": "^0.8.0"
98
98
  },
99
99
  "peerDependenciesMeta": {
100
100
  "react-native-worklets-core": {
@@ -86,4 +86,8 @@ export interface NativeStorage extends HybridObject<{
86
86
  getString(key: string): string;
87
87
  setString(key: string, value: string): void;
88
88
  removeString(key: string): void;
89
+ /** AES-GCM at rest in the same prefs/suite as getString; key material in Keystore / Keychain. */
90
+ getSecureString(key: string): string;
91
+ setSecureString(key: string, value: string): void;
92
+ removeSecureString(key: string): void;
89
93
  }
package/src/fetch.ts CHANGED
@@ -714,11 +714,10 @@ export type NitroWorkletMapper<T> = (payload: {
714
714
  }) => T;
715
715
 
716
716
  let nitroRuntime: any | undefined;
717
- let WorkletsRef: any | undefined;
718
717
  function ensureWorkletRuntime(name = 'nitro-fetch'): any | undefined {
719
718
  try {
720
- const { Worklets } = require('react-native-worklets-core');
721
- nitroRuntime = nitroRuntime ?? Worklets.createContext(name);
719
+ const { createWorkletRuntime } = require('react-native-worklets');
720
+ nitroRuntime = nitroRuntime ?? createWorkletRuntime(name);
722
721
  return nitroRuntime;
723
722
  } catch {
724
723
  console.warn('react-native-worklets-core not available');
@@ -726,19 +725,6 @@ function ensureWorkletRuntime(name = 'nitro-fetch'): any | undefined {
726
725
  }
727
726
  }
728
727
 
729
- function getWorklets(): any | undefined {
730
- try {
731
- if (WorkletsRef) return WorkletsRef;
732
-
733
- const { Worklets } = require('react-native-worklets-core');
734
- WorkletsRef = Worklets;
735
- return WorkletsRef;
736
- } catch {
737
- console.warn('react-native-worklets-core not available');
738
- return undefined;
739
- }
740
- }
741
-
742
728
  export async function nitroFetchOnWorklet<T>(
743
729
  input: RequestInfo | URL,
744
730
  init: RequestInit | undefined,
@@ -746,17 +732,17 @@ export async function nitroFetchOnWorklet<T>(
746
732
  options?: { preferBytes?: boolean; runtimeName?: string }
747
733
  ): Promise<T> {
748
734
  const preferBytes = options?.preferBytes === true; // default true
749
- let rt: any | undefined;
750
- let Worklets: any | undefined;
735
+ let runOnRuntimeAsync: any;
736
+ let rt: any;
751
737
  try {
752
738
  rt = ensureWorkletRuntime(options?.runtimeName);
753
- Worklets = getWorklets();
754
- } catch (e) {
755
- console.error('nitroFetchOnWorklet: setup failed', e);
739
+ const worklets = require('react-native-worklets');
740
+ runOnRuntimeAsync = worklets.runOnRuntimeAsync;
741
+ } catch {
742
+ // Module not available
756
743
  }
757
-
758
744
  // Fallback: if runtime is not available, do the work on JS
759
- if (!rt || !Worklets || typeof rt.runAsync !== 'function') {
745
+ if (!runOnRuntimeAsync || !rt) {
760
746
  console.warn('nitroFetchOnWorklet: no runtime, mapping on JS thread');
761
747
  const res = await nitroFetchRaw(input, init);
762
748
  const payload = {
@@ -771,7 +757,7 @@ export async function nitroFetchOnWorklet<T>(
771
757
  } as const;
772
758
  return mapWorklet(payload as any);
773
759
  }
774
- return await rt.runAsync(() => {
760
+ return await runOnRuntimeAsync(rt, () => {
775
761
  'worklet';
776
762
  const unboxedNitroFetch = boxedNitroFetch.unbox();
777
763
  const unboxedClient = unboxedNitroFetch.createClient();
@@ -792,9 +778,6 @@ export async function nitroFetchOnWorklet<T>(
792
778
  });
793
779
  }
794
780
 
795
- export const x = ensureWorkletRuntime();
796
- export const y = getWorklets();
797
-
798
781
  export type {
799
782
  NitroFormDataPart,
800
783
  NitroRequest,
package/src/index.tsx CHANGED
@@ -8,6 +8,15 @@ export {
8
8
  } from './fetch';
9
9
  export type { NitroFormDataPart, NitroRequest, NitroResponse } from './fetch';
10
10
  export { NitroFetch } from './NitroInstances';
11
+ export {
12
+ registerTokenRefresh,
13
+ clearTokenRefresh,
14
+ callRefreshEndpoint,
15
+ getStoredTokenRefreshConfig,
16
+ getNestedField,
17
+ applyTemplate,
18
+ } from './tokenRefresh';
19
+ export type { TokenRefreshConfig } from './tokenRefresh';
11
20
  import './fetch';
12
21
 
13
22
  // Keep legacy export to avoid breaking any local tests/usages during scaffolding.
@@ -0,0 +1,160 @@
1
+ import { NativeStorage as NativeStorageSingleton } from './NitroInstances';
2
+
3
+ // Storage keys
4
+ const KEY_WS = 'nitro_token_refresh_websocket';
5
+ const KEY_FETCH = 'nitro_token_refresh_fetch';
6
+ const KEY_WS_CACHE = 'nitro_token_refresh_ws_cache';
7
+ const KEY_FETCH_CACHE = 'nitro_token_refresh_fetch_cache';
8
+
9
+ type TokenRefreshTarget = 'websocket' | 'fetch' | 'all';
10
+
11
+ type TokenRefreshJsonMapping = {
12
+ jsonPath: string;
13
+ header: string;
14
+ valueTemplate?: string;
15
+ };
16
+
17
+ type TokenRefreshCompositeHeader = {
18
+ header: string;
19
+ template: string;
20
+ paths: Record<string, string>;
21
+ };
22
+
23
+ export type TokenRefreshConfig = {
24
+ url: string;
25
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH';
26
+ headers?: Record<string, string>;
27
+ body?: string;
28
+ responseType?: 'json' | 'text';
29
+ mappings?: TokenRefreshJsonMapping[];
30
+ compositeHeaders?: TokenRefreshCompositeHeader[];
31
+ textHeader?: string;
32
+ textTemplate?: string;
33
+ onFailure?: 'skip' | 'useStoredHeaders';
34
+ };
35
+
36
+ // — Helpers —
37
+
38
+ /**
39
+ * Resolve a dot-notation path inside a parsed JSON object.
40
+ */
41
+ export function getNestedField(
42
+ obj: unknown,
43
+ dotPath: string
44
+ ): string | undefined {
45
+ const parts = dotPath.split('.');
46
+ let current: unknown = obj;
47
+ for (const part of parts) {
48
+ if (current == null || typeof current !== 'object') return undefined;
49
+ current = (current as Record<string, unknown>)[part];
50
+ }
51
+ return current != null ? String(current) : undefined;
52
+ }
53
+
54
+ export function applyTemplate(template: string, value: string): string {
55
+ return template.replace(/\{\{value\}\}/g, value);
56
+ }
57
+
58
+ function applyCompositeTemplate(
59
+ template: string,
60
+ values: Record<string, string>
61
+ ): string {
62
+ return template.replace(
63
+ /\{\{(\w+)\}\}/g,
64
+ (_: string, key: string) => values[key] ?? ''
65
+ );
66
+ }
67
+
68
+ export async function callRefreshEndpoint(
69
+ config: TokenRefreshConfig
70
+ ): Promise<Record<string, string>> {
71
+ const method = config.method ?? 'POST';
72
+ const response = await fetch(config.url, {
73
+ method,
74
+ headers: config.headers,
75
+ body: config.body,
76
+ });
77
+
78
+ if (!response.ok) {
79
+ throw new Error(
80
+ `Token refresh failed: ${response.status} ${response.statusText}`
81
+ );
82
+ }
83
+
84
+ const headers: Record<string, string> = {};
85
+
86
+ if (config.responseType === 'text') {
87
+ const text = await response.text();
88
+ if (config.textHeader) {
89
+ headers[config.textHeader] = config.textTemplate
90
+ ? applyTemplate(config.textTemplate, text)
91
+ : text;
92
+ }
93
+ return headers;
94
+ }
95
+
96
+ // Default: json
97
+ const json = await response.json();
98
+
99
+ if (config.mappings) {
100
+ for (const mapping of config.mappings) {
101
+ const value = getNestedField(json, mapping.jsonPath);
102
+ if (value != null) {
103
+ headers[mapping.header] = mapping.valueTemplate
104
+ ? applyTemplate(mapping.valueTemplate, value)
105
+ : value;
106
+ }
107
+ }
108
+ }
109
+
110
+ if (config.compositeHeaders) {
111
+ for (const comp of config.compositeHeaders) {
112
+ const values: Record<string, string> = {};
113
+ for (const [placeholder, jsonPath] of Object.entries(comp.paths)) {
114
+ const val = getNestedField(json, jsonPath);
115
+ if (val != null) values[placeholder] = val;
116
+ }
117
+ headers[comp.header] = applyCompositeTemplate(comp.template, values);
118
+ }
119
+ }
120
+
121
+ return headers;
122
+ }
123
+
124
+ export function registerTokenRefresh(
125
+ options: { target: TokenRefreshTarget } & TokenRefreshConfig
126
+ ): void {
127
+ const { target, ...config } = options;
128
+ const raw = JSON.stringify(config);
129
+ if (target === 'websocket' || target === 'all') {
130
+ NativeStorageSingleton.setSecureString(KEY_WS, raw);
131
+ }
132
+ if (target === 'fetch' || target === 'all') {
133
+ NativeStorageSingleton.setSecureString(KEY_FETCH, raw);
134
+ }
135
+ }
136
+
137
+ export function clearTokenRefresh(target?: TokenRefreshTarget): void {
138
+ const t = target ?? 'all';
139
+ if (t === 'websocket' || t === 'all') {
140
+ NativeStorageSingleton.removeSecureString(KEY_WS);
141
+ NativeStorageSingleton.removeSecureString(KEY_WS_CACHE);
142
+ }
143
+ if (t === 'fetch' || t === 'all') {
144
+ NativeStorageSingleton.removeSecureString(KEY_FETCH);
145
+ NativeStorageSingleton.removeSecureString(KEY_FETCH_CACHE);
146
+ }
147
+ }
148
+
149
+ export function getStoredTokenRefreshConfig(
150
+ target: 'websocket' | 'fetch'
151
+ ): TokenRefreshConfig | null {
152
+ const key = target === 'websocket' ? KEY_WS : KEY_FETCH;
153
+ try {
154
+ const raw = NativeStorageSingleton.getSecureString(key);
155
+ if (!raw) return null;
156
+ return JSON.parse(raw) as TokenRefreshConfig;
157
+ } catch {
158
+ return null;
159
+ }
160
+ }