@aguacerowx/mapsgl 0.0.29 → 0.0.32

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aguacerowx/mapsgl",
3
- "version": "0.0.29",
3
+ "version": "0.0.32",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -69,26 +69,14 @@ export class WeatherLayerManager extends EventEmitter {
69
69
  const runKey = `${state.model}-${state.date}-${state.run}-${state.variable}`;
70
70
  const existingRunKey = this.shaderLayer?.runKey ?? 'none';
71
71
 
72
- console.log(`[WLM._handleStateChange]`, {
73
- runKey, timeKey,
74
- existingRunKey,
75
- currentLoadedTimeKey: this.currentLoadedTimeKey,
76
- shaderLayerExists: !!this.shaderLayer,
77
- decision: !this.shaderLayer || existingRunKey !== runKey
78
- ? 'REBUILD'
79
- : this.currentLoadedTimeKey !== timeKey
80
- ? 'UPDATE_DATA'
81
- : 'STYLE_ONLY'
82
- });
83
-
84
72
  if (!this.shaderLayer || this.shaderLayer.runKey !== runKey) {
85
- console.log(`[WLM._handleStateChange] → dispatching _rebuildLayerAndPreload (runKey changed: "${existingRunKey}" → "${runKey}")`);
73
+ //console.log(`[WLM._handleStateChange] → dispatching _rebuildLayerAndPreload (runKey changed: "${existingRunKey}" → "${runKey}")`);
86
74
  this._rebuildLayerAndPreload(state);
87
75
  } else if (this.currentLoadedTimeKey !== timeKey) {
88
- console.log(`[WLM._handleStateChange] → dispatching _updateLayerData (timeKey changed: ${this.currentLoadedTimeKey} → ${timeKey})`);
76
+ //console.log(`[WLM._handleStateChange] → dispatching _updateLayerData (timeKey changed: ${this.currentLoadedTimeKey} → ${timeKey})`);
89
77
  this._updateLayerData(state);
90
78
  } else {
91
- console.log(`[WLM._handleStateChange] → style/opacity update only`);
79
+ //console.log(`[WLM._handleStateChange] → style/opacity update only`);
92
80
  }
93
81
 
94
82
  if (this.shaderLayer) {
@@ -140,30 +128,30 @@ export class WeatherLayerManager extends EventEmitter {
140
128
  }
141
129
 
142
130
  const timeKey = state.isMRMS ? state.mrmsTimestamp : state.forecastHour;
143
- console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} timeKey=${timeKey}`);
131
+ //console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} timeKey=${timeKey}`);
144
132
 
145
133
  if (this.shaderLayer.switchToPreloadedTexture(timeKey)) {
146
134
  this.currentLoadedTimeKey = timeKey;
147
- console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} — FAST PATH: preloaded texture found for timeKey=${timeKey}, swapped instantly`);
135
+ //console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} — FAST PATH: preloaded texture found for timeKey=${timeKey}, swapped instantly`);
148
136
  this.map.triggerRepaint();
149
137
  return;
150
138
  }
151
139
 
152
- console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} — SLOW PATH: no preloaded texture for timeKey=${timeKey}, fetching...`);
140
+ //console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} — SLOW PATH: no preloaded texture for timeKey=${timeKey}, fetching...`);
153
141
  const fetchStart = performance.now();
154
142
  try {
155
143
  const grid = await this.core._loadGridData(state);
156
144
  const fetchMs = (performance.now() - fetchStart).toFixed(1);
157
145
 
158
146
  if (requestToken !== this.latestDataRequestToken) {
159
- console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} — STALE after fetch (latestToken=${this.latestDataRequestToken}), discarding (${fetchMs}ms)`);
147
+ //console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} — STALE after fetch (latestToken=${this.latestDataRequestToken}), discarding (${fetchMs}ms)`);
160
148
  return;
161
149
  }
162
150
 
163
151
  if (grid && grid.data) {
164
152
  const gridModel = state.isMRMS ? 'mrms' : state.model;
165
153
  const { gridDef } = this.core._getGridCornersAndDef(gridModel);
166
- console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} — grid received in ${fetchMs}ms, storing+switching texture for timeKey=${timeKey}`);
154
+ //console.log(`[WLM._updateLayerDataWithToken] token=${requestToken} — grid received in ${fetchMs}ms, storing+switching texture for timeKey=${timeKey}`);
167
155
 
168
156
  this.shaderLayer.storePreloadedTexture(
169
157
  timeKey, grid.data, grid.encoding,
@@ -189,28 +177,17 @@ export class WeatherLayerManager extends EventEmitter {
189
177
 
190
178
  async _rebuildLayerAndPreload(state) {
191
179
  const rebuildId = ++this.currentRebuildId;
192
- console.log(`[WLM._rebuildLayerAndPreload] START rebuildId=${rebuildId}`, {
193
- model: state.model, variable: state.variable, date: state.date,
194
- run: state.run, forecastHour: state.forecastHour,
195
- isMRMS: state.isMRMS, mrmsTimestamp: state.mrmsTimestamp
196
- });
197
180
 
198
181
  this.core.cancelAllRequests();
199
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — cancelled all pending requests`);
200
182
 
201
183
  if (this.shaderLayer) {
202
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — removing existing shaderLayer id=${this.shaderLayer.id} runKey=${this.shaderLayer.runKey}`);
203
184
  this.map.removeLayer(this.shaderLayer.id);
204
185
  this.shaderLayer = null;
205
186
  }
206
187
  this.currentLoadedTimeKey = null;
207
188
 
208
- if (!state.variable) {
209
- console.warn(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — no variable set, aborting rebuild`);
210
- return;
211
- }
189
+ if (!state.variable) return;
212
190
 
213
- // --- FIX: Correct an invalid forecastHour before building the layer ---
214
191
  if (
215
192
  !state.isMRMS &&
216
193
  state.forecastHour === 0 &&
@@ -220,50 +197,32 @@ export class WeatherLayerManager extends EventEmitter {
220
197
  const availableHours =
221
198
  this.core.modelStatus?.[state.model]?.[state.date]?.[state.run] || [];
222
199
  const firstValidHour = availableHours.find(h => h !== 0);
223
- console.warn(
224
- `[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — ptypeRefl/HRRR hour-0 correction triggered.`,
225
- { availableHours, firstValidHour: firstValidHour ?? 'NOT FOUND — will proceed with 0' }
226
- );
227
200
  if (firstValidHour !== undefined) {
228
201
  state = { ...state, forecastHour: firstValidHour };
229
- // CRITICAL: Mutate core.state directly instead of calling core.setState().
230
- // core.setState() emits state:change, which triggers _handleStateChange,
231
- // which spawns a second concurrent rebuild — causing a duplicate addLayer
232
- // crash and a gl=null texture upload on the layer that wins the race.
233
202
  this.core.state.forecastHour = firstValidHour;
234
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} corrected forecastHour to ${firstValidHour} (silent, no state:change emitted)`);
203
+ } else {
204
+ // Run exists but has no valid hours yet — bail out entirely
205
+ console.warn(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — ptypeRefl/HRRR: no valid hours in new run yet, aborting rebuild`);
206
+ return;
235
207
  }
236
208
  }
237
- // --- END FIX ---
238
209
 
239
- // Guard: if a newer rebuild has already started, bail before touching the map
240
- if (rebuildId !== this.currentRebuildId) {
241
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — STALE before addLayer (currentRebuildId=${this.currentRebuildId}), aborting`);
242
- return;
243
- }
210
+ if (rebuildId !== this.currentRebuildId) return;
244
211
 
245
212
  const runKey = `${state.model}-${state.date}-${state.run}-${state.variable}`;
246
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — creating shaderLayer runKey=${runKey}, forecastHour=${state.forecastHour}`);
247
213
 
248
214
  this.shaderLayer = new GridRenderLayer(this.layerId);
249
215
  this.shaderLayer.runKey = runKey;
250
216
  this.map.addLayer(this.shaderLayer, 'AML_-_terrain');
251
217
  this._updateLayerStyle(state);
252
218
 
253
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — fetching grid data...`);
254
- const fetchStart = performance.now();
255
219
  const grid = await this.core._loadGridData(state);
256
- const fetchMs = (performance.now() - fetchStart).toFixed(1);
257
220
 
258
- if (rebuildId !== this.currentRebuildId) {
259
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — STALE after grid fetch (currentRebuildId=${this.currentRebuildId}), discarding result (fetch took ${fetchMs}ms)`);
260
- return;
261
- }
221
+ if (rebuildId !== this.currentRebuildId) return;
262
222
 
263
223
  if (grid && grid.data) {
264
224
  const gridModel = state.isMRMS ? 'mrms' : state.model;
265
225
  const { gridDef } = this.core._getGridCornersAndDef(gridModel);
266
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — grid data received in ${fetchMs}ms, uploading texture. nx=${gridDef.grid_params.nx} ny=${gridDef.grid_params.ny} dataLength=${grid.data.length}`);
267
226
 
268
227
  this.shaderLayer.updateDataTexture(
269
228
  grid.data, grid.encoding,
@@ -272,35 +231,25 @@ export class WeatherLayerManager extends EventEmitter {
272
231
 
273
232
  this.currentLoadedTimeKey = state.isMRMS ? state.mrmsTimestamp : state.forecastHour;
274
233
  this.latestDataRequestToken = this.currentRebuildId;
275
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — texture uploaded, currentLoadedTimeKey=${this.currentLoadedTimeKey}, triggering repaint`);
276
234
  this.map.triggerRepaint();
277
- } else {
278
- console.error(
279
- `[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — grid fetch returned null/empty after ${fetchMs}ms.`,
280
- { model: state.model, variable: state.variable, date: state.date, run: state.run, forecastHour: state.forecastHour, isMRMS: state.isMRMS },
281
- '← THIS IS WHY THE MAP IS BLANK'
282
- );
283
235
  }
284
236
 
285
237
  if (rebuildId === this.currentRebuildId) {
286
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — starting preload for all time steps`);
287
238
  this._preloadAllTimeSteps(state);
288
- } else {
289
- console.log(`[WLM._rebuildLayerAndPreload] rebuildId=${rebuildId} — skipping preload, rebuild superseded by rebuildId=${this.currentRebuildId}`);
290
239
  }
291
240
  }
292
241
 
293
242
  _preloadAllTimeSteps(state) {
294
243
  const timeSteps = state.isMRMS ? state.availableTimestamps : state.availableHours;
295
244
  if (!timeSteps || timeSteps.length <= 1) {
296
- console.log(`[WLM._preloadAllTimeSteps] skipping — only ${timeSteps?.length ?? 0} time steps available`);
245
+ //console.log(`[WLM._preloadAllTimeSteps] skipping — only ${timeSteps?.length ?? 0} time steps available`);
297
246
  return;
298
247
  }
299
248
 
300
249
  const currentFrameTime = state.isMRMS ? state.mrmsTimestamp : state.forecastHour;
301
250
  const stepsToPreload = timeSteps.filter(t => t !== currentFrameTime);
302
251
  const capturedRebuildId = this.currentRebuildId;
303
- console.log(`[WLM._preloadAllTimeSteps] preloading ${stepsToPreload.length} frames (skipping currentFrameTime=${currentFrameTime}), capturedRebuildId=${capturedRebuildId}`);
252
+ //console.log(`[WLM._preloadAllTimeSteps] preloading ${stepsToPreload.length} frames (skipping currentFrameTime=${currentFrameTime}), capturedRebuildId=${capturedRebuildId}`);
304
253
 
305
254
  const gridModel = state.isMRMS ? 'mrms' : state.model;
306
255
  const { gridDef } = this.core._getGridCornersAndDef(gridModel);
@@ -321,7 +270,7 @@ export class WeatherLayerManager extends EventEmitter {
321
270
  gridDef.grid_params.nx, gridDef.grid_params.ny
322
271
  );
323
272
  completed++;
324
- console.log(`[WLM._preloadAllTimeSteps] stored texture for time=${time} (${completed}/${stepsToPreload.length} done, ${failed} failed)`);
273
+ //console.log(`[WLM._preloadAllTimeSteps] stored texture for time=${time} (${completed}/${stepsToPreload.length} done, ${failed} failed)`);
325
274
  } else if (!grid?.data) {
326
275
  failed++;
327
276
  console.warn(`[WLM._preloadAllTimeSteps] null grid for time=${time} — skipping texture store (${completed}/${stepsToPreload.length} done, ${failed} failed)`);
@@ -357,10 +306,10 @@ export class WeatherLayerManager extends EventEmitter {
357
306
  let dataRange;
358
307
  if (state.variable === 'ptypeRefl' || state.variable === 'ptypeRate') {
359
308
  if (state.isMRMS) {
360
- console.log('🔧 Using MRMS ptype data range: 5-380');
309
+ //console.log('🔧 Using MRMS ptype data range: 5-380');
361
310
  dataRange = [5, 380];
362
311
  } else {
363
- console.log('🔧 Using Model ptype data range: 5-380');
312
+ //console.log('🔧 Using Model ptype data range: 5-380');
364
313
  dataRange = [5, 380]; // Models also use the full colormap range
365
314
  }
366
315
  } else {
@@ -432,7 +381,7 @@ export class WeatherLayerManager extends EventEmitter {
432
381
  * @returns {Promise<void>}
433
382
  */
434
383
  async refreshData() {
435
- console.log('[WeatherLayerManager] Manual data refresh triggered.');
384
+ //console.log('[WeatherLayerManager] Manual data refresh triggered.');
436
385
  // This just calls the internal logic we already built.
437
386
  await this._checkForUpdates();
438
387
  }
@@ -480,8 +429,14 @@ export class WeatherLayerManager extends EventEmitter {
480
429
  this.emit('data:updated', { type: 'mrms', variable: currentVariable, newTimestamps: newTimestampsToPreload });
481
430
  }
482
431
  } else {
432
+ const previousStatus = this.core.modelStatus;
483
433
  const modelStatus = await this.core.fetchModelStatus(true);
484
- this.core._emitStateChange();
434
+
435
+ // Only emit if the status actually changed
436
+ const statusChanged = JSON.stringify(previousStatus) !== JSON.stringify(modelStatus);
437
+ if (statusChanged) {
438
+ this.core._emitStateChange();
439
+ }
485
440
 
486
441
  const latestRun = findLatestModelRun(modelStatus, currentModel);
487
442
  if (!latestRun) return;
@@ -525,6 +480,6 @@ export class WeatherLayerManager extends EventEmitter {
525
480
  // 4. Clear any remaining internal state
526
481
  this.currentLoadedTimeKey = null;
527
482
 
528
- console.log(`WeatherLayerManager with id "${this.layerId}" has been destroyed.`);
483
+ //console.log(`WeatherLayerManager with id "${this.layerId}" has been destroyed.`);
529
484
  }
530
485
  }