http-request-manager 18.13.36 → 18.13.38
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.
|
@@ -382,7 +382,7 @@ class SymmetricalEncryptionService {
|
|
|
382
382
|
}
|
|
383
383
|
decrypt(str, key = this.appID) {
|
|
384
384
|
if (!str || key === '')
|
|
385
|
-
return;
|
|
385
|
+
return null;
|
|
386
386
|
let _key = CryptoJS.enc.Utf8.parse(key);
|
|
387
387
|
let _iv = CryptoJS.enc.Utf8.parse(key);
|
|
388
388
|
try {
|
|
@@ -401,7 +401,10 @@ class SymmetricalEncryptionService {
|
|
|
401
401
|
return decryptedStr;
|
|
402
402
|
}
|
|
403
403
|
catch (error) {
|
|
404
|
-
|
|
404
|
+
const message = String(error?.message || '');
|
|
405
|
+
if (message && !message.includes('Malformed UTF-8 data')) {
|
|
406
|
+
console.warn('Decryption failed');
|
|
407
|
+
}
|
|
405
408
|
return null;
|
|
406
409
|
}
|
|
407
410
|
return null;
|
|
@@ -5158,13 +5161,18 @@ class LocalStorageManagerService extends ComponentStore {
|
|
|
5158
5161
|
}
|
|
5159
5162
|
let storageData = found.data;
|
|
5160
5163
|
if (options.encrypted) {
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
storageData = decryptedData;
|
|
5164
|
+
if (this.isString(found.data) && !this.encryptionTest.isEncrypted(found.data)) {
|
|
5165
|
+
storageData = found.data;
|
|
5164
5166
|
}
|
|
5165
5167
|
else {
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
+
const decryptedData = this.encryption.decrypt(found.data, this.app.appID);
|
|
5169
|
+
if (decryptedData !== null) {
|
|
5170
|
+
storageData = decryptedData;
|
|
5171
|
+
}
|
|
5172
|
+
else {
|
|
5173
|
+
console.warn(`Failed to decrypt data for store: ${store}`);
|
|
5174
|
+
storageData = found.data;
|
|
5175
|
+
}
|
|
5168
5176
|
}
|
|
5169
5177
|
}
|
|
5170
5178
|
try {
|
|
@@ -5362,34 +5370,31 @@ class LocalStorageManagerService extends ComponentStore {
|
|
|
5362
5370
|
sessionData = [];
|
|
5363
5371
|
}
|
|
5364
5372
|
if (str) {
|
|
5365
|
-
const
|
|
5366
|
-
if (
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
console.warn('Failed to parse decrypted settings:', error);
|
|
5372
|
-
settings = [];
|
|
5373
|
+
const plainSettings = this.tryParseSettingsArray(str);
|
|
5374
|
+
if (plainSettings) {
|
|
5375
|
+
settings = plainSettings;
|
|
5376
|
+
const migratedSettings = this.encryption.encrypt(settings, this.app.appID);
|
|
5377
|
+
if (migratedSettings) {
|
|
5378
|
+
localStorage.setItem(this.storageSettingsName, migratedSettings);
|
|
5373
5379
|
}
|
|
5380
|
+
console.warn('Recovered settings from plaintext storage and migrated to encrypted format');
|
|
5374
5381
|
}
|
|
5375
5382
|
else {
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
const
|
|
5379
|
-
if (
|
|
5380
|
-
settings =
|
|
5381
|
-
const migratedSettings = this.encryption.encrypt(settings, this.app.appID);
|
|
5382
|
-
if (migratedSettings) {
|
|
5383
|
-
localStorage.setItem(this.storageSettingsName, migratedSettings);
|
|
5384
|
-
}
|
|
5385
|
-
console.warn('Recovered settings from plaintext storage and migrated to encrypted format');
|
|
5383
|
+
const decryptedStr = this.encryption.decrypt(str, this.app.appID);
|
|
5384
|
+
if (decryptedStr) {
|
|
5385
|
+
const decryptedSettings = this.tryParseSettingsArray(decryptedStr);
|
|
5386
|
+
if (decryptedSettings) {
|
|
5387
|
+
settings = decryptedSettings;
|
|
5386
5388
|
}
|
|
5387
5389
|
else {
|
|
5390
|
+
console.warn('Failed to parse decrypted settings data. Resetting corrupted settings store.');
|
|
5391
|
+
localStorage.removeItem(this.storageSettingsName);
|
|
5388
5392
|
settings = [];
|
|
5389
5393
|
}
|
|
5390
5394
|
}
|
|
5391
|
-
|
|
5392
|
-
console.warn('Failed to
|
|
5395
|
+
else {
|
|
5396
|
+
console.warn('Failed to decrypt settings data. Resetting corrupted settings store.');
|
|
5397
|
+
localStorage.removeItem(this.storageSettingsName);
|
|
5393
5398
|
settings = [];
|
|
5394
5399
|
}
|
|
5395
5400
|
}
|
|
@@ -5469,16 +5474,16 @@ class LocalStorageManagerService extends ComponentStore {
|
|
|
5469
5474
|
try {
|
|
5470
5475
|
const str = localStorage.getItem(this.storageSettingsName);
|
|
5471
5476
|
if (str) {
|
|
5472
|
-
|
|
5477
|
+
const plainSettings = this.tryParseSettingsArray(str);
|
|
5478
|
+
if (plainSettings) {
|
|
5479
|
+
return false;
|
|
5480
|
+
}
|
|
5473
5481
|
const decryptedStr = this.encryption.decrypt(str, this.app.appID);
|
|
5474
5482
|
if (decryptedStr !== null && decryptedStr !== undefined) {
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
}
|
|
5478
|
-
else {
|
|
5479
|
-
// Decryption failed, data is likely corrupted
|
|
5480
|
-
return true;
|
|
5483
|
+
const decryptedSettings = this.tryParseSettingsArray(decryptedStr);
|
|
5484
|
+
return !decryptedSettings;
|
|
5481
5485
|
}
|
|
5486
|
+
return true;
|
|
5482
5487
|
}
|
|
5483
5488
|
return false;
|
|
5484
5489
|
}
|
|
@@ -5487,6 +5492,42 @@ class LocalStorageManagerService extends ComponentStore {
|
|
|
5487
5492
|
return true;
|
|
5488
5493
|
}
|
|
5489
5494
|
}
|
|
5495
|
+
tryParseSettingsArray(raw) {
|
|
5496
|
+
if (!raw) {
|
|
5497
|
+
return null;
|
|
5498
|
+
}
|
|
5499
|
+
if (Array.isArray(raw)) {
|
|
5500
|
+
return raw;
|
|
5501
|
+
}
|
|
5502
|
+
if (!this.isString(raw)) {
|
|
5503
|
+
return null;
|
|
5504
|
+
}
|
|
5505
|
+
try {
|
|
5506
|
+
const parsed = JSON.parse(raw);
|
|
5507
|
+
if (Array.isArray(parsed)) {
|
|
5508
|
+
return parsed;
|
|
5509
|
+
}
|
|
5510
|
+
if (this.isString(parsed)) {
|
|
5511
|
+
const nestedParsed = JSON.parse(parsed);
|
|
5512
|
+
if (Array.isArray(nestedParsed)) {
|
|
5513
|
+
return nestedParsed;
|
|
5514
|
+
}
|
|
5515
|
+
}
|
|
5516
|
+
}
|
|
5517
|
+
catch {
|
|
5518
|
+
// Continue to fallback parser
|
|
5519
|
+
}
|
|
5520
|
+
try {
|
|
5521
|
+
const fallbackParsed = this.fixAndParseJSON(raw);
|
|
5522
|
+
if (Array.isArray(fallbackParsed)) {
|
|
5523
|
+
return fallbackParsed;
|
|
5524
|
+
}
|
|
5525
|
+
}
|
|
5526
|
+
catch {
|
|
5527
|
+
return null;
|
|
5528
|
+
}
|
|
5529
|
+
return null;
|
|
5530
|
+
}
|
|
5490
5531
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageManagerService, deps: [{ token: CONFIG_SETTINGS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5491
5532
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageManagerService, providedIn: 'root' }); }
|
|
5492
5533
|
}
|
|
@@ -5541,13 +5582,18 @@ class LocalStorageSignalsManagerService {
|
|
|
5541
5582
|
}
|
|
5542
5583
|
let storageData = found.data;
|
|
5543
5584
|
if (options.encrypted) {
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
storageData = decryptedData;
|
|
5585
|
+
if (this.isString(found.data) && !this.encryptionTest.isEncrypted(found.data)) {
|
|
5586
|
+
storageData = found.data;
|
|
5547
5587
|
}
|
|
5548
5588
|
else {
|
|
5549
|
-
|
|
5550
|
-
|
|
5589
|
+
const decryptedData = this.encryption.decrypt(found.data, this.app.appID);
|
|
5590
|
+
if (decryptedData !== null) {
|
|
5591
|
+
storageData = decryptedData;
|
|
5592
|
+
}
|
|
5593
|
+
else {
|
|
5594
|
+
console.warn(`Failed to decrypt data for store: ${store}`);
|
|
5595
|
+
storageData = found.data; // Use undecrypted data as fallback
|
|
5596
|
+
}
|
|
5551
5597
|
}
|
|
5552
5598
|
}
|
|
5553
5599
|
try {
|
|
@@ -5682,23 +5728,51 @@ class LocalStorageSignalsManagerService {
|
|
|
5682
5728
|
const str = localStorage.getItem(this.storageSettingsName);
|
|
5683
5729
|
const localStr = localStorage.getItem(this.storageName);
|
|
5684
5730
|
const sessionStr = sessionStorage.getItem(this.storageName);
|
|
5685
|
-
|
|
5686
|
-
|
|
5731
|
+
let localData = [];
|
|
5732
|
+
let sessionData = [];
|
|
5733
|
+
try {
|
|
5734
|
+
localData = localStr ? JSON.parse(localStr) : [];
|
|
5735
|
+
}
|
|
5736
|
+
catch (error) {
|
|
5737
|
+
console.warn('Failed to parse local storage data:', error);
|
|
5738
|
+
localData = [];
|
|
5739
|
+
}
|
|
5740
|
+
try {
|
|
5741
|
+
sessionData = sessionStr ? JSON.parse(sessionStr) : [];
|
|
5742
|
+
}
|
|
5743
|
+
catch (error) {
|
|
5744
|
+
console.warn('Failed to parse session storage data:', error);
|
|
5745
|
+
sessionData = [];
|
|
5746
|
+
}
|
|
5687
5747
|
let settings = [];
|
|
5688
5748
|
if (str) {
|
|
5689
|
-
const
|
|
5690
|
-
if (
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
console.warn('Failed to parse decrypted settings:', error);
|
|
5696
|
-
settings = [];
|
|
5749
|
+
const plainSettings = this.tryParseSettingsArray(str);
|
|
5750
|
+
if (plainSettings) {
|
|
5751
|
+
settings = plainSettings;
|
|
5752
|
+
const migratedSettings = this.encryption.encrypt(settings, this.app.appID);
|
|
5753
|
+
if (migratedSettings) {
|
|
5754
|
+
localStorage.setItem(this.storageSettingsName, migratedSettings);
|
|
5697
5755
|
}
|
|
5756
|
+
console.warn('Recovered settings from plaintext storage and migrated to encrypted format');
|
|
5698
5757
|
}
|
|
5699
5758
|
else {
|
|
5700
|
-
|
|
5701
|
-
|
|
5759
|
+
const decryptedStr = this.encryption.decrypt(str, this.app.appID);
|
|
5760
|
+
if (decryptedStr) {
|
|
5761
|
+
const decryptedSettings = this.tryParseSettingsArray(decryptedStr);
|
|
5762
|
+
if (decryptedSettings) {
|
|
5763
|
+
settings = decryptedSettings;
|
|
5764
|
+
}
|
|
5765
|
+
else {
|
|
5766
|
+
console.warn('Failed to parse decrypted settings data. Resetting corrupted settings store.');
|
|
5767
|
+
localStorage.removeItem(this.storageSettingsName);
|
|
5768
|
+
settings = [];
|
|
5769
|
+
}
|
|
5770
|
+
}
|
|
5771
|
+
else {
|
|
5772
|
+
console.warn('Failed to decrypt settings data. Resetting corrupted settings store.');
|
|
5773
|
+
localStorage.removeItem(this.storageSettingsName);
|
|
5774
|
+
settings = [];
|
|
5775
|
+
}
|
|
5702
5776
|
}
|
|
5703
5777
|
}
|
|
5704
5778
|
settings.forEach(store => {
|
|
@@ -5782,6 +5856,33 @@ class LocalStorageSignalsManagerService {
|
|
|
5782
5856
|
validStoreName(str) {
|
|
5783
5857
|
return str.toLowerCase().replace(/\s+/g, '_').replace(/[^ -~]/g, '');
|
|
5784
5858
|
}
|
|
5859
|
+
tryParseSettingsArray(raw) {
|
|
5860
|
+
if (!raw) {
|
|
5861
|
+
return null;
|
|
5862
|
+
}
|
|
5863
|
+
if (Array.isArray(raw)) {
|
|
5864
|
+
return raw;
|
|
5865
|
+
}
|
|
5866
|
+
if (!this.isString(raw)) {
|
|
5867
|
+
return null;
|
|
5868
|
+
}
|
|
5869
|
+
try {
|
|
5870
|
+
const parsed = JSON.parse(raw);
|
|
5871
|
+
if (Array.isArray(parsed)) {
|
|
5872
|
+
return parsed;
|
|
5873
|
+
}
|
|
5874
|
+
if (this.isString(parsed)) {
|
|
5875
|
+
const nestedParsed = JSON.parse(parsed);
|
|
5876
|
+
if (Array.isArray(nestedParsed)) {
|
|
5877
|
+
return nestedParsed;
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
}
|
|
5881
|
+
catch {
|
|
5882
|
+
return null;
|
|
5883
|
+
}
|
|
5884
|
+
return null;
|
|
5885
|
+
}
|
|
5785
5886
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageSignalsManagerService, deps: [{ token: CONFIG_SETTINGS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5786
5887
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageSignalsManagerService, providedIn: 'root' }); }
|
|
5787
5888
|
}
|
|
@@ -6102,7 +6203,7 @@ class DatabaseManagerService extends DbService {
|
|
|
6102
6203
|
console.error(`createTableRecords: DB not open. Cannot write to '${tableName}'.`);
|
|
6103
6204
|
return EMPTY;
|
|
6104
6205
|
}
|
|
6105
|
-
const tableInstance = this.
|
|
6206
|
+
const tableInstance = this.getTable(tableName);
|
|
6106
6207
|
if (!tableInstance) {
|
|
6107
6208
|
console.error(`createTableRecords: Table '${tableName}' does not exist in DB version ${this.verno}. Available:`, this.tables.map(t => t.name));
|
|
6108
6209
|
return EMPTY;
|
|
@@ -6110,17 +6211,49 @@ class DatabaseManagerService extends DbService {
|
|
|
6110
6211
|
console.log(`createTableRecords: Bulk putting ${insertRecords.length} records into ${tableName}`);
|
|
6111
6212
|
return from(tableInstance.bulkPut(insertRecords)).pipe(map(() => insertRecords));
|
|
6112
6213
|
}));
|
|
6214
|
+
const recreateMissingTableAndRetry = () => {
|
|
6215
|
+
const inferredSchema = this.inferSchemaFromRecords(insertRecords);
|
|
6216
|
+
if (!inferredSchema) {
|
|
6217
|
+
console.warn(`createTableRecords: Could not infer schema for '${tableName}'. Retrying after DB reopen.`);
|
|
6218
|
+
return from(this.createNewDatabase()).pipe(switchMap(() => writeRecords()));
|
|
6219
|
+
}
|
|
6220
|
+
const tableDef = TableSchemaDef.adapt({ table: tableName, schema: inferredSchema });
|
|
6221
|
+
return this.createDatabaseTable(tableDef).pipe(switchMap((created) => {
|
|
6222
|
+
if (!created) {
|
|
6223
|
+
console.warn(`createTableRecords: Failed to recreate table '${tableName}' from inferred schema. Retrying after DB reopen.`);
|
|
6224
|
+
return from(this.createNewDatabase()).pipe(switchMap(() => writeRecords()));
|
|
6225
|
+
}
|
|
6226
|
+
return writeRecords();
|
|
6227
|
+
}));
|
|
6228
|
+
};
|
|
6113
6229
|
return writeRecords().pipe(catchError((error) => {
|
|
6114
6230
|
if (!this.isMissingObjectStoreError(error)) {
|
|
6115
6231
|
throw error;
|
|
6116
6232
|
}
|
|
6117
|
-
console.warn(`createTableRecords: Missing object store for '${tableName}'.
|
|
6118
|
-
return
|
|
6233
|
+
console.warn(`createTableRecords: Missing object store for '${tableName}'. Recreating table and retrying once...`, error);
|
|
6234
|
+
return recreateMissingTableAndRetry().pipe(catchError((retryError) => {
|
|
6119
6235
|
console.error(`createTableRecords: Retry failed for '${tableName}'`, retryError);
|
|
6120
6236
|
throw retryError;
|
|
6121
6237
|
}));
|
|
6122
6238
|
}));
|
|
6123
6239
|
}
|
|
6240
|
+
inferSchemaFromRecords(records) {
|
|
6241
|
+
if (!Array.isArray(records) || records.length === 0) {
|
|
6242
|
+
return null;
|
|
6243
|
+
}
|
|
6244
|
+
const sample = records.find((record) => record && typeof record === 'object');
|
|
6245
|
+
if (!sample) {
|
|
6246
|
+
return null;
|
|
6247
|
+
}
|
|
6248
|
+
const fields = Object.keys(sample)
|
|
6249
|
+
.filter((key) => key !== 'id')
|
|
6250
|
+
.filter((key) => {
|
|
6251
|
+
const value = sample[key];
|
|
6252
|
+
return value === null || ['string', 'number', 'boolean'].includes(typeof value);
|
|
6253
|
+
})
|
|
6254
|
+
.sort();
|
|
6255
|
+
return ['++id', ...fields].join(', ');
|
|
6256
|
+
}
|
|
6124
6257
|
isMissingObjectStoreError(error) {
|
|
6125
6258
|
const name = String(error?.name || '').toLowerCase();
|
|
6126
6259
|
const innerName = String(error?.inner?.name || '').toLowerCase();
|