http-request-manager 18.16.25 → 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.
|
@@ -6610,16 +6610,19 @@ class DatabaseManagerService extends DbService {
|
|
|
6610
6610
|
}
|
|
6611
6611
|
updateTableRecord(table, record) {
|
|
6612
6612
|
const tableName = this.cleanTableName(table);
|
|
6613
|
+
console.log(`🔵 updateTableRecord: INPUT table='${table}' CLEANED='${tableName}'`);
|
|
6613
6614
|
return this.updateTableRecords(tableName, [record])
|
|
6614
6615
|
.pipe(map(item => item.length > 0 ? item[0] : null));
|
|
6615
6616
|
}
|
|
6616
6617
|
updateTableRecords(table, records) {
|
|
6617
6618
|
const tableName = this.cleanTableName(table);
|
|
6619
|
+
console.log(`🔵 updateTableRecords: INPUT table='${table}' CLEANED='${tableName}' recordCount=${records.length}`);
|
|
6618
6620
|
return this.getDatabaseTable(tableName).pipe(switchMap((tableData) => {
|
|
6619
6621
|
if (!tableData) {
|
|
6620
|
-
console.warn(
|
|
6622
|
+
console.warn(`❌ updateTableRecords: Table '${tableName}' not found`);
|
|
6621
6623
|
return EMPTY;
|
|
6622
6624
|
}
|
|
6625
|
+
console.log(`✅ updateTableRecords: Table '${tableName}' FOUND, executing bulkPut with ${records.length} records`);
|
|
6623
6626
|
const insertRecords = records.map((record) => {
|
|
6624
6627
|
const payload = { ...(record || {}) };
|
|
6625
6628
|
if (payload.id === undefined || payload.id === null || payload.id === '') {
|
|
@@ -7228,19 +7231,16 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7228
7231
|
}
|
|
7229
7232
|
return this.httpManagerService.getRequest(requestOptions, effectiveParams).pipe(tap((data) => {
|
|
7230
7233
|
// Extract array from paginated response if needed
|
|
7234
|
+
// Data is already adapted by RequestService.request() pipe - no need to adapt again
|
|
7231
7235
|
const arrayData = (data?.results && Array.isArray(data.results)) ? data.results : data;
|
|
7232
|
-
|
|
7233
|
-
let adaptedData = this.applyAdapter(arrayData);
|
|
7234
|
-
adaptedData = (!adaptedData) ? (this.dataType === DataType.ARRAY) ? [] : {} : adaptedData;
|
|
7235
|
-
this.setData$(adaptedData);
|
|
7236
|
+
this.setData$(arrayData);
|
|
7236
7237
|
}), concatMap((data) => {
|
|
7237
7238
|
// Extract array from paginated response for database storage
|
|
7239
|
+
// Data is already adapted by RequestService.request() pipe - no need to adapt again
|
|
7238
7240
|
const dbData = (data?.results && Array.isArray(data.results)) ? data.results : data;
|
|
7239
|
-
|
|
7240
|
-
const adaptedDbData = this.applyAdapter(dbData);
|
|
7241
|
-
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) {
|
|
7242
7242
|
const tableName = this.databaseOptions.table;
|
|
7243
|
-
const schema = this.buildSchemaFromSample(
|
|
7243
|
+
const schema = this.buildSchemaFromSample(dbData[0]);
|
|
7244
7244
|
const tableDef = TableSchemaDef.adapt({ table: tableName, schema });
|
|
7245
7245
|
const schemaSignature = this.buildSchemaSignature(schema);
|
|
7246
7246
|
// Always ensure table exists immediately before writing to avoid stale schema/store races.
|
|
@@ -7255,7 +7255,7 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7255
7255
|
console.warn('[DB STORAGE] Table create/open not ready, skipping DB write for this payload:', { table: tableName });
|
|
7256
7256
|
return of(data);
|
|
7257
7257
|
}
|
|
7258
|
-
return this.dbManagerService.createTableRecords(tableName,
|
|
7258
|
+
return this.dbManagerService.createTableRecords(tableName, dbData).pipe(tap(() => this.saveRequestCacheMetadata(tableName, 'GET', requestSignature, schemaSignature, options)));
|
|
7259
7259
|
}));
|
|
7260
7260
|
}), catchError((error) => {
|
|
7261
7261
|
console.error('[DB STORAGE] Failed to ensure table and write records:', { table: tableName, schema, error });
|
|
@@ -7368,26 +7368,37 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7368
7368
|
return this.httpManagerService.getRequest(requestOptions, effectiveParams)
|
|
7369
7369
|
.pipe(tap((data) => {
|
|
7370
7370
|
console.log('📦 fetchRecord received data:', data);
|
|
7371
|
-
//
|
|
7372
|
-
|
|
7373
|
-
|
|
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;
|
|
7374
7374
|
const id = options.path?.length ? options.path[options.path.length - 1] : null;
|
|
7375
|
+
// For single-record operations (CREATE, UPDATE, DELETE), extract from array if needed
|
|
7376
|
+
let singleRecord = finalData;
|
|
7377
|
+
if (Array.isArray(finalData) && finalData.length > 0) {
|
|
7378
|
+
singleRecord = finalData[0];
|
|
7379
|
+
}
|
|
7375
7380
|
if (method === 'DELETE') {
|
|
7376
7381
|
console.log('🗑️ Deleting record with id:', id);
|
|
7377
7382
|
this.deleteData$({ id });
|
|
7378
7383
|
}
|
|
7379
7384
|
if (method === 'UPDATE') {
|
|
7380
|
-
console.log('✏️ Updating record:',
|
|
7381
|
-
this.updateData$(
|
|
7385
|
+
console.log('✏️ Updating record:', singleRecord);
|
|
7386
|
+
this.updateData$(singleRecord);
|
|
7382
7387
|
}
|
|
7383
7388
|
if (method === 'CREATE') {
|
|
7384
|
-
console.log('➕ Adding record:',
|
|
7385
|
-
this.addData$(
|
|
7389
|
+
console.log('➕ Adding record:', finalData);
|
|
7390
|
+
this.addData$(finalData);
|
|
7386
7391
|
}
|
|
7387
7392
|
}), concatMap((data) => {
|
|
7388
|
-
|
|
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;
|
|
7389
7395
|
const tableName = this.databaseOptions?.table;
|
|
7390
7396
|
const idFromPath = options.path?.length ? options.path[options.path.length - 1] : null;
|
|
7397
|
+
// For single-record operations, extract from array if needed
|
|
7398
|
+
let singleRecord = dbData;
|
|
7399
|
+
if (Array.isArray(dbData) && dbData.length > 0) {
|
|
7400
|
+
singleRecord = dbData[0];
|
|
7401
|
+
}
|
|
7391
7402
|
if (this.hasDatabase && tableName) {
|
|
7392
7403
|
switch (method) {
|
|
7393
7404
|
case 'DELETE':
|
|
@@ -7398,18 +7409,18 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7398
7409
|
this.logger.warn('fetchRecord', 'DELETE method called but id is missing from path', { options });
|
|
7399
7410
|
break;
|
|
7400
7411
|
case 'UPDATE':
|
|
7401
|
-
if (
|
|
7402
|
-
this.logger.debug('fetchRecord', 'Updating database record', { table: tableName, id:
|
|
7403
|
-
return this.dbManagerService.updateTableRecord(tableName,
|
|
7412
|
+
if (singleRecord && singleRecord.id != null) {
|
|
7413
|
+
this.logger.debug('fetchRecord', 'Updating database record', { table: tableName, id: singleRecord.id, data: singleRecord });
|
|
7414
|
+
return this.dbManagerService.updateTableRecord(tableName, singleRecord);
|
|
7404
7415
|
}
|
|
7405
|
-
this.logger.warn('fetchRecord', 'UPDATE method called but
|
|
7416
|
+
this.logger.warn('fetchRecord', 'UPDATE method called but singleRecord or id is missing', { singleRecord, hasData: !!singleRecord, hasId: !!singleRecord?.id });
|
|
7406
7417
|
break;
|
|
7407
7418
|
case 'CREATE':
|
|
7408
|
-
if (
|
|
7409
|
-
this.logger.debug('fetchRecord', 'Creating database record', { table: tableName, id:
|
|
7410
|
-
return this.dbManagerService.createTableRecord(tableName,
|
|
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);
|
|
7411
7422
|
}
|
|
7412
|
-
this.logger.warn('fetchRecord', 'CREATE method called but data.id is invalid', {
|
|
7423
|
+
this.logger.warn('fetchRecord', 'CREATE method called but data.id is invalid', { dbData });
|
|
7413
7424
|
break;
|
|
7414
7425
|
default:
|
|
7415
7426
|
this.logger.debug('fetchRecord', 'Method does not require database operation', { method });
|
|
@@ -7421,7 +7432,7 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7421
7432
|
hasTable: !!tableName
|
|
7422
7433
|
});
|
|
7423
7434
|
}
|
|
7424
|
-
return of(
|
|
7435
|
+
return of(dbData);
|
|
7425
7436
|
}));
|
|
7426
7437
|
})));
|
|
7427
7438
|
// CREATE RECORD
|
|
@@ -7430,17 +7441,13 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7430
7441
|
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
7431
7442
|
const effectiveParams = this.getEffectiveParams(options?.path);
|
|
7432
7443
|
return this.httpManagerService.postRequest(data, requestOptions, effectiveParams)
|
|
7433
|
-
.pipe(tap((
|
|
7434
|
-
//
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
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);
|
|
7438
7448
|
this.operationSuccess.next(OperationResultModel.adapt({ success: true, operation: 'CREATE' }));
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
}), concatMap((data) => {
|
|
7442
|
-
// Apply adapter before database operations
|
|
7443
|
-
const adaptedData = this.applyAdapter(data);
|
|
7449
|
+
this.wsCommunication('CREATE', [...options?.path || [], safeData.id]);
|
|
7450
|
+
}), concatMap((adaptedData) => {
|
|
7444
7451
|
if (this.hasDatabase && this.databaseOptions?.table && adaptedData?.id) {
|
|
7445
7452
|
return this.dbManagerService.createTableRecord(this.databaseOptions.table, adaptedData);
|
|
7446
7453
|
}
|
|
@@ -7453,17 +7460,13 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7453
7460
|
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
7454
7461
|
const effectiveParams = this.getEffectiveParams(options?.path);
|
|
7455
7462
|
return this.httpManagerService.putRequest(data, requestOptions, effectiveParams)
|
|
7456
|
-
.pipe(tap((
|
|
7457
|
-
//
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
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);
|
|
7461
7467
|
this.operationSuccess.next(OperationResultModel.adapt({ success: true, operation: 'UPDATE' }));
|
|
7462
|
-
// Always call wsCommunication - it will queue if not connected
|
|
7463
7468
|
this.wsCommunication('UPDATE', [...options?.path || []]);
|
|
7464
|
-
}), concatMap((
|
|
7465
|
-
// Apply adapter before database operations
|
|
7466
|
-
const adaptedData = this.applyAdapter(data);
|
|
7469
|
+
}), concatMap((adaptedData) => {
|
|
7467
7470
|
if (this.hasDatabase && this.databaseOptions?.table && adaptedData?.id) {
|
|
7468
7471
|
return this.dbManagerService.updateTableRecord(this.databaseOptions.table, adaptedData);
|
|
7469
7472
|
}
|
|
@@ -7476,17 +7479,13 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7476
7479
|
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
7477
7480
|
const effectiveParams = this.getEffectiveParams(options?.path);
|
|
7478
7481
|
return this.httpManagerService.deleteRequest(requestOptions, effectiveParams)
|
|
7479
|
-
.pipe(tap((
|
|
7480
|
-
//
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
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);
|
|
7484
7486
|
this.operationSuccess.next(OperationResultModel.adapt({ success: true, operation: 'DELETE' }));
|
|
7485
|
-
// Always call wsCommunication - it will queue if not connected
|
|
7486
7487
|
this.wsCommunication('DELETE', [...options?.path || []]);
|
|
7487
|
-
}), concatMap((
|
|
7488
|
-
// Apply adapter before database operations
|
|
7489
|
-
const adaptedData = this.applyAdapter(data);
|
|
7488
|
+
}), concatMap((adaptedData) => {
|
|
7490
7489
|
if (this.hasDatabase && this.databaseOptions?.table && adaptedData?.id) {
|
|
7491
7490
|
return this.dbManagerService.deleteTableRecord(this.databaseOptions.table, adaptedData.id);
|
|
7492
7491
|
}
|
|
@@ -7499,13 +7498,12 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7499
7498
|
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
7500
7499
|
const effectiveParams = this.getEffectiveParams(options?.path);
|
|
7501
7500
|
return this.httpManagerService.postRequest(data, requestOptions, effectiveParams)
|
|
7502
|
-
.pipe(tap((
|
|
7503
|
-
//
|
|
7504
|
-
const adaptedRes = this.applyAdapter(res);
|
|
7501
|
+
.pipe(tap((adaptedRes) => {
|
|
7502
|
+
// Data is already adapted by RequestService
|
|
7505
7503
|
if (adaptedRes.length > 0)
|
|
7506
7504
|
this.setData$(adaptedRes);
|
|
7507
7505
|
this.streamedResponse = adaptedRes;
|
|
7508
|
-
}), concatMap((
|
|
7506
|
+
}), concatMap((adaptedRes) => this.persistStreamDataToDb(adaptedRes, options)), scan((acc, res) => {
|
|
7509
7507
|
const previous = acc.current;
|
|
7510
7508
|
const current = res;
|
|
7511
7509
|
return { previous, current };
|
|
@@ -7520,14 +7518,12 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7520
7518
|
}));
|
|
7521
7519
|
})));
|
|
7522
7520
|
this.fetchStream = (options) => this.effect(() => of(options).pipe(tap(() => {
|
|
7523
|
-
// console.log('[DEBUG] fetchStream called')
|
|
7524
7521
|
this.streamedResponse = [];
|
|
7525
7522
|
this.httpManagerService.isPending.next(true);
|
|
7526
7523
|
}), switchMap((options) => {
|
|
7527
7524
|
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
7528
7525
|
requestOptions.stream = true;
|
|
7529
7526
|
const effectiveParams = this.getEffectiveParams(options?.path);
|
|
7530
|
-
// console.log('[DEBUG] Making streaming request:', requestOptions)
|
|
7531
7527
|
if (this.hasDatabase && this.databaseOptions?.table) {
|
|
7532
7528
|
const requestSignature = this.buildRequestSignature('STREAM', requestOptions, effectiveParams);
|
|
7533
7529
|
const fetchStreamFromAPI = () => {
|
|
@@ -7536,9 +7532,7 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7536
7532
|
if (Array.isArray(currentStateData) && currentStateData.length > 0) {
|
|
7537
7533
|
return of({ data: currentStateData, fromCache: true });
|
|
7538
7534
|
}
|
|
7539
|
-
if (currentStateData &&
|
|
7540
|
-
!Array.isArray(currentStateData) &&
|
|
7541
|
-
Object.keys(currentStateData).length > 0) {
|
|
7535
|
+
if (currentStateData && !Array.isArray(currentStateData) && Object.keys(currentStateData).length > 0) {
|
|
7542
7536
|
return of({ data: currentStateData, fromCache: true });
|
|
7543
7537
|
}
|
|
7544
7538
|
return of({ data: this.dataType === DataType.ARRAY ? [] : {}, fromCache: true });
|
|
@@ -7573,9 +7567,7 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7573
7567
|
if (Array.isArray(currentStateData) && currentStateData.length > 0) {
|
|
7574
7568
|
return of({ data: currentStateData, fromCache: true });
|
|
7575
7569
|
}
|
|
7576
|
-
if (currentStateData &&
|
|
7577
|
-
!Array.isArray(currentStateData) &&
|
|
7578
|
-
Object.keys(currentStateData).length > 0) {
|
|
7570
|
+
if (currentStateData && !Array.isArray(currentStateData) && Object.keys(currentStateData).length > 0) {
|
|
7579
7571
|
return of({ data: currentStateData, fromCache: true });
|
|
7580
7572
|
}
|
|
7581
7573
|
return fetchStreamFromAPI();
|
|
@@ -7585,23 +7577,17 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7585
7577
|
}));
|
|
7586
7578
|
})).pipe(tap((packet) => {
|
|
7587
7579
|
const res = packet?.data;
|
|
7588
|
-
//
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
// console.log('[DEBUG] Updating state with streaming data:', adaptedRes)
|
|
7593
|
-
this.setData$(adaptedRes);
|
|
7594
|
-
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];
|
|
7595
7584
|
}
|
|
7596
7585
|
}), concatMap((packet) => {
|
|
7597
7586
|
if (packet?.fromCache) {
|
|
7598
7587
|
return of(packet?.data);
|
|
7599
7588
|
}
|
|
7600
7589
|
return this.persistStreamDataToDb(packet?.data, options);
|
|
7601
|
-
}), map((res) => {
|
|
7602
|
-
// console.log('[DEBUG] Returning data to subscribers:', res)
|
|
7603
|
-
return res;
|
|
7604
|
-
}), catchError((error) => {
|
|
7590
|
+
}), map((res) => res), catchError((error) => {
|
|
7605
7591
|
console.error('[DEBUG] Streaming error:', error);
|
|
7606
7592
|
return of([]);
|
|
7607
7593
|
}), finalize(() => this.httpManagerService.isPending.next(false)));
|
|
@@ -7609,23 +7595,12 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7609
7595
|
// If no database is configured, always call the API (do not check tracker)
|
|
7610
7596
|
return this.httpManagerService.getRequest(requestOptions, effectiveParams)
|
|
7611
7597
|
.pipe(tap((res) => {
|
|
7612
|
-
//
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
if (adaptedRes && adaptedRes.length > 0) {
|
|
7617
|
-
// console.log('[DEBUG] Updating state with streaming data:', adaptedRes)
|
|
7618
|
-
this.setData$(adaptedRes);
|
|
7619
|
-
this.streamedResponse = [...this.streamedResponse, ...adaptedRes];
|
|
7620
|
-
}
|
|
7621
|
-
else {
|
|
7622
|
-
// console.log('[DEBUG] No streaming data or empty array:', adaptedRes)
|
|
7598
|
+
// Data is already adapted by RequestService
|
|
7599
|
+
if (res && res.length > 0) {
|
|
7600
|
+
this.setData$(res);
|
|
7601
|
+
this.streamedResponse = [...this.streamedResponse, ...res];
|
|
7623
7602
|
}
|
|
7624
|
-
}), concatMap((res) => this.persistStreamDataToDb(res, options)), map((res) => {
|
|
7625
|
-
// console.log('[DEBUG] Returning data to subscribers:', res)
|
|
7626
|
-
return res; // Return the data so subscribers can receive it
|
|
7627
|
-
}), catchError((error) => {
|
|
7628
|
-
// console.error('[DEBUG] Streaming error:', error)
|
|
7603
|
+
}), concatMap((res) => this.persistStreamDataToDb(res, options)), map((res) => res), catchError((error) => {
|
|
7629
7604
|
return of([]);
|
|
7630
7605
|
}), finalize(() => this.httpManagerService.isPending.next(false)));
|
|
7631
7606
|
})));
|
|
@@ -7913,17 +7888,16 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7913
7888
|
if (!this.hasDatabase || !this.databaseOptions?.table) {
|
|
7914
7889
|
return of(payload);
|
|
7915
7890
|
}
|
|
7916
|
-
//
|
|
7917
|
-
const
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
? [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]
|
|
7924
7898
|
: [];
|
|
7925
7899
|
if (dbData.length === 0) {
|
|
7926
|
-
return of(
|
|
7900
|
+
return of(payload);
|
|
7927
7901
|
}
|
|
7928
7902
|
const tableName = this.databaseOptions.table;
|
|
7929
7903
|
const requestOptions = this.updateRequestOptions(streamOptions?.headers);
|
|
@@ -7942,13 +7916,13 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7942
7916
|
return ensureTable$.pipe(switchMap((created) => {
|
|
7943
7917
|
if (!created) {
|
|
7944
7918
|
console.warn('[DB STORAGE] Stream table create/open not ready, skipping DB write for this chunk:', { table: tableName });
|
|
7945
|
-
return of(
|
|
7919
|
+
return of(payload);
|
|
7946
7920
|
}
|
|
7947
|
-
return this.dbManagerService.createTableRecords(tableName, dbData).pipe(tap(() => this.saveRequestCacheMetadata(tableName, 'STREAM', requestSignature, schemaSignature, streamOptions)), map(() =>
|
|
7921
|
+
return this.dbManagerService.createTableRecords(tableName, dbData).pipe(tap(() => this.saveRequestCacheMetadata(tableName, 'STREAM', requestSignature, schemaSignature, streamOptions)), map(() => payload));
|
|
7948
7922
|
}));
|
|
7949
|
-
}), map(() =>
|
|
7923
|
+
}), map(() => payload), catchError((error) => {
|
|
7950
7924
|
console.error('[DB STORAGE] Failed to persist streaming payload:', { table: tableName, schema, error });
|
|
7951
|
-
return of(
|
|
7925
|
+
return of(payload);
|
|
7952
7926
|
}));
|
|
7953
7927
|
}
|
|
7954
7928
|
// WEBSOCKET COMMUNICATION (STATE MANAGER)
|
|
@@ -8270,19 +8244,8 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8270
8244
|
return Object.keys(obj).length === 0;
|
|
8271
8245
|
}
|
|
8272
8246
|
/**
|
|
8273
|
-
*
|
|
8274
|
-
* Handles both array and single object responses
|
|
8275
|
-
* Only applies adapter when it exists - returns data as-is otherwise
|
|
8247
|
+
* Update request options with provided headers
|
|
8276
8248
|
*/
|
|
8277
|
-
applyAdapter(data) {
|
|
8278
|
-
if (!data || !this.apiOptions?.adapter) {
|
|
8279
|
-
return data;
|
|
8280
|
-
}
|
|
8281
|
-
if (Array.isArray(data)) {
|
|
8282
|
-
return data.map((item) => this.apiOptions.adapter(item));
|
|
8283
|
-
}
|
|
8284
|
-
return this.apiOptions.adapter(data);
|
|
8285
|
-
}
|
|
8286
8249
|
updateRequestOptions(headers) {
|
|
8287
8250
|
const options = ApiRequest.adapt({ ...this.apiOptions });
|
|
8288
8251
|
options.headers = (headers)
|
|
@@ -8406,6 +8369,58 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8406
8369
|
const currentQueryParams = { ...(currentEntry.queryParams || {}) };
|
|
8407
8370
|
const currentQueryCombinations = [...(currentEntry.queryCombinations || [])];
|
|
8408
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
|
+
}
|
|
8409
8424
|
this.localStorageManagerService.updateStore({
|
|
8410
8425
|
name: tableName,
|
|
8411
8426
|
data: {
|
|
@@ -8416,7 +8431,7 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8416
8431
|
...currentEntry,
|
|
8417
8432
|
signature,
|
|
8418
8433
|
savedAt: Date.now(),
|
|
8419
|
-
path:
|
|
8434
|
+
path: resolvedPath,
|
|
8420
8435
|
headers: this.filterHeaders(options?.headers),
|
|
8421
8436
|
queryCombinations: currentQueryCombinations,
|
|
8422
8437
|
queryParams: currentQueryParams,
|
|
@@ -8543,22 +8558,6 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8543
8558
|
});
|
|
8544
8559
|
return result;
|
|
8545
8560
|
}
|
|
8546
|
-
trackerBuildExpiryEpoch(expireIn) {
|
|
8547
|
-
if (typeof expireIn === 'undefined' || expireIn === null || expireIn === '')
|
|
8548
|
-
return null;
|
|
8549
|
-
if (typeof expireIn === 'number' && Number.isFinite(expireIn) && expireIn > 0) {
|
|
8550
|
-
return Math.floor(Date.now() / 1000) + Math.floor(expireIn);
|
|
8551
|
-
}
|
|
8552
|
-
const raw = String(expireIn).trim().toLowerCase().replace(/\s+/g, '');
|
|
8553
|
-
const parsed = raw.match(/^(\d+)(y|w|d|hr|h|mn|min|m|s)$/);
|
|
8554
|
-
if (!parsed)
|
|
8555
|
-
return null;
|
|
8556
|
-
const toSeconds = { y: 31556926, w: 604800, d: 86400, hr: 3600, h: 3600, mn: 60, min: 60, m: 60, s: 1 };
|
|
8557
|
-
const seconds = toSeconds[parsed[2]];
|
|
8558
|
-
if (!seconds)
|
|
8559
|
-
return null;
|
|
8560
|
-
return Math.floor(Date.now() / 1000) + Number(parsed[1]) * seconds;
|
|
8561
|
-
}
|
|
8562
8561
|
checkTrackerAllowsRequest(tableName, type, path, options, storeData) {
|
|
8563
8562
|
const normalized = this.trackerNormalizePath(path);
|
|
8564
8563
|
const ignoreQueryParams = Array.isArray(options?.ignoreQueryParams) ? options.ignoreQueryParams : [];
|
|
@@ -8577,58 +8576,47 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8577
8576
|
const combinationString = keys.sort().map((k) => `${k}=${filtered[k]}`).join('&');
|
|
8578
8577
|
// Legacy per-key queryParams for backward compatibility (read-only)
|
|
8579
8578
|
const queryParams = { ...(meta.queryParams || {}) };
|
|
8580
|
-
|
|
8579
|
+
const queryParamsExpires = meta.queryParamsExpires ?? null;
|
|
8581
8580
|
// New combination-based tracking
|
|
8582
|
-
|
|
8581
|
+
const queryCombinations = [...(meta.queryCombinations || [])];
|
|
8583
8582
|
// Reset combinations if the request path has changed (different endpoint)
|
|
8584
8583
|
// Use trackerNormalizePath so inline query strings (e.g. 'items?a=1') are stripped
|
|
8585
8584
|
// before comparing, matching the same normalization applied to the current request.
|
|
8586
8585
|
const storedPathKey = meta.path
|
|
8587
8586
|
? this.trackerNormalizePath(meta.path.filter((p) => typeof p === 'string' || typeof p === 'number').map(String)).pathKey
|
|
8588
8587
|
: null;
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
Object.keys(queryParams).forEach((k) => delete queryParams[k]);
|
|
8593
|
-
queryParamsExpires = null;
|
|
8594
|
-
}
|
|
8595
|
-
if (queryParamsExpires !== null && queryParamsExpires <= now) {
|
|
8596
|
-
queryCombinations = [];
|
|
8597
|
-
queryParamsExpires = null;
|
|
8598
|
-
Object.keys(queryParams).forEach((k) => delete queryParams[k]);
|
|
8599
|
-
}
|
|
8588
|
+
const pathChanged = storedPathKey && storedPathKey !== normalized.pathKey;
|
|
8589
|
+
const isExpired = queryParamsExpires !== null && queryParamsExpires <= now;
|
|
8590
|
+
const shouldReset = pathChanged || isExpired;
|
|
8600
8591
|
// Determine if request is accepted (not yet tracked)
|
|
8601
8592
|
// Use combination-based tracking when available; fall back to legacy per-key tracking
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
}
|
|
8616
|
-
if (accepted) {
|
|
8617
|
-
queryCombinations = [...queryCombinations, combinationString];
|
|
8618
|
-
// Also update legacy queryParams so existing consumers still work
|
|
8619
|
-
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) => {
|
|
8620
8606
|
const value = filtered[key];
|
|
8621
|
-
const consumed =
|
|
8607
|
+
const consumed = acc[key] || [];
|
|
8622
8608
|
if (!consumed.includes(value)) {
|
|
8623
|
-
|
|
8609
|
+
acc[key] = [...consumed, value];
|
|
8624
8610
|
}
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
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) {
|
|
8632
8620
|
this.localStorageManagerService.store$(tableName).pipe(take(1), tap((latestStoreData) => {
|
|
8633
8621
|
const currentCache = latestStoreData?.requestCache || {};
|
|
8634
8622
|
const currentEntry = currentCache[type] || {};
|
|
@@ -8640,9 +8628,9 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8640
8628
|
...currentCache,
|
|
8641
8629
|
[type]: {
|
|
8642
8630
|
...currentEntry,
|
|
8643
|
-
queryCombinations,
|
|
8644
|
-
queryParams,
|
|
8645
|
-
queryParamsExpires,
|
|
8631
|
+
queryCombinations: finalQueryCombinations,
|
|
8632
|
+
queryParams: finalQueryParams,
|
|
8633
|
+
queryParamsExpires: finalQueryParamsExpires,
|
|
8646
8634
|
}
|
|
8647
8635
|
}
|
|
8648
8636
|
}
|