http-request-manager 18.16.26 → 18.16.28

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.
@@ -7231,19 +7231,16 @@ class HTTPManagerStateService extends ComponentStore {
7231
7231
  }
7232
7232
  return this.httpManagerService.getRequest(requestOptions, effectiveParams).pipe(tap((data) => {
7233
7233
  // Extract array from paginated response if needed
7234
+ // Data is already adapted by RequestService.request() pipe - no need to adapt again
7234
7235
  const arrayData = (data?.results && Array.isArray(data.results)) ? data.results : data;
7235
- // Apply adapter to response data
7236
- let adaptedData = this.applyAdapter(arrayData);
7237
- adaptedData = (!adaptedData) ? (this.dataType === DataType.ARRAY) ? [] : {} : adaptedData;
7238
- this.setData$(adaptedData);
7236
+ this.setData$(arrayData);
7239
7237
  }), concatMap((data) => {
7240
7238
  // Extract array from paginated response for database storage
7239
+ // Data is already adapted by RequestService.request() pipe - no need to adapt again
7241
7240
  const dbData = (data?.results && Array.isArray(data.results)) ? data.results : data;
7242
- // Apply adapter before database storage
7243
- const adaptedDbData = this.applyAdapter(dbData);
7244
- if (this.hasDatabase && this.databaseOptions?.table && Array.isArray(adaptedDbData) && adaptedDbData.length > 0) {
7241
+ if (this.hasDatabase && this.databaseOptions?.table && Array.isArray(dbData) && dbData.length > 0) {
7245
7242
  const tableName = this.databaseOptions.table;
7246
- const schema = this.buildSchemaFromSample(adaptedDbData[0]);
7243
+ const schema = this.buildSchemaFromSample(dbData[0]);
7247
7244
  const tableDef = TableSchemaDef.adapt({ table: tableName, schema });
7248
7245
  const schemaSignature = this.buildSchemaSignature(schema);
7249
7246
  // Always ensure table exists immediately before writing to avoid stale schema/store races.
@@ -7258,7 +7255,7 @@ class HTTPManagerStateService extends ComponentStore {
7258
7255
  console.warn('[DB STORAGE] Table create/open not ready, skipping DB write for this payload:', { table: tableName });
7259
7256
  return of(data);
7260
7257
  }
7261
- return this.dbManagerService.createTableRecords(tableName, adaptedDbData).pipe(tap(() => this.saveRequestCacheMetadata(tableName, 'GET', requestSignature, schemaSignature, options)));
7258
+ return this.dbManagerService.createTableRecords(tableName, dbData).pipe(tap(() => this.saveRequestCacheMetadata(tableName, 'GET', requestSignature, schemaSignature, options)));
7262
7259
  }));
7263
7260
  }), catchError((error) => {
7264
7261
  console.error('[DB STORAGE] Failed to ensure table and write records:', { table: tableName, schema, error });
@@ -7371,14 +7368,14 @@ class HTTPManagerStateService extends ComponentStore {
7371
7368
  return this.httpManagerService.getRequest(requestOptions, effectiveParams)
7372
7369
  .pipe(tap((data) => {
7373
7370
  console.log('📦 fetchRecord received data:', data);
7374
- // Apply adapter if provided
7375
- let adaptedData = this.applyAdapter(data);
7376
- adaptedData = (!adaptedData) ? (this.dataType === DataType.ARRAY) ? [] : {} : adaptedData;
7371
+ // Data is already adapted by RequestService.request() pipe - no need to adapt again
7372
+ const arrayData = (data?.results && Array.isArray(data.results)) ? data.results : data;
7373
+ const finalData = (!arrayData) ? (this.dataType === DataType.ARRAY) ? [] : {} : arrayData;
7377
7374
  const id = options.path?.length ? options.path[options.path.length - 1] : null;
7378
7375
  // For single-record operations (CREATE, UPDATE, DELETE), extract from array if needed
7379
- let singleRecord = adaptedData;
7380
- if (Array.isArray(adaptedData) && adaptedData.length > 0) {
7381
- singleRecord = adaptedData[0];
7376
+ let singleRecord = finalData;
7377
+ if (Array.isArray(finalData) && finalData.length > 0) {
7378
+ singleRecord = finalData[0];
7382
7379
  }
7383
7380
  if (method === 'DELETE') {
7384
7381
  console.log('🗑️ Deleting record with id:', id);
@@ -7389,17 +7386,18 @@ class HTTPManagerStateService extends ComponentStore {
7389
7386
  this.updateData$(singleRecord);
7390
7387
  }
7391
7388
  if (method === 'CREATE') {
7392
- console.log('➕ Adding record:', adaptedData);
7393
- this.addData$(adaptedData);
7389
+ console.log('➕ Adding record:', finalData);
7390
+ this.addData$(finalData);
7394
7391
  }
7395
7392
  }), concatMap((data) => {
7396
- const adaptedData = this.applyAdapter(data);
7393
+ // Data is already adapted by RequestService.request() pipe - no need to adapt again
7394
+ const dbData = (data?.results && Array.isArray(data.results)) ? data.results : data;
7397
7395
  const tableName = this.databaseOptions?.table;
7398
7396
  const idFromPath = options.path?.length ? options.path[options.path.length - 1] : null;
7399
7397
  // For single-record operations, extract from array if needed
7400
- let singleRecord = adaptedData;
7401
- if (Array.isArray(adaptedData) && adaptedData.length > 0) {
7402
- singleRecord = adaptedData[0];
7398
+ let singleRecord = dbData;
7399
+ if (Array.isArray(dbData) && dbData.length > 0) {
7400
+ singleRecord = dbData[0];
7403
7401
  }
7404
7402
  if (this.hasDatabase && tableName) {
7405
7403
  switch (method) {
@@ -7418,11 +7416,11 @@ class HTTPManagerStateService extends ComponentStore {
7418
7416
  this.logger.warn('fetchRecord', 'UPDATE method called but singleRecord or id is missing', { singleRecord, hasData: !!singleRecord, hasId: !!singleRecord?.id });
7419
7417
  break;
7420
7418
  case 'CREATE':
7421
- if (adaptedData && adaptedData.id != null && adaptedData.id !== '') {
7422
- this.logger.debug('fetchRecord', 'Creating database record', { table: tableName, id: adaptedData.id, data: adaptedData });
7423
- return this.dbManagerService.createTableRecord(tableName, adaptedData);
7419
+ if (dbData && dbData.id != null && dbData.id !== '') {
7420
+ this.logger.debug('fetchRecord', 'Creating database record', { table: tableName, id: dbData.id, data: dbData });
7421
+ return this.dbManagerService.createTableRecord(tableName, dbData);
7424
7422
  }
7425
- this.logger.warn('fetchRecord', 'CREATE method called but data.id is invalid', { adaptedData });
7423
+ this.logger.warn('fetchRecord', 'CREATE method called but data.id is invalid', { dbData });
7426
7424
  break;
7427
7425
  default:
7428
7426
  this.logger.debug('fetchRecord', 'Method does not require database operation', { method });
@@ -7434,7 +7432,7 @@ class HTTPManagerStateService extends ComponentStore {
7434
7432
  hasTable: !!tableName
7435
7433
  });
7436
7434
  }
7437
- return of(adaptedData);
7435
+ return of(dbData);
7438
7436
  }));
7439
7437
  })));
7440
7438
  // CREATE RECORD
@@ -7443,17 +7441,13 @@ class HTTPManagerStateService extends ComponentStore {
7443
7441
  const requestOptions = this.updateRequestOptions(options?.headers);
7444
7442
  const effectiveParams = this.getEffectiveParams(options?.path);
7445
7443
  return this.httpManagerService.postRequest(data, requestOptions, effectiveParams)
7446
- .pipe(tap((data) => {
7447
- // Apply adapter to response data
7448
- let adaptedData = this.applyAdapter(data);
7449
- adaptedData = (!adaptedData) ? (this.dataType === DataType.ARRAY) ? [] : {} : adaptedData;
7450
- this.addData$(adaptedData);
7444
+ .pipe(tap((adaptedData) => {
7445
+ // Data is already adapted by RequestService
7446
+ const safeData = (!adaptedData) ? (this.dataType === DataType.ARRAY ? [] : {}) : adaptedData;
7447
+ this.addData$(safeData);
7451
7448
  this.operationSuccess.next(OperationResultModel.adapt({ success: true, operation: 'CREATE' }));
7452
- // Always call wsCommunication - it will queue if not connected
7453
- this.wsCommunication('CREATE', [...options?.path || [], adaptedData.id]);
7454
- }), concatMap((data) => {
7455
- // Apply adapter before database operations
7456
- const adaptedData = this.applyAdapter(data);
7449
+ this.wsCommunication('CREATE', [...options?.path || [], safeData.id]);
7450
+ }), concatMap((adaptedData) => {
7457
7451
  if (this.hasDatabase && this.databaseOptions?.table && adaptedData?.id) {
7458
7452
  return this.dbManagerService.createTableRecord(this.databaseOptions.table, adaptedData);
7459
7453
  }
@@ -7466,17 +7460,13 @@ class HTTPManagerStateService extends ComponentStore {
7466
7460
  const requestOptions = this.updateRequestOptions(options?.headers);
7467
7461
  const effectiveParams = this.getEffectiveParams(options?.path);
7468
7462
  return this.httpManagerService.putRequest(data, requestOptions, effectiveParams)
7469
- .pipe(tap((data) => {
7470
- // Apply adapter to response data
7471
- let adaptedData = this.applyAdapter(data);
7472
- adaptedData = (!adaptedData) ? (this.dataType === DataType.ARRAY) ? [] : {} : adaptedData;
7473
- this.updateData$(adaptedData);
7463
+ .pipe(tap((adaptedData) => {
7464
+ // Data is already adapted by RequestService
7465
+ const safeData = (!adaptedData) ? (this.dataType === DataType.ARRAY ? [] : {}) : adaptedData;
7466
+ this.updateData$(safeData);
7474
7467
  this.operationSuccess.next(OperationResultModel.adapt({ success: true, operation: 'UPDATE' }));
7475
- // Always call wsCommunication - it will queue if not connected
7476
7468
  this.wsCommunication('UPDATE', [...options?.path || []]);
7477
- }), concatMap((data) => {
7478
- // Apply adapter before database operations
7479
- const adaptedData = this.applyAdapter(data);
7469
+ }), concatMap((adaptedData) => {
7480
7470
  if (this.hasDatabase && this.databaseOptions?.table && adaptedData?.id) {
7481
7471
  return this.dbManagerService.updateTableRecord(this.databaseOptions.table, adaptedData);
7482
7472
  }
@@ -7489,17 +7479,13 @@ class HTTPManagerStateService extends ComponentStore {
7489
7479
  const requestOptions = this.updateRequestOptions(options?.headers);
7490
7480
  const effectiveParams = this.getEffectiveParams(options?.path);
7491
7481
  return this.httpManagerService.deleteRequest(requestOptions, effectiveParams)
7492
- .pipe(tap((data) => {
7493
- // Apply adapter to response data
7494
- let adaptedData = this.applyAdapter(data);
7495
- adaptedData = (!adaptedData) ? (this.dataType === DataType.ARRAY) ? [] : {} : adaptedData;
7496
- this.deleteData$(adaptedData);
7482
+ .pipe(tap((adaptedData) => {
7483
+ // Data is already adapted by RequestService
7484
+ const safeData = (!adaptedData) ? (this.dataType === DataType.ARRAY ? [] : {}) : adaptedData;
7485
+ this.deleteData$(safeData);
7497
7486
  this.operationSuccess.next(OperationResultModel.adapt({ success: true, operation: 'DELETE' }));
7498
- // Always call wsCommunication - it will queue if not connected
7499
7487
  this.wsCommunication('DELETE', [...options?.path || []]);
7500
- }), concatMap((data) => {
7501
- // Apply adapter before database operations
7502
- const adaptedData = this.applyAdapter(data);
7488
+ }), concatMap((adaptedData) => {
7503
7489
  if (this.hasDatabase && this.databaseOptions?.table && adaptedData?.id) {
7504
7490
  return this.dbManagerService.deleteTableRecord(this.databaseOptions.table, adaptedData.id);
7505
7491
  }
@@ -7512,13 +7498,12 @@ class HTTPManagerStateService extends ComponentStore {
7512
7498
  const requestOptions = this.updateRequestOptions(options?.headers);
7513
7499
  const effectiveParams = this.getEffectiveParams(options?.path);
7514
7500
  return this.httpManagerService.postRequest(data, requestOptions, effectiveParams)
7515
- .pipe(tap((res) => {
7516
- // Apply adapter to streaming response
7517
- const adaptedRes = this.applyAdapter(res);
7501
+ .pipe(tap((adaptedRes) => {
7502
+ // Data is already adapted by RequestService
7518
7503
  if (adaptedRes.length > 0)
7519
7504
  this.setData$(adaptedRes);
7520
7505
  this.streamedResponse = adaptedRes;
7521
- }), concatMap((res) => this.persistStreamDataToDb(res, options)), scan((acc, res) => {
7506
+ }), concatMap((adaptedRes) => this.persistStreamDataToDb(adaptedRes, options)), scan((acc, res) => {
7522
7507
  const previous = acc.current;
7523
7508
  const current = res;
7524
7509
  return { previous, current };
@@ -7533,14 +7518,12 @@ class HTTPManagerStateService extends ComponentStore {
7533
7518
  }));
7534
7519
  })));
7535
7520
  this.fetchStream = (options) => this.effect(() => of(options).pipe(tap(() => {
7536
- // console.log('[DEBUG] fetchStream called')
7537
7521
  this.streamedResponse = [];
7538
7522
  this.httpManagerService.isPending.next(true);
7539
7523
  }), switchMap((options) => {
7540
7524
  const requestOptions = this.updateRequestOptions(options?.headers);
7541
7525
  requestOptions.stream = true;
7542
7526
  const effectiveParams = this.getEffectiveParams(options?.path);
7543
- // console.log('[DEBUG] Making streaming request:', requestOptions)
7544
7527
  if (this.hasDatabase && this.databaseOptions?.table) {
7545
7528
  const requestSignature = this.buildRequestSignature('STREAM', requestOptions, effectiveParams);
7546
7529
  const fetchStreamFromAPI = () => {
@@ -7549,9 +7532,7 @@ class HTTPManagerStateService extends ComponentStore {
7549
7532
  if (Array.isArray(currentStateData) && currentStateData.length > 0) {
7550
7533
  return of({ data: currentStateData, fromCache: true });
7551
7534
  }
7552
- if (currentStateData &&
7553
- !Array.isArray(currentStateData) &&
7554
- Object.keys(currentStateData).length > 0) {
7535
+ if (currentStateData && !Array.isArray(currentStateData) && Object.keys(currentStateData).length > 0) {
7555
7536
  return of({ data: currentStateData, fromCache: true });
7556
7537
  }
7557
7538
  return of({ data: this.dataType === DataType.ARRAY ? [] : {}, fromCache: true });
@@ -7586,9 +7567,7 @@ class HTTPManagerStateService extends ComponentStore {
7586
7567
  if (Array.isArray(currentStateData) && currentStateData.length > 0) {
7587
7568
  return of({ data: currentStateData, fromCache: true });
7588
7569
  }
7589
- if (currentStateData &&
7590
- !Array.isArray(currentStateData) &&
7591
- Object.keys(currentStateData).length > 0) {
7570
+ if (currentStateData && !Array.isArray(currentStateData) && Object.keys(currentStateData).length > 0) {
7592
7571
  return of({ data: currentStateData, fromCache: true });
7593
7572
  }
7594
7573
  return fetchStreamFromAPI();
@@ -7598,23 +7577,17 @@ class HTTPManagerStateService extends ComponentStore {
7598
7577
  }));
7599
7578
  })).pipe(tap((packet) => {
7600
7579
  const res = packet?.data;
7601
- // Apply adapter to streaming response
7602
- const adaptedRes = this.applyAdapter(res);
7603
- // console.log('[DEBUG] Streaming response received:', adaptedRes)
7604
- if (adaptedRes && adaptedRes.length > 0) {
7605
- // console.log('[DEBUG] Updating state with streaming data:', adaptedRes)
7606
- this.setData$(adaptedRes);
7607
- this.streamedResponse = [...this.streamedResponse, ...adaptedRes];
7580
+ // Data is already adapted by RequestService
7581
+ if (res && res.length > 0) {
7582
+ this.setData$(res);
7583
+ this.streamedResponse = [...this.streamedResponse, ...res];
7608
7584
  }
7609
7585
  }), concatMap((packet) => {
7610
7586
  if (packet?.fromCache) {
7611
7587
  return of(packet?.data);
7612
7588
  }
7613
7589
  return this.persistStreamDataToDb(packet?.data, options);
7614
- }), map((res) => {
7615
- // console.log('[DEBUG] Returning data to subscribers:', res)
7616
- return res;
7617
- }), catchError((error) => {
7590
+ }), map((res) => res), catchError((error) => {
7618
7591
  console.error('[DEBUG] Streaming error:', error);
7619
7592
  return of([]);
7620
7593
  }), finalize(() => this.httpManagerService.isPending.next(false)));
@@ -7622,23 +7595,12 @@ class HTTPManagerStateService extends ComponentStore {
7622
7595
  // If no database is configured, always call the API (do not check tracker)
7623
7596
  return this.httpManagerService.getRequest(requestOptions, effectiveParams)
7624
7597
  .pipe(tap((res) => {
7625
- // Apply adapter to streaming response
7626
- const adaptedRes = this.applyAdapter(res);
7627
- console.log('[DEBUG] Streaming response received:', adaptedRes);
7628
- // Always update state with streaming data
7629
- if (adaptedRes && adaptedRes.length > 0) {
7630
- // console.log('[DEBUG] Updating state with streaming data:', adaptedRes)
7631
- this.setData$(adaptedRes);
7632
- this.streamedResponse = [...this.streamedResponse, ...adaptedRes];
7598
+ // Data is already adapted by RequestService
7599
+ if (res && res.length > 0) {
7600
+ this.setData$(res);
7601
+ this.streamedResponse = [...this.streamedResponse, ...res];
7633
7602
  }
7634
- else {
7635
- // console.log('[DEBUG] No streaming data or empty array:', adaptedRes)
7636
- }
7637
- }), concatMap((res) => this.persistStreamDataToDb(res, options)), map((res) => {
7638
- // console.log('[DEBUG] Returning data to subscribers:', res)
7639
- return res; // Return the data so subscribers can receive it
7640
- }), catchError((error) => {
7641
- // console.error('[DEBUG] Streaming error:', error)
7603
+ }), concatMap((res) => this.persistStreamDataToDb(res, options)), map((res) => res), catchError((error) => {
7642
7604
  return of([]);
7643
7605
  }), finalize(() => this.httpManagerService.isPending.next(false)));
7644
7606
  })));
@@ -7926,17 +7888,16 @@ class HTTPManagerStateService extends ComponentStore {
7926
7888
  if (!this.hasDatabase || !this.databaseOptions?.table) {
7927
7889
  return of(payload);
7928
7890
  }
7929
- // Apply adapter to payload before processing
7930
- const adaptedPayload = this.applyAdapter(payload);
7931
- const dbData = (adaptedPayload?.results && Array.isArray(adaptedPayload.results))
7932
- ? adaptedPayload.results
7933
- : Array.isArray(adaptedPayload)
7934
- ? adaptedPayload
7935
- : adaptedPayload
7936
- ? [adaptedPayload]
7891
+ // Payload is already adapted by RequestService.requestStreaming() pipe - no need to adapt again
7892
+ const dbData = (payload?.results && Array.isArray(payload.results))
7893
+ ? payload.results
7894
+ : Array.isArray(payload)
7895
+ ? payload
7896
+ : payload
7897
+ ? [payload]
7937
7898
  : [];
7938
7899
  if (dbData.length === 0) {
7939
- return of(adaptedPayload);
7900
+ return of(payload);
7940
7901
  }
7941
7902
  const tableName = this.databaseOptions.table;
7942
7903
  const requestOptions = this.updateRequestOptions(streamOptions?.headers);
@@ -7955,13 +7916,13 @@ class HTTPManagerStateService extends ComponentStore {
7955
7916
  return ensureTable$.pipe(switchMap((created) => {
7956
7917
  if (!created) {
7957
7918
  console.warn('[DB STORAGE] Stream table create/open not ready, skipping DB write for this chunk:', { table: tableName });
7958
- return of(adaptedPayload);
7919
+ return of(payload);
7959
7920
  }
7960
- return this.dbManagerService.createTableRecords(tableName, dbData).pipe(tap(() => this.saveRequestCacheMetadata(tableName, 'STREAM', requestSignature, schemaSignature, streamOptions)), map(() => adaptedPayload));
7921
+ return this.dbManagerService.createTableRecords(tableName, dbData).pipe(tap(() => this.saveRequestCacheMetadata(tableName, 'STREAM', requestSignature, schemaSignature, streamOptions)), map(() => payload));
7961
7922
  }));
7962
- }), map(() => adaptedPayload), catchError((error) => {
7923
+ }), map(() => payload), catchError((error) => {
7963
7924
  console.error('[DB STORAGE] Failed to persist streaming payload:', { table: tableName, schema, error });
7964
- return of(adaptedPayload);
7925
+ return of(payload);
7965
7926
  }));
7966
7927
  }
7967
7928
  // WEBSOCKET COMMUNICATION (STATE MANAGER)
@@ -8283,19 +8244,8 @@ class HTTPManagerStateService extends ComponentStore {
8283
8244
  return Object.keys(obj).length === 0;
8284
8245
  }
8285
8246
  /**
8286
- * Apply adapter to data if adapter is provided
8287
- * Handles both array and single object responses
8288
- * Only applies adapter when it exists - returns data as-is otherwise
8247
+ * Update request options with provided headers
8289
8248
  */
8290
- applyAdapter(data) {
8291
- if (!data || !this.apiOptions?.adapter) {
8292
- return data;
8293
- }
8294
- if (Array.isArray(data)) {
8295
- return data.map((item) => this.apiOptions.adapter(item));
8296
- }
8297
- return this.apiOptions.adapter(data);
8298
- }
8299
8249
  updateRequestOptions(headers) {
8300
8250
  const options = ApiRequest.adapt({ ...this.apiOptions });
8301
8251
  options.headers = (headers)
@@ -8419,6 +8369,58 @@ class HTTPManagerStateService extends ComponentStore {
8419
8369
  const currentQueryParams = { ...(currentEntry.queryParams || {}) };
8420
8370
  const currentQueryCombinations = [...(currentEntry.queryCombinations || [])];
8421
8371
  const currentQueryParamsExpires = currentEntry.queryParamsExpires ?? null;
8372
+ // Extract query params from options?.path and build combination string
8373
+ const resolvedPath = this.resolvePath(options?.path);
8374
+ const extractedParams = {};
8375
+ const ignoreQueryParams = Array.isArray(options?.ignoreQueryParams) ? options.ignoreQueryParams : [];
8376
+ if (Array.isArray(resolvedPath)) {
8377
+ const normalizedIgnore = ignoreQueryParams.map(p => this.trackerNormalizeParamKey(p));
8378
+ resolvedPath.forEach((pathPart) => {
8379
+ // Extract query params from objects in the path array
8380
+ if (pathPart && typeof pathPart === 'object' && !Array.isArray(pathPart)) {
8381
+ Object.keys(pathPart).forEach((key) => {
8382
+ const normalizedKey = this.trackerNormalizeParamKey(key);
8383
+ const value = String(pathPart[key]);
8384
+ // Only add to queryParams if NOT in ignoreQueryParams
8385
+ if (!normalizedIgnore.includes(normalizedKey)) {
8386
+ if (!currentQueryParams[key]) {
8387
+ currentQueryParams[key] = [];
8388
+ }
8389
+ if (!currentQueryParams[key].includes(value)) {
8390
+ currentQueryParams[key].push(value);
8391
+ }
8392
+ // Track extracted param for combination string
8393
+ extractedParams[normalizedKey] = value;
8394
+ }
8395
+ });
8396
+ }
8397
+ else if (typeof pathPart === 'string') {
8398
+ // Parse URL query strings like 'items?active=true&location=6'
8399
+ const normalized = this.trackerNormalizePath([pathPart]);
8400
+ if (normalized.hasQuery) {
8401
+ const filtered = this.trackerFilterQuery(normalized.query, ignoreQueryParams);
8402
+ Object.assign(extractedParams, filtered);
8403
+ // Add filtered params to queryParams
8404
+ Object.keys(filtered).forEach((key) => {
8405
+ if (!currentQueryParams[key]) {
8406
+ currentQueryParams[key] = [];
8407
+ }
8408
+ if (!currentQueryParams[key].includes(filtered[key])) {
8409
+ currentQueryParams[key].push(filtered[key]);
8410
+ }
8411
+ });
8412
+ }
8413
+ }
8414
+ });
8415
+ }
8416
+ // Build combination string if we have extracted params
8417
+ if (Object.keys(extractedParams).length > 0) {
8418
+ const keys = Object.keys(extractedParams).sort();
8419
+ const combinationString = keys.map((k) => `${k}=${extractedParams[k]}`).join('&');
8420
+ if (!currentQueryCombinations.includes(combinationString)) {
8421
+ currentQueryCombinations.push(combinationString);
8422
+ }
8423
+ }
8422
8424
  this.localStorageManagerService.updateStore({
8423
8425
  name: tableName,
8424
8426
  data: {
@@ -8429,7 +8431,7 @@ class HTTPManagerStateService extends ComponentStore {
8429
8431
  ...currentEntry,
8430
8432
  signature,
8431
8433
  savedAt: Date.now(),
8432
- path: this.resolvePath(options?.path),
8434
+ path: resolvedPath,
8433
8435
  headers: this.filterHeaders(options?.headers),
8434
8436
  queryCombinations: currentQueryCombinations,
8435
8437
  queryParams: currentQueryParams,
@@ -8556,22 +8558,6 @@ class HTTPManagerStateService extends ComponentStore {
8556
8558
  });
8557
8559
  return result;
8558
8560
  }
8559
- trackerBuildExpiryEpoch(expireIn) {
8560
- if (typeof expireIn === 'undefined' || expireIn === null || expireIn === '')
8561
- return null;
8562
- if (typeof expireIn === 'number' && Number.isFinite(expireIn) && expireIn > 0) {
8563
- return Math.floor(Date.now() / 1000) + Math.floor(expireIn);
8564
- }
8565
- const raw = String(expireIn).trim().toLowerCase().replace(/\s+/g, '');
8566
- const parsed = raw.match(/^(\d+)(y|w|d|hr|h|mn|min|m|s)$/);
8567
- if (!parsed)
8568
- return null;
8569
- const toSeconds = { y: 31556926, w: 604800, d: 86400, hr: 3600, h: 3600, mn: 60, min: 60, m: 60, s: 1 };
8570
- const seconds = toSeconds[parsed[2]];
8571
- if (!seconds)
8572
- return null;
8573
- return Math.floor(Date.now() / 1000) + Number(parsed[1]) * seconds;
8574
- }
8575
8561
  checkTrackerAllowsRequest(tableName, type, path, options, storeData) {
8576
8562
  const normalized = this.trackerNormalizePath(path);
8577
8563
  const ignoreQueryParams = Array.isArray(options?.ignoreQueryParams) ? options.ignoreQueryParams : [];
@@ -8590,58 +8576,47 @@ class HTTPManagerStateService extends ComponentStore {
8590
8576
  const combinationString = keys.sort().map((k) => `${k}=${filtered[k]}`).join('&');
8591
8577
  // Legacy per-key queryParams for backward compatibility (read-only)
8592
8578
  const queryParams = { ...(meta.queryParams || {}) };
8593
- let queryParamsExpires = meta.queryParamsExpires ?? null;
8579
+ const queryParamsExpires = meta.queryParamsExpires ?? null;
8594
8580
  // New combination-based tracking
8595
- let queryCombinations = [...(meta.queryCombinations || [])];
8581
+ const queryCombinations = [...(meta.queryCombinations || [])];
8596
8582
  // Reset combinations if the request path has changed (different endpoint)
8597
8583
  // Use trackerNormalizePath so inline query strings (e.g. 'items?a=1') are stripped
8598
8584
  // before comparing, matching the same normalization applied to the current request.
8599
8585
  const storedPathKey = meta.path
8600
8586
  ? this.trackerNormalizePath(meta.path.filter((p) => typeof p === 'string' || typeof p === 'number').map(String)).pathKey
8601
8587
  : null;
8602
- if (storedPathKey && storedPathKey !== normalized.pathKey) {
8603
- queryCombinations = [];
8604
- // Also clear legacy per-key tracking so old data from a different path doesn't block
8605
- Object.keys(queryParams).forEach((k) => delete queryParams[k]);
8606
- queryParamsExpires = null;
8607
- }
8608
- if (queryParamsExpires !== null && queryParamsExpires <= now) {
8609
- queryCombinations = [];
8610
- queryParamsExpires = null;
8611
- Object.keys(queryParams).forEach((k) => delete queryParams[k]);
8612
- }
8588
+ const pathChanged = storedPathKey && storedPathKey !== normalized.pathKey;
8589
+ const isExpired = queryParamsExpires !== null && queryParamsExpires <= now;
8590
+ const shouldReset = pathChanged || isExpired;
8613
8591
  // Determine if request is accepted (not yet tracked)
8614
8592
  // Use combination-based tracking when available; fall back to legacy per-key tracking
8615
- let accepted;
8616
- if (queryCombinations.length > 0) {
8617
- accepted = !queryCombinations.includes(combinationString);
8618
- }
8619
- else if (Object.keys(queryParams).length > 0) {
8620
- // Legacy per-key backward compatibility
8621
- accepted = !keys.every((key) => {
8622
- const consumed = queryParams[key] || [];
8623
- return consumed.includes(filtered[key]);
8624
- });
8625
- }
8626
- else {
8627
- accepted = true;
8628
- }
8629
- if (accepted) {
8630
- queryCombinations = [...queryCombinations, combinationString];
8631
- // Also update legacy queryParams so existing consumers still work
8632
- keys.forEach(key => {
8593
+ const accepted = shouldReset
8594
+ ? true
8595
+ : queryCombinations.length > 0
8596
+ ? !queryCombinations.includes(combinationString)
8597
+ : Object.keys(queryParams).length > 0
8598
+ ? !keys.every((key) => (queryParams[key] || []).includes(filtered[key]))
8599
+ : true;
8600
+ // Compute updated values immutably
8601
+ const updatedQueryCombinations = accepted
8602
+ ? [...queryCombinations, combinationString]
8603
+ : queryCombinations;
8604
+ const updatedQueryParams = accepted
8605
+ ? keys.reduce((acc, key) => {
8633
8606
  const value = filtered[key];
8634
- const consumed = queryParams[key] || [];
8607
+ const consumed = acc[key] || [];
8635
8608
  if (!consumed.includes(value)) {
8636
- queryParams[key] = [...consumed, value];
8609
+ acc[key] = [...consumed, value];
8637
8610
  }
8638
- });
8639
- }
8640
- const newExpiry = this.trackerBuildExpiryEpoch(options?.queryParamsExpiresIn);
8641
- if (newExpiry !== null) {
8642
- queryParamsExpires = newExpiry;
8643
- }
8644
- if (accepted || newExpiry !== null) {
8611
+ return acc;
8612
+ }, { ...queryParams })
8613
+ : { ...queryParams };
8614
+ const updatedQueryParamsExpires = this.utils.expires(options?.queryParamsExpiresIn) ?? queryParamsExpires;
8615
+ // Apply reset if path changed or expired
8616
+ const finalQueryCombinations = shouldReset ? updatedQueryCombinations : queryCombinations;
8617
+ const finalQueryParams = shouldReset ? updatedQueryParams : queryParams;
8618
+ const finalQueryParamsExpires = shouldReset ? updatedQueryParamsExpires : updatedQueryParamsExpires;
8619
+ if (accepted || updatedQueryParamsExpires !== queryParamsExpires) {
8645
8620
  this.localStorageManagerService.store$(tableName).pipe(take(1), tap((latestStoreData) => {
8646
8621
  const currentCache = latestStoreData?.requestCache || {};
8647
8622
  const currentEntry = currentCache[type] || {};
@@ -8653,9 +8628,9 @@ class HTTPManagerStateService extends ComponentStore {
8653
8628
  ...currentCache,
8654
8629
  [type]: {
8655
8630
  ...currentEntry,
8656
- queryCombinations,
8657
- queryParams,
8658
- queryParamsExpires,
8631
+ queryCombinations: finalQueryCombinations,
8632
+ queryParams: finalQueryParams,
8633
+ queryParamsExpires: finalQueryParamsExpires,
8659
8634
  }
8660
8635
  }
8661
8636
  }