@aguacerowx/react-native 0.0.50 → 0.0.51
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/aguacerowx/reactnative/WeatherFrameProcessorModule.java +36 -0
- package/ios/WeatherFrameProcessorModule.swift +33 -2
- package/lib/commonjs/WeatherLayerManager.js +54 -6
- package/lib/commonjs/WeatherLayerManager.js.map +1 -1
- package/lib/commonjs/aguaceroCoreDebugHooks.js +144 -0
- package/lib/commonjs/aguaceroCoreDebugHooks.js.map +1 -0
- package/lib/commonjs/aguaceroRnDebug.js +351 -0
- package/lib/commonjs/aguaceroRnDebug.js.map +1 -0
- package/lib/commonjs/index.js +37 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/nexrad/nexradAndroidController.js +13 -0
- package/lib/commonjs/nexrad/nexradAndroidController.js.map +1 -1
- package/lib/commonjs/nexrad/nexradDiag.js +7 -1
- package/lib/commonjs/nexrad/nexradDiag.js.map +1 -1
- package/lib/commonjs/satellite/satelliteAndroidController.js +9 -0
- package/lib/commonjs/satellite/satelliteAndroidController.js.map +1 -1
- package/lib/module/WeatherLayerManager.js +54 -6
- package/lib/module/WeatherLayerManager.js.map +1 -1
- package/lib/module/aguaceroCoreDebugHooks.js +136 -0
- package/lib/module/aguaceroCoreDebugHooks.js.map +1 -0
- package/lib/module/aguaceroRnDebug.js +334 -0
- package/lib/module/aguaceroRnDebug.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/nexrad/nexradAndroidController.js +13 -0
- package/lib/module/nexrad/nexradAndroidController.js.map +1 -1
- package/lib/module/nexrad/nexradDiag.js +7 -1
- package/lib/module/nexrad/nexradDiag.js.map +1 -1
- package/lib/module/satellite/satelliteAndroidController.js +9 -0
- package/lib/module/satellite/satelliteAndroidController.js.map +1 -1
- package/lib/typescript/WeatherLayerManager.d.ts.map +1 -1
- package/lib/typescript/aguaceroCoreDebugHooks.d.ts +10 -0
- package/lib/typescript/aguaceroCoreDebugHooks.d.ts.map +1 -0
- package/lib/typescript/aguaceroRnDebug.d.ts +97 -0
- package/lib/typescript/aguaceroRnDebug.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/nexrad/nexradAndroidController.d.ts.map +1 -1
- package/lib/typescript/nexrad/nexradDiag.d.ts.map +1 -1
- package/lib/typescript/satellite/satelliteAndroidController.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/WeatherLayerManager.js +78 -21
- package/src/aguaceroCoreDebugHooks.js +142 -0
- package/src/aguaceroRnDebug.js +328 -0
- package/src/index.js +8 -0
- package/src/nexrad/nexradAndroidController.js +11 -1
- package/src/nexrad/nexradDiag.js +7 -1
- package/src/satellite/satelliteAndroidController.js +9 -0
|
@@ -104,6 +104,8 @@ public class WeatherFrameProcessorModule extends ReactContextBaseJavaModule {
|
|
|
104
104
|
options.hasKey("gridRequestSiteOrigin") && !options.isNull("gridRequestSiteOrigin")
|
|
105
105
|
? options.getString("gridRequestSiteOrigin")
|
|
106
106
|
: null;
|
|
107
|
+
final boolean debug =
|
|
108
|
+
options.hasKey("debug") && !options.isNull("debug") && options.getBoolean("debug");
|
|
107
109
|
|
|
108
110
|
// FIX 3: Submit to Executor instead of spinning up a raw OS thread
|
|
109
111
|
taskExecutor.execute(() -> {
|
|
@@ -141,6 +143,19 @@ public class WeatherFrameProcessorModule extends ReactContextBaseJavaModule {
|
|
|
141
143
|
}
|
|
142
144
|
Request request = requestBuilder.build();
|
|
143
145
|
|
|
146
|
+
if (debug) {
|
|
147
|
+
String redactedUrl = urlString.replaceAll("([?&])apiKey=[^&]*", "$1apiKey=(redacted)");
|
|
148
|
+
Log.w("AguaceroRN", "[debug][FrameProcessor] REQUEST "
|
|
149
|
+
+ "method=GET url=" + redactedUrl
|
|
150
|
+
+ " apiKey.len=" + (apiKey != null ? apiKey.length() : 0)
|
|
151
|
+
+ " bundleId=" + (bundleId != null && !bundleId.isEmpty() ? bundleId : "(none)")
|
|
152
|
+
+ " gridOrigin=" + (gridRequestSiteOrigin != null ? gridRequestSiteOrigin : "(none)")
|
|
153
|
+
+ " headers=[x-api-key, "
|
|
154
|
+
+ (bundleId != null && !bundleId.isEmpty() ? "x-app-identifier, " : "")
|
|
155
|
+
+ (gridRequestSiteOrigin != null ? "Origin, Referer" : "no Origin/Referer")
|
|
156
|
+
+ "]");
|
|
157
|
+
}
|
|
158
|
+
|
|
144
159
|
Call call = httpClient.newCall(request);
|
|
145
160
|
activeCalls.add(call);
|
|
146
161
|
|
|
@@ -179,6 +194,27 @@ public class WeatherFrameProcessorModule extends ReactContextBaseJavaModule {
|
|
|
179
194
|
FileOutputStream fos = null;
|
|
180
195
|
try {
|
|
181
196
|
if (!response.isSuccessful()) {
|
|
197
|
+
if (debug) {
|
|
198
|
+
String bodyPeek = "";
|
|
199
|
+
try {
|
|
200
|
+
ResponseBody peekBody = response.peekBody(512);
|
|
201
|
+
if (peekBody != null) {
|
|
202
|
+
bodyPeek = peekBody.string();
|
|
203
|
+
}
|
|
204
|
+
} catch (Exception ignored) {
|
|
205
|
+
bodyPeek = "(unreadable)";
|
|
206
|
+
}
|
|
207
|
+
String redactedUrl = urlString.replaceAll("([?&])apiKey=[^&]*", "$1apiKey=(redacted)");
|
|
208
|
+
Log.e("AguaceroRN", "[debug][FrameProcessor] HTTP_ERROR code=" + response.code()
|
|
209
|
+
+ " url=" + redactedUrl
|
|
210
|
+
+ " apiKey.len=" + (apiKey != null ? apiKey.length() : 0)
|
|
211
|
+
+ " bundleId=" + (bundleId != null && !bundleId.isEmpty() ? bundleId : "(none)")
|
|
212
|
+
+ " gridOrigin=" + (gridRequestSiteOrigin != null ? gridRequestSiteOrigin : "(none)")
|
|
213
|
+
+ " body=" + bodyPeek);
|
|
214
|
+
if (response.code() == 403) {
|
|
215
|
+
Log.e("AguaceroRN", "[debug][FrameProcessor] 403 hint: verify API key, allowlisted bundleId (x-app-identifier), and gridRequestSiteOrigin (Origin/Referer) match your web app.");
|
|
216
|
+
}
|
|
217
|
+
}
|
|
182
218
|
promise.reject("HTTP_ERROR", "HTTP " + response.code());
|
|
183
219
|
return;
|
|
184
220
|
}
|
|
@@ -46,13 +46,15 @@ class WeatherFrameProcessorModule: NSObject {
|
|
|
46
46
|
|
|
47
47
|
let apiKey = options["apiKey"] as? String ?? ""
|
|
48
48
|
let bundleId = options["bundleId"] as? String
|
|
49
|
+
let debug = (options["debug"] as? Bool) == true
|
|
50
|
+
let gridOriginOpt = options["gridRequestSiteOrigin"] as? String
|
|
49
51
|
|
|
50
52
|
var request = URLRequest(url: url)
|
|
51
53
|
request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
|
|
52
54
|
if let bundleId = bundleId, !bundleId.isEmpty {
|
|
53
55
|
request.setValue(bundleId, forHTTPHeaderField: "x-app-identifier")
|
|
54
56
|
}
|
|
55
|
-
if let site =
|
|
57
|
+
if let site = gridOriginOpt {
|
|
56
58
|
var origin = site.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
57
59
|
while origin.hasSuffix("/") {
|
|
58
60
|
origin.removeLast()
|
|
@@ -63,6 +65,17 @@ class WeatherFrameProcessorModule: NSObject {
|
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
if debug {
|
|
69
|
+
let redacted = urlString.replacingOccurrences(
|
|
70
|
+
of: #"([?&])apiKey=[^&]*"#,
|
|
71
|
+
with: "$1apiKey=(redacted)",
|
|
72
|
+
options: .regularExpression
|
|
73
|
+
)
|
|
74
|
+
let bundleStr = (bundleId?.isEmpty == false) ? bundleId! : "(none)"
|
|
75
|
+
let originStr = (gridOriginOpt?.isEmpty == false) ? gridOriginOpt! : "(none)"
|
|
76
|
+
print("[AguaceroRN][debug][FrameProcessor] REQUEST url=\(redacted) apiKey.len=\(apiKey.count) bundleId=\(bundleStr) gridOrigin=\(originStr)")
|
|
77
|
+
}
|
|
78
|
+
|
|
66
79
|
let task = session.dataTask(with: request) { data, response, error in
|
|
67
80
|
let fetchDuration = (CFAbsoluteTimeGetCurrent() - startTime) * 1000
|
|
68
81
|
|
|
@@ -89,7 +102,25 @@ class WeatherFrameProcessorModule: NSObject {
|
|
|
89
102
|
|
|
90
103
|
guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
|
|
91
104
|
let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
|
|
92
|
-
|
|
105
|
+
if debug {
|
|
106
|
+
let redacted = urlString.replacingOccurrences(
|
|
107
|
+
of: #"([?&])apiKey=[^&]*"#,
|
|
108
|
+
with: "$1apiKey=(redacted)",
|
|
109
|
+
options: .regularExpression
|
|
110
|
+
)
|
|
111
|
+
var bodySnippet = ""
|
|
112
|
+
if let data = data, let text = String(data: data, encoding: .utf8) {
|
|
113
|
+
bodySnippet = text.count > 512 ? String(text.prefix(512)) + "…" : text
|
|
114
|
+
}
|
|
115
|
+
let bundleStr = (bundleId?.isEmpty == false) ? bundleId! : "(none)"
|
|
116
|
+
let originStr = (gridOriginOpt?.isEmpty == false) ? gridOriginOpt! : "(none)"
|
|
117
|
+
print("[AguaceroRN][debug][FrameProcessor] HTTP_ERROR status=\(statusCode) url=\(redacted) apiKey.len=\(apiKey.count) bundleId=\(bundleStr) gridOrigin=\(originStr) body=\(bodySnippet)")
|
|
118
|
+
if statusCode == 403 {
|
|
119
|
+
print("[AguaceroRN][debug][FrameProcessor] 403 hint: verify API key, allowlisted bundleId (x-app-identifier), and gridRequestSiteOrigin (Origin/Referer) match your web app.")
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
print("🔍 [WeatherFrameProcessor] \(fileId) HTTP_ERROR status=\(statusCode)")
|
|
123
|
+
}
|
|
93
124
|
reject("HTTP_ERROR", "HTTP request failed with status code: \(statusCode)", nil)
|
|
94
125
|
return
|
|
95
126
|
}
|
|
@@ -18,6 +18,8 @@ var _satelliteAndroidController = require("./satellite/satelliteAndroidControlle
|
|
|
18
18
|
var _NwsAlertsOverlay = _interopRequireDefault(require("./nws/NwsAlertsOverlay"));
|
|
19
19
|
var _MapRegistry = require("./MapRegistry");
|
|
20
20
|
var _satelliteBridgeDiag = require("./satelliteBridgeDiag");
|
|
21
|
+
var _aguaceroRnDebug = require("./aguaceroRnDebug");
|
|
22
|
+
var _aguaceroCoreDebugHooks = require("./aguaceroCoreDebugHooks");
|
|
21
23
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
24
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
23
25
|
// packages/react-native/src/WeatherLayerManager.js
|
|
@@ -150,8 +152,9 @@ function satelliteObsTimelineSig(state) {
|
|
|
150
152
|
return `${keys.length}:${keys[0]}:${keys[keys.length - 1]}`;
|
|
151
153
|
}
|
|
152
154
|
|
|
153
|
-
/** True
|
|
155
|
+
/** True when {@link WeatherLayerManager} `debug` / {@link configureAguaceroRnDebug}, or legacy `__AGUACERO_WX_GRID_DEBUG__`. */
|
|
154
156
|
function wxGridDebugEnabled() {
|
|
157
|
+
if ((0, _aguaceroRnDebug.isAguaceroRnDebugEnabled)()) return true;
|
|
155
158
|
try {
|
|
156
159
|
if (typeof __DEV__ !== 'undefined' && __DEV__) return true;
|
|
157
160
|
return Boolean(typeof globalThis !== 'undefined' && globalThis.__AGUACERO_WX_GRID_DEBUG__);
|
|
@@ -269,8 +272,15 @@ const WeatherLayerManager = exports.WeatherLayerManager = /*#__PURE__*/(0, _reac
|
|
|
269
272
|
onNwsAlertClick,
|
|
270
273
|
/** Same semantics as mapsgl / AguaceroCore: Origin + Referer for grid CDN (required by many CloudFront rules). */
|
|
271
274
|
gridRequestSiteOrigin,
|
|
275
|
+
/** When true, logs auth/HTTP diagnostics under `[AguaceroRN][debug]` (Metro / Logcat / Xcode). */
|
|
276
|
+
debug = false,
|
|
272
277
|
...restProps
|
|
273
278
|
} = props;
|
|
279
|
+
(0, _react.useEffect)(() => {
|
|
280
|
+
(0, _aguaceroRnDebug.configureAguaceroRnDebug)({
|
|
281
|
+
enabled: Boolean(debug)
|
|
282
|
+
});
|
|
283
|
+
}, [debug]);
|
|
274
284
|
const context = (0, _react.useContext)(_AguaceroContext.AguaceroContext);
|
|
275
285
|
|
|
276
286
|
// Create the core here instead of getting it from context
|
|
@@ -285,6 +295,24 @@ const WeatherLayerManager = exports.WeatherLayerManager = /*#__PURE__*/(0, _reac
|
|
|
285
295
|
},
|
|
286
296
|
autoRefresh: false // <-- add this
|
|
287
297
|
}), [apiKey, gridRequestSiteOrigin]);
|
|
298
|
+
(0, _react.useEffect)(() => {
|
|
299
|
+
if (!core) return;
|
|
300
|
+
(0, _aguaceroCoreDebugHooks.installAguaceroCoreDebugHooks)(core, {
|
|
301
|
+
gridRequestSiteOriginProp: gridRequestSiteOrigin ?? null,
|
|
302
|
+
debugProp: Boolean(debug)
|
|
303
|
+
});
|
|
304
|
+
if ((0, _aguaceroRnDebug.isAguaceroRnDebugEnabled)() && !apiKey) {
|
|
305
|
+
(0, _aguaceroRnDebug.aguaceroDebugWarn)('WeatherLayerManager.missingApiKey', {
|
|
306
|
+
hint: 'apiKey prop is empty — all CDN requests will fail or return 403'
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
if ((0, _aguaceroRnDebug.isAguaceroRnDebugEnabled)() && apiKey && !gridRequestSiteOrigin) {
|
|
310
|
+
(0, _aguaceroRnDebug.aguaceroDebugWarn)('WeatherLayerManager.missingGridOrigin', {
|
|
311
|
+
hint: 'gridRequestSiteOrigin is not set — CloudFront often returns 403 without Origin/Referer on React Native',
|
|
312
|
+
snapshot: (0, _aguaceroRnDebug.getAguaceroAuthDiagnosticSnapshot)(core)
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}, [core, debug, gridRequestSiteOrigin, apiKey]);
|
|
288
316
|
const [watchesWarningsOptions, setWatchesWarningsOptions] = (0, _react.useState)(() => ({
|
|
289
317
|
alertInteractionEnabled: true,
|
|
290
318
|
...(watchesWarningsProp ?? {})
|
|
@@ -650,7 +678,11 @@ const WeatherLayerManager = exports.WeatherLayerManager = /*#__PURE__*/(0, _reac
|
|
|
650
678
|
} else {
|
|
651
679
|
resourcePath = `/grids/${model}/${date}/${run}/${currentFrame}/${variable}/0`;
|
|
652
680
|
}
|
|
653
|
-
const options = buildGridFrameProcessOptions(core.baseGridUrl, resourcePath, core.apiKey, core.bundleId, gridRequestSiteOrigin);
|
|
681
|
+
const options = (0, _aguaceroRnDebug.augmentProcessFrameOptionsForDebug)(buildGridFrameProcessOptions(core.baseGridUrl, resourcePath, core.apiKey, core.bundleId, gridRequestSiteOrigin), core);
|
|
682
|
+
(0, _aguaceroCoreDebugHooks.logProcessFrameAuthMismatch)(core, options, {
|
|
683
|
+
phase: 'preloadCurrent',
|
|
684
|
+
currentCacheKey
|
|
685
|
+
});
|
|
654
686
|
try {
|
|
655
687
|
wxGridVerbose('processFrameRequest', {
|
|
656
688
|
currentCacheKey,
|
|
@@ -755,12 +787,20 @@ const WeatherLayerManager = exports.WeatherLayerManager = /*#__PURE__*/(0, _reac
|
|
|
755
787
|
const cancelled = e && (e.code === 'E_CANCELLED' || e?.userInfo?.code === 'E_CANCELLED' || typeof e?.message === 'string' && e.message.includes('superseded'));
|
|
756
788
|
if (!cancelled) {
|
|
757
789
|
hasPreloadedRef.current = false;
|
|
758
|
-
|
|
790
|
+
const errDetail = {
|
|
759
791
|
currentCacheKey,
|
|
760
792
|
code: e?.code,
|
|
761
793
|
message: e?.message,
|
|
762
794
|
userInfo: e?.userInfo
|
|
763
|
-
}
|
|
795
|
+
};
|
|
796
|
+
wxGridWarn('preloadProcessFrameError', errDetail);
|
|
797
|
+
if ((0, _aguaceroRnDebug.isAguaceroRnDebugEnabled)()) {
|
|
798
|
+
(0, _aguaceroRnDebug.aguaceroDebugWarn)('preloadProcessFrameError', {
|
|
799
|
+
...errDetail,
|
|
800
|
+
auth: (0, _aguaceroRnDebug.getAguaceroAuthDiagnosticSnapshot)(core),
|
|
801
|
+
is403: e?.code === 'HTTP_ERROR' && typeof e?.message === 'string' && e.message.includes('403')
|
|
802
|
+
});
|
|
803
|
+
}
|
|
764
804
|
} else {
|
|
765
805
|
wxGridVerbose('preloadProcessFrameCancelled', {
|
|
766
806
|
currentCacheKey
|
|
@@ -785,7 +825,11 @@ const WeatherLayerManager = exports.WeatherLayerManager = /*#__PURE__*/(0, _reac
|
|
|
785
825
|
} else {
|
|
786
826
|
resourcePath = `/grids/${model}/${date}/${run}/${frame}/${variable}/0`;
|
|
787
827
|
}
|
|
788
|
-
const options = buildGridFrameProcessOptions(core.baseGridUrl, resourcePath, core.apiKey, core.bundleId, gridRequestSiteOrigin);
|
|
828
|
+
const options = (0, _aguaceroRnDebug.augmentProcessFrameOptionsForDebug)(buildGridFrameProcessOptions(core.baseGridUrl, resourcePath, core.apiKey, core.bundleId, gridRequestSiteOrigin), core);
|
|
829
|
+
(0, _aguaceroCoreDebugHooks.logProcessFrameAuthMismatch)(core, options, {
|
|
830
|
+
phase: 'preloadBackground',
|
|
831
|
+
cacheKey
|
|
832
|
+
});
|
|
789
833
|
WeatherFrameProcessorModule.processFrame(options).then(result => {
|
|
790
834
|
if (!result || !result.filePath) {
|
|
791
835
|
return;
|
|
@@ -1174,7 +1218,11 @@ const WeatherLayerManager = exports.WeatherLayerManager = /*#__PURE__*/(0, _reac
|
|
|
1174
1218
|
m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0'),
|
|
1175
1219
|
d = frameDate.getUTCDate().toString().padStart(2, '0');
|
|
1176
1220
|
const resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${currentVariable}/0`;
|
|
1177
|
-
const options = buildGridFrameProcessOptions(core.baseGridUrl, resourcePath, core.apiKey, core.bundleId, gridRequestSiteOrigin);
|
|
1221
|
+
const options = (0, _aguaceroRnDebug.augmentProcessFrameOptionsForDebug)(buildGridFrameProcessOptions(core.baseGridUrl, resourcePath, core.apiKey, core.bundleId, gridRequestSiteOrigin), core);
|
|
1222
|
+
(0, _aguaceroCoreDebugHooks.logProcessFrameAuthMismatch)(core, options, {
|
|
1223
|
+
phase: 'mrmsRefresh',
|
|
1224
|
+
cacheKey
|
|
1225
|
+
});
|
|
1178
1226
|
WeatherFrameProcessorModule.processFrame(options).then(result => {
|
|
1179
1227
|
if (!result || !result.filePath) return;
|
|
1180
1228
|
const frameData = {
|