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.
- package/android/src/main/java/com/margelo/nitro/nitrofetch/AutoPrefetcher.kt +203 -45
- package/android/src/main/java/com/margelo/nitro/nitrofetch/NativeStorage.kt +173 -77
- package/ios/NativeStorage.swift +122 -28
- package/ios/NitroAutoPrefetcher.swift +170 -20
- package/ios/NitroBootstrap.mm +5 -5
- package/lib/module/fetch.js +10 -26
- package/lib/module/fetch.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/tokenRefresh.js +105 -0
- package/lib/module/tokenRefresh.js.map +1 -0
- package/lib/typescript/src/NitroFetch.nitro.d.ts +4 -0
- package/lib/typescript/src/NitroFetch.nitro.d.ts.map +1 -1
- package/lib/typescript/src/fetch.d.ts +0 -2
- package/lib/typescript/src/fetch.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/tokenRefresh.d.ts +36 -0
- package/lib/typescript/src/tokenRefresh.d.ts.map +1 -0
- package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.cpp +13 -0
- package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.hpp +3 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNativeStorageSpec.kt +12 -0
- package/nitrogen/generated/ios/c++/HybridNativeStorageSpecSwift.hpp +20 -0
- package/nitrogen/generated/ios/swift/HybridNativeStorageSpec.swift +3 -0
- package/nitrogen/generated/ios/swift/HybridNativeStorageSpec_cxx.swift +34 -0
- package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.cpp +3 -0
- package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.hpp +3 -0
- package/package.json +2 -2
- package/src/NitroFetch.nitro.ts +4 -0
- package/src/fetch.ts +10 -27
- package/src/index.tsx +9 -0
- 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":";;AAAA,SAASA,aAAa,IAAIC,sBAAsB,QAAQ,qBAAkB;;AAE1E;AACA,MAAMC,MAAM,GAAG,+BAA+B;AAC9C,MAAMC,SAAS,GAAG,2BAA2B;AAC7C,MAAMC,YAAY,GAAG,8BAA8B;AACnD,MAAMC,eAAe,GAAG,iCAAiC;AA6BzD;;AAEA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAC5BC,GAAY,EACZC,OAAe,EACK;EACpB,MAAMC,KAAK,GAAGD,OAAO,CAACE,KAAK,CAAC,GAAG,CAAC;EAChC,IAAIC,OAAgB,GAAGJ,GAAG;EAC1B,KAAK,MAAMK,IAAI,IAAIH,KAAK,EAAE;IACxB,IAAIE,OAAO,IAAI,IAAI,IAAI,OAAOA,OAAO,KAAK,QAAQ,EAAE,OAAOE,SAAS;IACpEF,OAAO,GAAIA,OAAO,CAA6BC,IAAI,CAAC;EACtD;EACA,OAAOD,OAAO,IAAI,IAAI,GAAGG,MAAM,CAACH,OAAO,CAAC,GAAGE,SAAS;AACtD;AAEA,OAAO,SAASE,aAAaA,CAACC,QAAgB,EAAEC,KAAa,EAAU;EACrE,OAAOD,QAAQ,CAACE,OAAO,CAAC,gBAAgB,EAAED,KAAK,CAAC;AAClD;AAEA,SAASE,sBAAsBA,CAC7BH,QAAgB,EAChBI,MAA8B,EACtB;EACR,OAAOJ,QAAQ,CAACE,OAAO,CACrB,gBAAgB,EAChB,CAACG,CAAS,EAAEC,GAAW,KAAKF,MAAM,CAACE,GAAG,CAAC,IAAI,EAC7C,CAAC;AACH;AAEA,OAAO,eAAeC,mBAAmBA,CACvCC,MAA0B,EACO;EACjC,MAAMC,MAAM,GAAGD,MAAM,CAACC,MAAM,IAAI,MAAM;EACtC,MAAMC,QAAQ,GAAG,MAAMC,KAAK,CAACH,MAAM,CAACI,GAAG,EAAE;IACvCH,MAAM;IACNI,OAAO,EAAEL,MAAM,CAACK,OAAO;IACvBC,IAAI,EAAEN,MAAM,CAACM;EACf,CAAC,CAAC;EAEF,IAAI,CAACJ,QAAQ,CAACK,EAAE,EAAE;IAChB,MAAM,IAAIC,KAAK,CACb,yBAAyBN,QAAQ,CAACO,MAAM,IAAIP,QAAQ,CAACQ,UAAU,EACjE,CAAC;EACH;EAEA,MAAML,OAA+B,GAAG,CAAC,CAAC;EAE1C,IAAIL,MAAM,CAACW,YAAY,KAAK,MAAM,EAAE;IAClC,MAAMC,IAAI,GAAG,MAAMV,QAAQ,CAACU,IAAI,CAAC,CAAC;IAClC,IAAIZ,MAAM,CAACa,UAAU,EAAE;MACrBR,OAAO,CAACL,MAAM,CAACa,UAAU,CAAC,GAAGb,MAAM,CAACc,YAAY,GAC5CvB,aAAa,CAACS,MAAM,CAACc,YAAY,EAAEF,IAAI,CAAC,GACxCA,IAAI;IACV;IACA,OAAOP,OAAO;EAChB;;EAEA;EACA,MAAMU,IAAI,GAAG,MAAMb,QAAQ,CAACa,IAAI,CAAC,CAAC;EAElC,IAAIf,MAAM,CAACgB,QAAQ,EAAE;IACnB,KAAK,MAAMC,OAAO,IAAIjB,MAAM,CAACgB,QAAQ,EAAE;MACrC,MAAMvB,KAAK,GAAGX,cAAc,CAACiC,IAAI,EAAEE,OAAO,CAACC,QAAQ,CAAC;MACpD,IAAIzB,KAAK,IAAI,IAAI,EAAE;QACjBY,OAAO,CAACY,OAAO,CAACE,MAAM,CAAC,GAAGF,OAAO,CAACG,aAAa,GAC3C7B,aAAa,CAAC0B,OAAO,CAACG,aAAa,EAAE3B,KAAK,CAAC,GAC3CA,KAAK;MACX;IACF;EACF;EAEA,IAAIO,MAAM,CAACqB,gBAAgB,EAAE;IAC3B,KAAK,MAAMC,IAAI,IAAItB,MAAM,CAACqB,gBAAgB,EAAE;MAC1C,MAAMzB,MAA8B,GAAG,CAAC,CAAC;MACzC,KAAK,MAAM,CAAC2B,WAAW,EAAEL,QAAQ,CAAC,IAAIM,MAAM,CAACC,OAAO,CAACH,IAAI,CAACI,KAAK,CAAC,EAAE;QAChE,MAAMC,GAAG,GAAG7C,cAAc,CAACiC,IAAI,EAAEG,QAAQ,CAAC;QAC1C,IAAIS,GAAG,IAAI,IAAI,EAAE/B,MAAM,CAAC2B,WAAW,CAAC,GAAGI,GAAG;MAC5C;MACAtB,OAAO,CAACiB,IAAI,CAACH,MAAM,CAAC,GAAGxB,sBAAsB,CAAC2B,IAAI,CAAC9B,QAAQ,EAAEI,MAAM,CAAC;IACtE;EACF;EAEA,OAAOS,OAAO;AAChB;AAEA,OAAO,SAASuB,oBAAoBA,CAClCC,OAA4D,EACtD;EACN,MAAM;IAAEC,MAAM;IAAE,GAAG9B;EAAO,CAAC,GAAG6B,OAAO;EACrC,MAAME,GAAG,GAAGC,IAAI,CAACC,SAAS,CAACjC,MAAM,CAAC;EAClC,IAAI8B,MAAM,KAAK,WAAW,IAAIA,MAAM,KAAK,KAAK,EAAE;IAC9CrD,sBAAsB,CAACyD,eAAe,CAACxD,MAAM,EAAEqD,GAAG,CAAC;EACrD;EACA,IAAID,MAAM,KAAK,OAAO,IAAIA,MAAM,KAAK,KAAK,EAAE;IAC1CrD,sBAAsB,CAACyD,eAAe,CAACvD,SAAS,EAAEoD,GAAG,CAAC;EACxD;AACF;AAEA,OAAO,SAASI,iBAAiBA,CAACL,MAA2B,EAAQ;EACnE,MAAMM,CAAC,GAAGN,MAAM,IAAI,KAAK;EACzB,IAAIM,CAAC,KAAK,WAAW,IAAIA,CAAC,KAAK,KAAK,EAAE;IACpC3D,sBAAsB,CAAC4D,kBAAkB,CAAC3D,MAAM,CAAC;IACjDD,sBAAsB,CAAC4D,kBAAkB,CAACzD,YAAY,CAAC;EACzD;EACA,IAAIwD,CAAC,KAAK,OAAO,IAAIA,CAAC,KAAK,KAAK,EAAE;IAChC3D,sBAAsB,CAAC4D,kBAAkB,CAAC1D,SAAS,CAAC;IACpDF,sBAAsB,CAAC4D,kBAAkB,CAACxD,eAAe,CAAC;EAC5D;AACF;AAEA,OAAO,SAASyD,2BAA2BA,CACzCR,MAA6B,EACF;EAC3B,MAAMhC,GAAG,GAAGgC,MAAM,KAAK,WAAW,GAAGpD,MAAM,GAAGC,SAAS;EACvD,IAAI;IACF,MAAMoD,GAAG,GAAGtD,sBAAsB,CAAC8D,eAAe,CAACzC,GAAG,CAAC;IACvD,IAAI,CAACiC,GAAG,EAAE,OAAO,IAAI;IACrB,OAAOC,IAAI,CAACQ,KAAK,CAACT,GAAG,CAAC;EACxB,CAAC,CAAC,MAAM;IACN,OAAO,IAAI;EACb;AACF","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;
|
|
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;
|
|
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;
|
package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNativeStorageSpec.kt
CHANGED
|
@@ -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.
|
|
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
|
|
97
|
+
"react-native-worklets": "^0.8.0"
|
|
98
98
|
},
|
|
99
99
|
"peerDependenciesMeta": {
|
|
100
100
|
"react-native-worklets-core": {
|
package/src/NitroFetch.nitro.ts
CHANGED
|
@@ -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 {
|
|
721
|
-
nitroRuntime = nitroRuntime ??
|
|
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
|
|
750
|
-
let
|
|
735
|
+
let runOnRuntimeAsync: any;
|
|
736
|
+
let rt: any;
|
|
751
737
|
try {
|
|
752
738
|
rt = ensureWorkletRuntime(options?.runtimeName);
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
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 (!
|
|
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
|
|
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
|
+
}
|