mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-17 16:37:43 +00:00
refactor: replace PFLog with SyncLog/OpLog and remove obsolete migration scripts
PFLog was named after "Pfapi" which is no longer used. Replace with SyncLog in sync provider files and OpLog in op-log infrastructure files. Delete unused migration scripts.
This commit is contained in:
parent
f6c9714433
commit
f78f6f4e39
36 changed files with 297 additions and 500 deletions
|
|
@ -1,146 +0,0 @@
|
|||
#!/usr/bin/env ts-node
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as glob from 'glob';
|
||||
|
||||
interface Replacement {
|
||||
pattern: RegExp;
|
||||
replacement: string;
|
||||
}
|
||||
|
||||
const replacements: Replacement[] = [
|
||||
// Replace Log.log with PFLog.log
|
||||
{ pattern: /\bLog\.log\(/g, replacement: 'PFLog.log(' },
|
||||
// Replace Log.err with PFLog.err
|
||||
{ pattern: /\bLog\.err\(/g, replacement: 'PFLog.err(' },
|
||||
// Replace Log.info with PFLog.info
|
||||
{ pattern: /\bLog\.info\(/g, replacement: 'PFLog.info(' },
|
||||
// Replace Log.debug with PFLog.debug
|
||||
{ pattern: /\bLog\.debug\(/g, replacement: 'PFLog.debug(' },
|
||||
// Replace Log.verbose with PFLog.verbose
|
||||
{ pattern: /\bLog\.verbose\(/g, replacement: 'PFLog.verbose(' },
|
||||
// Replace Log.critical with PFLog.critical
|
||||
{ pattern: /\bLog\.critical\(/g, replacement: 'PFLog.critical(' },
|
||||
];
|
||||
|
||||
function updateImports(content: string): string {
|
||||
// Check if file already imports PFLog
|
||||
const hasPFLogImport =
|
||||
/import\s*{[^}]*\bPFLog\b[^}]*}\s*from\s*['"][^'"]*\/log['"]/.test(content);
|
||||
|
||||
if (hasPFLogImport) {
|
||||
// If PFLog is already imported, just remove Log from the import if it's not used elsewhere
|
||||
return content;
|
||||
}
|
||||
|
||||
// Find existing Log import and add PFLog to it
|
||||
const logImportRegex = /import\s*{([^}]*\bLog\b[^}]*)}\s*from\s*(['"][^'"]*\/log['"])/;
|
||||
const match = content.match(logImportRegex);
|
||||
|
||||
if (match) {
|
||||
const [fullMatch, imports, importPath] = match;
|
||||
const importList = imports.split(',').map((s) => s.trim());
|
||||
|
||||
// Add PFLog if not already there
|
||||
if (!importList.includes('PFLog')) {
|
||||
importList.push('PFLog');
|
||||
}
|
||||
|
||||
// Check if Log is still used after replacements
|
||||
let tempContent = content;
|
||||
for (const { pattern, replacement } of replacements) {
|
||||
tempContent = tempContent.replace(pattern, replacement);
|
||||
}
|
||||
|
||||
// Remove the import statement from check
|
||||
tempContent = tempContent.replace(logImportRegex, '');
|
||||
|
||||
// If Log is no longer used, remove it from imports
|
||||
const logStillUsed = /\bLog\b/.test(tempContent);
|
||||
if (!logStillUsed) {
|
||||
const logIndex = importList.indexOf('Log');
|
||||
if (logIndex > -1) {
|
||||
importList.splice(logIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const newImports = importList.join(', ');
|
||||
const newImportStatement = `import { ${newImports} } from ${importPath}`;
|
||||
content = content.replace(fullMatch, newImportStatement);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
function processFile(filePath: string): { modified: boolean; changes: number } {
|
||||
try {
|
||||
let content = fs.readFileSync(filePath, 'utf8');
|
||||
const originalContent = content;
|
||||
let changeCount = 0;
|
||||
|
||||
// Count and apply replacements
|
||||
for (const { pattern, replacement } of replacements) {
|
||||
const matches = content.match(pattern);
|
||||
if (matches) {
|
||||
changeCount += matches.length;
|
||||
content = content.replace(pattern, replacement);
|
||||
}
|
||||
}
|
||||
|
||||
// Update imports if changes were made
|
||||
if (changeCount > 0) {
|
||||
content = updateImports(content);
|
||||
}
|
||||
|
||||
const modified = content !== originalContent;
|
||||
|
||||
if (modified) {
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
}
|
||||
|
||||
return { modified, changes: changeCount };
|
||||
} catch (error) {
|
||||
console.error(`Error processing ${filePath}:`, error);
|
||||
return { modified: false, changes: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log('Migrating Log to PFLog in pfapi directory...\n');
|
||||
|
||||
// Find all TypeScript files in pfapi directory
|
||||
const files = glob.sync('src/app/pfapi/**/*.ts', {
|
||||
ignore: ['**/*.spec.ts', '**/node_modules/**'],
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
console.log(`Found ${files.length} TypeScript files in pfapi directory\n`);
|
||||
|
||||
const modifiedFiles: { path: string; changes: number }[] = [];
|
||||
let totalChanges = 0;
|
||||
|
||||
for (const file of files) {
|
||||
const result = processFile(file);
|
||||
if (result.modified) {
|
||||
modifiedFiles.push({ path: file, changes: result.changes });
|
||||
totalChanges += result.changes;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\nMigration complete!\n');
|
||||
console.log(`Total changes: ${totalChanges}`);
|
||||
console.log(`Modified ${modifiedFiles.length} files:\n`);
|
||||
|
||||
modifiedFiles
|
||||
.sort((a, b) => b.changes - a.changes)
|
||||
.forEach(({ path: filePath, changes }) => {
|
||||
console.log(` - ${path.relative(process.cwd(), filePath)} (${changes} changes)`);
|
||||
});
|
||||
|
||||
if (modifiedFiles.length === 0) {
|
||||
console.log(' No files needed modification.');
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
#!/usr/bin/env ts-node
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as glob from 'glob';
|
||||
|
||||
const pfapiFiles = glob.sync('src/app/pfapi/**/*.ts', {
|
||||
ignore: ['**/*.spec.ts', '**/node_modules/**'],
|
||||
});
|
||||
|
||||
console.log(`Found ${pfapiFiles.length} pfapi files to check`);
|
||||
|
||||
let totalFiles = 0;
|
||||
let totalChanges = 0;
|
||||
|
||||
function migrateFile(filePath: string): void {
|
||||
let content = fs.readFileSync(filePath, 'utf8');
|
||||
let modified = false;
|
||||
let localChanges = 0;
|
||||
|
||||
// Replace SyncLog with PFLog in code
|
||||
const syncLogPattern = /\bSyncLog\b/g;
|
||||
const matches = content.match(syncLogPattern);
|
||||
if (matches) {
|
||||
content = content.replace(syncLogPattern, 'PFLog');
|
||||
modified = true;
|
||||
localChanges = matches.length;
|
||||
}
|
||||
|
||||
// Update imports - replace SyncLog with PFLog
|
||||
if (modified) {
|
||||
// Handle imports that have both SyncLog and PFLog
|
||||
content = content.replace(
|
||||
/import\s*{\s*([^}]*)\bSyncLog\b([^}]*)\}\s*from\s*['"][^'"]*core\/log['"]/g,
|
||||
(match, before, after) => {
|
||||
const imports = (before + after)
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s && s !== 'SyncLog');
|
||||
// Only add PFLog if it's not already there
|
||||
if (!imports.includes('PFLog')) {
|
||||
imports.push('PFLog');
|
||||
}
|
||||
const importPath = match.includes('"')
|
||||
? match.split('"')[1]
|
||||
: match.split("'")[1];
|
||||
return `import { ${imports.join(', ')} } from '${importPath}'`;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
fs.writeFileSync(filePath, content);
|
||||
console.log(`✓ ${filePath} (${localChanges} changes)`);
|
||||
totalFiles++;
|
||||
totalChanges += localChanges;
|
||||
}
|
||||
}
|
||||
|
||||
// Process all files
|
||||
pfapiFiles.forEach(migrateFile);
|
||||
|
||||
console.log(
|
||||
`\nMigration complete! Modified ${totalFiles} files with ${totalChanges} total changes`,
|
||||
);
|
||||
|
|
@ -355,7 +355,6 @@ export class Log {
|
|||
// Pre-configured logger instances for specific contexts
|
||||
// All context loggers now record to history
|
||||
export const SyncLog = Log.withContext('sync');
|
||||
export const PFLog = Log.withContext('pf');
|
||||
export const OpLog = Log.withContext('ol');
|
||||
export const PluginLog = Log.withContext('plugin');
|
||||
export const IssueLog = Log.withContext('issue');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { openDB, IDBPDatabase } from 'idb';
|
||||
import { PFLog } from '../log';
|
||||
import { OpLog } from '../log';
|
||||
|
||||
// Database constants - must match PFAPI's storage
|
||||
const DB_NAME = 'pf';
|
||||
|
|
@ -49,7 +49,7 @@ export class ClientIdService {
|
|||
const isNewFormat = /^[BEAI]_[a-zA-Z0-9]{4}$/.test(clientId);
|
||||
|
||||
if (!isOldFormat && !isNewFormat) {
|
||||
PFLog.critical('ClientIdService.loadClientId() Invalid clientId loaded:', {
|
||||
OpLog.critical('ClientIdService.loadClientId() Invalid clientId loaded:', {
|
||||
clientId,
|
||||
length: clientId.length,
|
||||
});
|
||||
|
|
@ -57,7 +57,7 @@ export class ClientIdService {
|
|||
}
|
||||
|
||||
this._cachedClientId = clientId;
|
||||
PFLog.normal('ClientIdService.loadClientId() loaded:', { clientId });
|
||||
OpLog.normal('ClientIdService.loadClientId() loaded:', { clientId });
|
||||
return clientId;
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ export class ClientIdService {
|
|||
await db.put(DB_STORE_NAME, newClientId, CLIENT_ID_KEY);
|
||||
|
||||
this._cachedClientId = newClientId;
|
||||
PFLog.normal('ClientIdService.generateNewClientId() generated:', { newClientId });
|
||||
OpLog.normal('ClientIdService.generateNewClientId() generated:', { newClientId });
|
||||
return newClientId;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { PFLog } from '../log';
|
||||
import { OpLog } from '../log';
|
||||
import {
|
||||
VectorClock as SharedVectorClock,
|
||||
compareVectorClocks as sharedCompareVectorClocks,
|
||||
|
|
@ -114,7 +114,7 @@ export const sanitizeVectorClock = (clock: any): VectorClock => {
|
|||
}
|
||||
}
|
||||
} catch (e) {
|
||||
PFLog.error('Error sanitizing vector clock', e);
|
||||
OpLog.error('Error sanitizing vector clock', e);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ export const incrementVectorClock = (
|
|||
typeof clientId !== 'string' ||
|
||||
clientId.length < MIN_CLIENT_ID_LENGTH
|
||||
) {
|
||||
PFLog.critical('incrementVectorClock: Invalid clientId', {
|
||||
OpLog.critical('incrementVectorClock: Invalid clientId', {
|
||||
clientId,
|
||||
type: typeof clientId,
|
||||
length: clientId?.length,
|
||||
|
|
@ -183,7 +183,7 @@ export const incrementVectorClock = (
|
|||
const currentValue = newClock[clientId] || 0;
|
||||
|
||||
// Log for debugging
|
||||
PFLog.verbose('incrementVectorClock', {
|
||||
OpLog.verbose('incrementVectorClock', {
|
||||
clientId,
|
||||
currentValue,
|
||||
allClients: Object.keys(newClock),
|
||||
|
|
@ -193,7 +193,7 @@ export const incrementVectorClock = (
|
|||
// Resetting to 1 would break causality (new ops appear older than previous ops)
|
||||
// User must do a SYNC_IMPORT to properly reset clocks across all clients
|
||||
if (currentValue >= Number.MAX_SAFE_INTEGER - 1000) {
|
||||
PFLog.critical('Vector clock component overflow detected', {
|
||||
OpLog.critical('Vector clock component overflow detected', {
|
||||
clientId,
|
||||
currentValue,
|
||||
});
|
||||
|
|
@ -294,7 +294,7 @@ export const hasVectorClockChanges = (
|
|||
} else {
|
||||
// Current clock is small enough that pruning couldn't have removed this key.
|
||||
hasMissingUnpruned = true;
|
||||
PFLog.warn('Vector clock change detected: client missing from current', {
|
||||
OpLog.warn('Vector clock change detected: client missing from current', {
|
||||
clientId,
|
||||
refValue: refVal,
|
||||
currentClock: vectorClockToString(current),
|
||||
|
|
@ -306,7 +306,7 @@ export const hasVectorClockChanges = (
|
|||
}
|
||||
|
||||
if (missingPrunedKeys.length > 0) {
|
||||
PFLog.verbose(
|
||||
OpLog.verbose(
|
||||
`Vector clock: ${missingPrunedKeys.length} reference client(s) missing from current (likely pruned)`,
|
||||
{ missingKeys: missingPrunedKeys },
|
||||
);
|
||||
|
|
@ -358,7 +358,7 @@ export const limitVectorClockSize = (
|
|||
// This means some "protected" IDs will be dropped, which could cause
|
||||
// incorrect CONCURRENT comparisons with full-state operations.
|
||||
if (allPreserveIds.length > MAX_VECTOR_CLOCK_SIZE) {
|
||||
PFLog.warn(
|
||||
OpLog.warn(
|
||||
'Vector clock pruning: preserveClientIds exceeds MAX_VECTOR_CLOCK_SIZE, some protected IDs will be dropped',
|
||||
{
|
||||
preserveCount: allPreserveIds.length,
|
||||
|
|
@ -368,7 +368,7 @@ export const limitVectorClockSize = (
|
|||
);
|
||||
}
|
||||
|
||||
PFLog.info('Vector clock pruning triggered', {
|
||||
OpLog.info('Vector clock pruning triggered', {
|
||||
originalSize: entries.length,
|
||||
maxSize: MAX_VECTOR_CLOCK_SIZE,
|
||||
currentClientId,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Subject } from 'rxjs';
|
|||
import { App, URLOpenListenerEvent } from '@capacitor/app';
|
||||
import { PluginListenerHandle } from '@capacitor/core';
|
||||
import { IS_NATIVE_PLATFORM } from '../../util/is-native-platform';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { SyncLog } from '../../core/log';
|
||||
|
||||
export interface OAuthCallbackData {
|
||||
code?: string;
|
||||
|
|
@ -36,21 +36,21 @@ export class OAuthCallbackHandlerService implements OnDestroy {
|
|||
this._urlListenerHandle = await App.addListener(
|
||||
'appUrlOpen',
|
||||
(event: URLOpenListenerEvent) => {
|
||||
PFLog.log('OAuthCallbackHandler: Received URL', event.url);
|
||||
SyncLog.log('OAuthCallbackHandler: Received URL', event.url);
|
||||
|
||||
if (event.url.startsWith('com.super-productivity.app://oauth-callback')) {
|
||||
const callbackData = this._parseOAuthCallback(event.url);
|
||||
|
||||
if (callbackData.code) {
|
||||
PFLog.log('OAuthCallbackHandler: Extracted auth code');
|
||||
SyncLog.log('OAuthCallbackHandler: Extracted auth code');
|
||||
} else if (callbackData.error) {
|
||||
PFLog.warn(
|
||||
SyncLog.warn(
|
||||
'OAuthCallbackHandler: OAuth error',
|
||||
callbackData.error,
|
||||
callbackData.error_description,
|
||||
);
|
||||
} else {
|
||||
PFLog.warn('OAuthCallbackHandler: No auth code or error in URL', event.url);
|
||||
SyncLog.warn('OAuthCallbackHandler: No auth code or error in URL', event.url);
|
||||
}
|
||||
|
||||
this._authCodeReceived$.next(callbackData);
|
||||
|
|
@ -73,7 +73,7 @@ export class OAuthCallbackHandlerService implements OnDestroy {
|
|||
provider: 'dropbox',
|
||||
};
|
||||
} catch (e) {
|
||||
PFLog.err('OAuthCallbackHandler: Failed to parse URL', url, e);
|
||||
SyncLog.err('OAuthCallbackHandler: Failed to parse URL', url, e);
|
||||
return {
|
||||
error: 'parse_error',
|
||||
error_description: 'Failed to parse OAuth callback URL',
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { loadAllData } from '../../root-store/meta/load-all-data.action';
|
|||
import { validateFull } from '../validation/validation-fn';
|
||||
import { dataRepair } from '../validation/data-repair';
|
||||
import { isDataRepairPossible } from '../validation/is-data-repair-possible.util';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import {
|
||||
AppDataComplete,
|
||||
CROSS_MODEL_VERSION,
|
||||
|
|
@ -96,7 +96,7 @@ export class BackupService {
|
|||
|
||||
// 2. Migrate legacy backups (pre-v14) that have the old data shape
|
||||
if (isLegacyBackupData(backupData as unknown as Record<string, unknown>)) {
|
||||
PFLog.normal(
|
||||
OpLog.normal(
|
||||
'BackupService: Detected legacy backup format, running migration...',
|
||||
);
|
||||
backupData = migrateLegacyBackup(
|
||||
|
|
@ -110,7 +110,7 @@ export class BackupService {
|
|||
|
||||
if (!validationResult.isValid) {
|
||||
// Try to repair
|
||||
PFLog.normal('BackupService: Validation failed, attempting repair...', {
|
||||
OpLog.normal('BackupService: Validation failed, attempting repair...', {
|
||||
success: validationResult.typiaResult.success,
|
||||
errors:
|
||||
'errors' in validationResult.typiaResult
|
||||
|
|
@ -157,24 +157,24 @@ export class BackupService {
|
|||
importedData: AppDataComplete,
|
||||
isForceConflict: boolean,
|
||||
): Promise<void> {
|
||||
PFLog.normal('BackupService: Persisting import to operation log...');
|
||||
OpLog.normal('BackupService: Persisting import to operation log...');
|
||||
|
||||
// 1. Backup current state before clearing operations
|
||||
let backupSucceeded = true;
|
||||
try {
|
||||
const existingStateCache = await this._opLogStore.loadStateCache();
|
||||
if (existingStateCache?.state) {
|
||||
PFLog.normal('BackupService: Backing up current state before import...');
|
||||
OpLog.normal('BackupService: Backing up current state before import...');
|
||||
await this._opLogStore.saveImportBackup(existingStateCache.state);
|
||||
}
|
||||
} catch (e) {
|
||||
PFLog.warn('BackupService: Failed to backup state before import:', e);
|
||||
OpLog.warn('BackupService: Failed to backup state before import:', e);
|
||||
backupSucceeded = false;
|
||||
}
|
||||
|
||||
// 2. Clear all old operations to prevent IndexedDB bloat
|
||||
if (backupSucceeded) {
|
||||
PFLog.normal('BackupService: Clearing old operations before import...');
|
||||
OpLog.normal('BackupService: Clearing old operations before import...');
|
||||
await this._opLogStore.clearAllOperations();
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ export class BackupService {
|
|||
schemaVersion: CURRENT_SCHEMA_VERSION,
|
||||
});
|
||||
|
||||
PFLog.normal('BackupService: Import persisted to operation log.');
|
||||
OpLog.normal('BackupService: Import persisted to operation log.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import {
|
|||
initialPluginMetaDataState,
|
||||
} from '../../plugins/plugin-persistence.model';
|
||||
import { AppDataComplete } from '../model/model-config';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
|
||||
const LEGACY_INBOX_PROJECT_ID = 'INBOX' as const;
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ export const isLegacyBackupData = (data: Record<string, unknown>): boolean => {
|
|||
export const migrateLegacyBackup = (
|
||||
legacyData: Record<string, unknown>,
|
||||
): AppDataComplete => {
|
||||
PFLog.log('migrateLegacyBackup: Starting legacy backup migration');
|
||||
OpLog.log('migrateLegacyBackup: Starting legacy backup migration');
|
||||
|
||||
let data = { ...legacyData } as Record<string, any>;
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ export const migrateLegacyBackup = (
|
|||
// === Final: Strip legacy keys that are not in v17's schema ===
|
||||
data = _stripLegacyKeys(data);
|
||||
|
||||
PFLog.log('migrateLegacyBackup: Migration complete');
|
||||
OpLog.log('migrateLegacyBackup: Migration complete');
|
||||
return data as unknown as AppDataComplete;
|
||||
};
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ function _migration2ArchiveSplitAndTimeTracking(
|
|||
if (data.archiveYoung && data.archiveOld && data.timeTracking && !data.taskArchive) {
|
||||
return data;
|
||||
}
|
||||
PFLog.log('migrateLegacyBackup: Running migration 2 (archive split + time tracking)');
|
||||
OpLog.log('migrateLegacyBackup: Running migration 2 (archive split + time tracking)');
|
||||
|
||||
// Extract project time tracking data
|
||||
const projectTimeTracking: TTWorkContextSessionMap = {};
|
||||
|
|
@ -334,7 +334,7 @@ function _migrateTaskDictionary(taskDict: Dictionary<TaskCopy>): void {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
function _migration3PlannerAndInbox(data: Record<string, any>): Record<string, any> {
|
||||
PFLog.log('migrateLegacyBackup: Running migration 3 (planner + inbox)');
|
||||
OpLog.log('migrateLegacyBackup: Running migration 3 (planner + inbox)');
|
||||
|
||||
// Migrate planner days → task.dueDay
|
||||
if (data.planner?.days) {
|
||||
|
|
@ -531,7 +531,7 @@ function _migrateTasksForMigration3(
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
function _migration4TaskDateTimeFields(data: Record<string, any>): Record<string, any> {
|
||||
PFLog.log('migrateLegacyBackup: Running migration 4 (task datetime fields)');
|
||||
OpLog.log('migrateLegacyBackup: Running migration 4 (task datetime fields)');
|
||||
|
||||
if (data.improvement && !Array.isArray(data.improvement.hiddenImprovementBannerItems)) {
|
||||
data.improvement.hiddenImprovementBannerItems = [];
|
||||
|
|
@ -806,7 +806,7 @@ function _stripLegacyKeys(data: Record<string, any>): Record<string, any> {
|
|||
if (V17_VALID_KEYS.has(key)) {
|
||||
stripped[key] = data[key];
|
||||
} else {
|
||||
PFLog.log(`migrateLegacyBackup: Stripping legacy key "${key}"`);
|
||||
OpLog.log(`migrateLegacyBackup: Stripping legacy key "${key}"`);
|
||||
}
|
||||
}
|
||||
return stripped;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { IValidation } from 'typia';
|
||||
import { PFLog } from '../../../core/log';
|
||||
import { OpLog } from '../../../core/log';
|
||||
|
||||
/**
|
||||
* Extracts a meaningful error message from various error shapes.
|
||||
|
|
@ -76,13 +76,13 @@ class AdditionalLogErrorBase<T = unknown[]> extends Error {
|
|||
super(extractedMessage ?? 'Unknown error');
|
||||
|
||||
if (additional.length > 0) {
|
||||
PFLog.log(this.name, ...additional);
|
||||
OpLog.log(this.name, ...additional);
|
||||
try {
|
||||
// Sanitize before logging to avoid exposing tokens in logs
|
||||
const sanitized = additional.map(sanitizeForLogging);
|
||||
PFLog.log('additional error log: ' + JSON.stringify(sanitized));
|
||||
OpLog.log('additional error log: ' + JSON.stringify(sanitized));
|
||||
} catch (e) {
|
||||
PFLog.log('additional error log not stringified: ', additional, e);
|
||||
OpLog.log('additional error log not stringified: ', additional, e);
|
||||
}
|
||||
}
|
||||
this.additionalLog = additional as T;
|
||||
|
|
@ -376,7 +376,7 @@ export class JsonParseError extends Error {
|
|||
this.dataSample = `...${dataStr.substring(start, end)}...`;
|
||||
}
|
||||
|
||||
PFLog.err('JsonParseError:', {
|
||||
OpLog.err('JsonParseError:', {
|
||||
message: this.message,
|
||||
position: this.position,
|
||||
dataSample: this.dataSample,
|
||||
|
|
@ -441,24 +441,24 @@ export class ModelValidationError extends Error {
|
|||
e?: unknown;
|
||||
}) {
|
||||
super('ModelValidationError');
|
||||
PFLog.log(`ModelValidationError for model ${params.id}:`, params);
|
||||
OpLog.log(`ModelValidationError for model ${params.id}:`, params);
|
||||
|
||||
if (params.validationResult) {
|
||||
PFLog.log('validation result: ', params.validationResult);
|
||||
OpLog.log('validation result: ', params.validationResult);
|
||||
|
||||
try {
|
||||
if ('errors' in params.validationResult) {
|
||||
const str = JSON.stringify(params.validationResult.errors);
|
||||
PFLog.log('validation errors: ' + str);
|
||||
OpLog.log('validation errors: ' + str);
|
||||
this.additionalLog = `Model: ${params.id}, Errors: ${str.substring(0, 400)}`;
|
||||
}
|
||||
} catch (e) {
|
||||
PFLog.err('Error stringifying validation errors:', e);
|
||||
OpLog.err('Error stringifying validation errors:', e);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.e) {
|
||||
PFLog.log('Additional error:', params.e);
|
||||
OpLog.log('Additional error:', params.e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -470,17 +470,17 @@ export class DataValidationFailedError extends Error {
|
|||
constructor(validationResult: IValidation<unknown>) {
|
||||
const errorSummary = DataValidationFailedError._buildErrorSummary(validationResult);
|
||||
super(errorSummary);
|
||||
PFLog.log('validation result: ', validationResult);
|
||||
OpLog.log('validation result: ', validationResult);
|
||||
|
||||
try {
|
||||
if ('errors' in validationResult) {
|
||||
const str = JSON.stringify(validationResult.errors);
|
||||
PFLog.log('validation errors_: ' + str);
|
||||
OpLog.log('validation errors_: ' + str);
|
||||
this.additionalLog = str.substring(0, 400);
|
||||
}
|
||||
PFLog.log('validation result_: ' + JSON.stringify(validationResult));
|
||||
OpLog.log('validation result_: ' + JSON.stringify(validationResult));
|
||||
} catch (e) {
|
||||
PFLog.err('Failed to stringify validation errors:', e);
|
||||
OpLog.err('Failed to stringify validation errors:', e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import { DecompressError } from '../core/errors/sync-errors';
|
||||
import {
|
||||
compressWithGzip,
|
||||
|
|
@ -8,7 +8,7 @@ import {
|
|||
|
||||
describe('compression-handler', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(PFLog, 'err').and.stub();
|
||||
spyOn(OpLog, 'err').and.stub();
|
||||
spyOn(console, 'log').and.stub();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { CompressError, DecompressError } from '../core/errors/sync-errors';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
|
||||
/**
|
||||
* Compresses a string using gzip and returns the raw bytes.
|
||||
|
|
@ -15,7 +15,7 @@ export async function compressWithGzip(input: string): Promise<Uint8Array> {
|
|||
const compressed = await new Response(stream.readable).arrayBuffer();
|
||||
return new Uint8Array(compressed);
|
||||
} catch (error) {
|
||||
PFLog.err(error);
|
||||
OpLog.err(error);
|
||||
throw new CompressError(error);
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ export async function compressWithGzipToString(input: string): Promise<string> {
|
|||
reader.readAsDataURL(new Blob([compressed]));
|
||||
});
|
||||
} catch (error) {
|
||||
PFLog.err(error);
|
||||
OpLog.err(error);
|
||||
throw new CompressError(error);
|
||||
}
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ export async function decompressGzipFromString(
|
|||
const decoded = new TextDecoder().decode(decompressed);
|
||||
return decoded;
|
||||
} catch (error) {
|
||||
PFLog.err(error);
|
||||
OpLog.err(error);
|
||||
throw new DecompressError(error);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import { JsonParseError } from '../core/errors/sync-errors';
|
||||
import { EncryptAndCompressHandlerService } from './encrypt-and-compress-handler.service';
|
||||
import { getErrorTxt } from '../../util/get-error-text';
|
||||
|
|
@ -12,9 +12,9 @@ describe('EncryptAndCompressHandlerService', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
service = new EncryptAndCompressHandlerService();
|
||||
spyOn(PFLog, 'err').and.stub();
|
||||
spyOn(PFLog, 'normal').and.stub();
|
||||
spyOn(PFLog, 'log').and.stub();
|
||||
spyOn(OpLog, 'err').and.stub();
|
||||
spyOn(OpLog, 'normal').and.stub();
|
||||
spyOn(OpLog, 'log').and.stub();
|
||||
});
|
||||
|
||||
describe('decompressAndDecrypt', () => {
|
||||
|
|
@ -112,7 +112,7 @@ describe('EncryptAndCompressHandlerService', () => {
|
|||
|
||||
describe('JsonParseError', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(PFLog, 'err').and.stub();
|
||||
spyOn(OpLog, 'err').and.stub();
|
||||
});
|
||||
|
||||
it('should extract position from SyntaxError message', () => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import {
|
|||
extractSyncFileStateFromPrefix,
|
||||
getSyncFilePrefix,
|
||||
} from '../util/sync-file-prefix';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import {
|
||||
deriveKeyFromPassword,
|
||||
encryptWithDerivedKey,
|
||||
|
|
@ -72,7 +72,7 @@ export class EncryptAndCompressHandlerService {
|
|||
isEncrypt,
|
||||
modelVersion,
|
||||
});
|
||||
PFLog.normal(
|
||||
OpLog.normal(
|
||||
`${EncryptAndCompressHandlerService.L}.${this.compressAndEncrypt.name}()`,
|
||||
{
|
||||
prefix,
|
||||
|
|
@ -110,7 +110,7 @@ export class EncryptAndCompressHandlerService {
|
|||
}> {
|
||||
const { isCompressed, isEncrypted, modelVersion, cleanDataStr } =
|
||||
extractSyncFileStateFromPrefix(dataStr);
|
||||
PFLog.normal(
|
||||
OpLog.normal(
|
||||
`${EncryptAndCompressHandlerService.L}.${this.decompressAndDecrypt.name}()`,
|
||||
{ isCompressed, isEncrypted, modelVersion },
|
||||
);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ import { initialTimeTrackingState } from '../../features/time-tracking/store/tim
|
|||
import { appDataValidators, validateFull } from '../validation/validation-fn';
|
||||
import { fixEntityStateConsistency } from '../../util/check-fix-entity-state-consistency';
|
||||
import { IValidation } from 'typia';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import { alertDialog } from '../../util/native-dialogs';
|
||||
import {
|
||||
initialPluginMetaDataState,
|
||||
|
|
@ -237,7 +237,7 @@ export const SYNC_CONFIG: BaseSyncConfig<AllModelConfig> = {
|
|||
const result = validateFull(data);
|
||||
|
||||
if (!environment.production && !result.isValid) {
|
||||
PFLog.log(result);
|
||||
OpLog.log(result);
|
||||
alertDialog('VALIDATION ERROR');
|
||||
}
|
||||
|
||||
|
|
@ -262,7 +262,7 @@ export const SYNC_CONFIG: BaseSyncConfig<AllModelConfig> = {
|
|||
return result.typiaResult;
|
||||
},
|
||||
onDbError: (err) => {
|
||||
PFLog.err(err);
|
||||
OpLog.err(err);
|
||||
alertDialog('DB ERROR: ' + err);
|
||||
},
|
||||
repair: (data: unknown, errors: IValidation.IError[]) => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { DBSchema, IDBPDatabase, openDB } from 'idb';
|
||||
import { SyncProviderId, PRIVATE_CFG_PREFIX } from './provider.const';
|
||||
import { PrivateCfgByProviderId } from '../core/types/sync.types';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { SyncLog } from '../../core/log';
|
||||
|
||||
/**
|
||||
* New database configuration for sync credentials.
|
||||
|
|
@ -78,7 +78,7 @@ export class SyncCredentialStore<PID extends SyncProviderId> {
|
|||
* Automatically migrates from legacy database if needed.
|
||||
*/
|
||||
async load(): Promise<PrivateCfgByProviderId<PID> | null> {
|
||||
PFLog.verbose(
|
||||
SyncLog.verbose(
|
||||
`${SyncCredentialStore.L}.${this.load.name}`,
|
||||
this._providerId,
|
||||
typeof this._privateCfgInMemory,
|
||||
|
|
@ -109,7 +109,7 @@ export class SyncCredentialStore<PID extends SyncProviderId> {
|
|||
|
||||
return loadedConfig ?? null;
|
||||
} catch (error) {
|
||||
PFLog.critical(`Failed to load credentials: ${error}`);
|
||||
SyncLog.critical(`Failed to load credentials: ${error}`);
|
||||
throw new Error(`Failed to load credentials: ${error}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ export class SyncCredentialStore<PID extends SyncProviderId> {
|
|||
* Clears the provider's credentials.
|
||||
*/
|
||||
async clear(): Promise<void> {
|
||||
PFLog.normal(`${SyncCredentialStore.L}.clear()`, this._providerId);
|
||||
SyncLog.normal(`${SyncCredentialStore.L}.clear()`, this._providerId);
|
||||
|
||||
this._privateCfgInMemory = undefined;
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ export class SyncCredentialStore<PID extends SyncProviderId> {
|
|||
const db = await this._ensureDb();
|
||||
await db.delete(DB_STORE_NAME, this._dbKey);
|
||||
} catch (error) {
|
||||
PFLog.critical(`Failed to clear credentials: ${error}`);
|
||||
SyncLog.critical(`Failed to clear credentials: ${error}`);
|
||||
throw new Error(`Failed to clear credentials: ${error}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -181,17 +181,17 @@ export class SyncCredentialStore<PID extends SyncProviderId> {
|
|||
// Create the credentials store if it doesn't exist
|
||||
if (!database.objectStoreNames.contains(DB_STORE_NAME)) {
|
||||
database.createObjectStore(DB_STORE_NAME);
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`[${SyncCredentialStore.L}] Created ${DB_STORE_NAME} object store`,
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
PFLog.verbose(
|
||||
SyncLog.verbose(
|
||||
`[${SyncCredentialStore.L}] Database connection initialized for ${this._providerId}`,
|
||||
);
|
||||
} catch (e) {
|
||||
PFLog.err(`[${SyncCredentialStore.L}] Failed to initialize database`, e);
|
||||
SyncLog.err(`[${SyncCredentialStore.L}] Failed to initialize database`, e);
|
||||
this._initPromise = undefined; // Allow retry
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -239,7 +239,7 @@ export class SyncCredentialStore<PID extends SyncProviderId> {
|
|||
legacyDb.close();
|
||||
|
||||
if (legacyConfig) {
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`[${SyncCredentialStore.L}] Migrating credentials for ${this._providerId} from legacy database`,
|
||||
);
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ export class SyncCredentialStore<PID extends SyncProviderId> {
|
|||
|
||||
return null;
|
||||
} catch (error) {
|
||||
PFLog.warn(
|
||||
SyncLog.warn(
|
||||
`[${SyncCredentialStore.L}] Failed to migrate from legacy database (this is ok for new installs): ${error}`,
|
||||
);
|
||||
return null;
|
||||
|
|
@ -266,7 +266,7 @@ export class SyncCredentialStore<PID extends SyncProviderId> {
|
|||
const encryptKeyInfo = cfgWithRedacted?.encryptKey
|
||||
? `[length=${cfgWithRedacted.encryptKey.length}]`
|
||||
: '[not set]';
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`${SyncCredentialStore.L}._save()`,
|
||||
this._providerId,
|
||||
`encryptKey=${encryptKeyInfo}`,
|
||||
|
|
@ -286,13 +286,13 @@ export class SyncCredentialStore<PID extends SyncProviderId> {
|
|||
try {
|
||||
const db = await this._ensureDb();
|
||||
await db.put(DB_STORE_NAME, privateCfg, this._dbKey);
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`${SyncCredentialStore.L}._save() SUCCESS`,
|
||||
this._providerId,
|
||||
`wrote to ${DB_STORE_NAME}/${this._dbKey}`,
|
||||
);
|
||||
} catch (error) {
|
||||
PFLog.critical(`Failed to save credentials: ${error}`);
|
||||
SyncLog.critical(`Failed to save credentials: ${error}`);
|
||||
throw new Error(`Failed to save credentials: ${error}`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
TooManyRequestsAPIError,
|
||||
UploadRevToMatchMismatchAPIError,
|
||||
} from '../../../core/errors/sync-errors';
|
||||
import { PFLog } from '../../../../core/log';
|
||||
import { SyncLog } from '../../../../core/log';
|
||||
import { SyncProviderServiceInterface } from '../../provider.interface';
|
||||
import { SyncProviderId } from '../../provider.const';
|
||||
import { tryCatchInlineAsync } from '../../../../util/try-catch-inline';
|
||||
|
|
@ -100,7 +100,7 @@ export class DropboxApi {
|
|||
* List folder contents
|
||||
*/
|
||||
async listFiles(path: string): Promise<string[]> {
|
||||
PFLog.normal(`${DropboxApi.L}.listFiles() for path: ${path}`);
|
||||
SyncLog.normal(`${DropboxApi.L}.listFiles() for path: ${path}`);
|
||||
try {
|
||||
const response = await this._request({
|
||||
method: 'POST',
|
||||
|
|
@ -116,7 +116,7 @@ export class DropboxApi {
|
|||
.filter((entry) => entry['.tag'] === 'file') // Only return files
|
||||
.map((entry) => entry.path_lower); // Return full path in lower case
|
||||
} catch (e) {
|
||||
PFLog.critical(`${DropboxApi.L}.listFiles() error for path: ${path}`, e);
|
||||
SyncLog.critical(`${DropboxApi.L}.listFiles() error for path: ${path}`, e);
|
||||
this._checkCommonErrors(e, path);
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -140,7 +140,7 @@ export class DropboxApi {
|
|||
});
|
||||
return response.json();
|
||||
} catch (e) {
|
||||
PFLog.critical(`${DropboxApi.L}.getMetaData() error for path: ${path}`, e);
|
||||
SyncLog.critical(`${DropboxApi.L}.getMetaData() error for path: ${path}`, e);
|
||||
this._checkCommonErrors(e, path);
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -183,7 +183,7 @@ export class DropboxApi {
|
|||
|
||||
return { meta, data: data as unknown as T };
|
||||
} catch (e) {
|
||||
PFLog.critical(`${DropboxApi.L}.download() error for path: ${path}`, e);
|
||||
SyncLog.critical(`${DropboxApi.L}.download() error for path: ${path}`, e);
|
||||
this._checkCommonErrors(e, path);
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -236,7 +236,7 @@ export class DropboxApi {
|
|||
|
||||
return result;
|
||||
} catch (e) {
|
||||
PFLog.critical(`${DropboxApi.L}.upload() error for path: ${path}`, e);
|
||||
SyncLog.critical(`${DropboxApi.L}.upload() error for path: ${path}`, e);
|
||||
this._checkCommonErrors(e, path);
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -255,7 +255,7 @@ export class DropboxApi {
|
|||
});
|
||||
return response.json();
|
||||
} catch (e) {
|
||||
PFLog.critical(`${DropboxApi.L}.remove() error for path: ${path}`, e);
|
||||
SyncLog.critical(`${DropboxApi.L}.remove() error for path: ${path}`, e);
|
||||
this._checkCommonErrors(e, path);
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -278,7 +278,7 @@ export class DropboxApi {
|
|||
});
|
||||
return response.json();
|
||||
} catch (e) {
|
||||
PFLog.critical(`${DropboxApi.L}.checkUser() error`, e);
|
||||
SyncLog.critical(`${DropboxApi.L}.checkUser() error`, e);
|
||||
this._checkCommonErrors(e, 'check/user');
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -288,13 +288,13 @@ export class DropboxApi {
|
|||
* Refresh access token using refresh token
|
||||
*/
|
||||
async updateAccessTokenFromRefreshTokenIfAvailable(): Promise<void> {
|
||||
PFLog.normal(`${DropboxApi.L}.updateAccessTokenFromRefreshTokenIfAvailable()`);
|
||||
SyncLog.normal(`${DropboxApi.L}.updateAccessTokenFromRefreshTokenIfAvailable()`);
|
||||
|
||||
const privateCfg = await this._parent.privateCfg.load();
|
||||
const refreshToken = privateCfg?.refreshToken;
|
||||
|
||||
if (!refreshToken) {
|
||||
PFLog.critical('Dropbox: No refresh token available');
|
||||
SyncLog.critical('Dropbox: No refresh token available');
|
||||
await this._clearTokensIfPresent(privateCfg);
|
||||
throw new MissingRefreshTokenAPIError();
|
||||
}
|
||||
|
|
@ -362,14 +362,14 @@ export class DropboxApi {
|
|||
data = (await response.json()) as TokenResponse;
|
||||
}
|
||||
|
||||
PFLog.normal('Dropbox: Refresh access token Response', data);
|
||||
SyncLog.normal('Dropbox: Refresh access token Response', data);
|
||||
|
||||
await this._parent.privateCfg.updatePartial({
|
||||
accessToken: data.access_token,
|
||||
refreshToken: data.refresh_token || privateCfg?.refreshToken,
|
||||
});
|
||||
} catch (e) {
|
||||
PFLog.critical('Failed to refresh Dropbox access token', e);
|
||||
SyncLog.critical('Failed to refresh Dropbox access token', e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
@ -470,7 +470,7 @@ export class DropboxApi {
|
|||
expiresAt: +data.expires_in * 1000 + Date.now(),
|
||||
};
|
||||
} catch (e) {
|
||||
PFLog.critical(`${DropboxApi.L}.getTokensFromAuthCode() error`, e);
|
||||
SyncLog.critical(`${DropboxApi.L}.getTokensFromAuthCode() error`, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
@ -530,7 +530,7 @@ export class DropboxApi {
|
|||
}
|
||||
|
||||
try {
|
||||
PFLog.log(`${DropboxApi.L}._requestNative() ${method} ${requestUrl}`);
|
||||
SyncLog.log(`${DropboxApi.L}._requestNative() ${method} ${requestUrl}`);
|
||||
|
||||
const capacitorResponse = await CapacitorHttp.request({
|
||||
url: requestUrl,
|
||||
|
|
@ -570,7 +570,7 @@ export class DropboxApi {
|
|||
|
||||
return response;
|
||||
} catch (e) {
|
||||
PFLog.critical(`${DropboxApi.L}._requestNative() error for ${url}`, e);
|
||||
SyncLog.critical(`${DropboxApi.L}._requestNative() error for ${url}`, e);
|
||||
this._checkCommonErrors(e, url);
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -693,7 +693,7 @@ export class DropboxApi {
|
|||
|
||||
return response;
|
||||
} catch (e) {
|
||||
PFLog.critical(`${DropboxApi.L}._request() error for ${url}`, e);
|
||||
SyncLog.critical(`${DropboxApi.L}._request() error for ${url}`, e);
|
||||
this._checkCommonErrors(e, url);
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -773,7 +773,7 @@ export class DropboxApi {
|
|||
return new Promise((resolve, reject) => {
|
||||
setTimeout(
|
||||
() => {
|
||||
PFLog.normal(`Too many requests ${path}, retrying in ${retryAfter}s...`);
|
||||
SyncLog.normal(`Too many requests ${path}, retrying in ${retryAfter}s...`);
|
||||
originalRequestExecutor()
|
||||
.then(resolve as (value: unknown) => void)
|
||||
.catch(reject);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
RemoteFileNotFoundAPIError,
|
||||
NoRevAPIError,
|
||||
} from '../../../core/errors/sync-errors';
|
||||
import { PFLog } from '../../../../core/log';
|
||||
import { SyncLog } from '../../../../core/log';
|
||||
import { DropboxApi } from './dropbox-api';
|
||||
import { generatePKCECodes } from './generate-pkce-codes';
|
||||
import { SyncCredentialStore } from '../../credential-store.service';
|
||||
|
|
@ -87,7 +87,7 @@ export class Dropbox implements SyncProviderServiceInterface<SyncProviderId.Drop
|
|||
};
|
||||
} catch (e) {
|
||||
if (this._isTokenError(e)) {
|
||||
PFLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
SyncLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
await this._api.updateAccessTokenFromRefreshTokenIfAvailable();
|
||||
return this.getFileRev(targetPath, localRev);
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ export class Dropbox implements SyncProviderServiceInterface<SyncProviderId.Drop
|
|||
}
|
||||
|
||||
if (typeof r.data !== 'string') {
|
||||
PFLog.critical(`${Dropbox.L}.${this.downloadFile.name}() data`, r.data);
|
||||
SyncLog.critical(`${Dropbox.L}.${this.downloadFile.name}() data`, r.data);
|
||||
throw new InvalidDataSPError(r.data);
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ export class Dropbox implements SyncProviderServiceInterface<SyncProviderId.Drop
|
|||
};
|
||||
} catch (e) {
|
||||
if (this._isTokenError(e)) {
|
||||
PFLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
SyncLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
await this._api.updateAccessTokenFromRefreshTokenIfAvailable();
|
||||
return this.downloadFile(targetPath);
|
||||
}
|
||||
|
|
@ -168,7 +168,7 @@ export class Dropbox implements SyncProviderServiceInterface<SyncProviderId.Drop
|
|||
try {
|
||||
const current = await this.getFileRev(targetPath, '');
|
||||
effectiveRev = current.rev;
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`${Dropbox.L}.${this.uploadFile.name}() got current rev for conditional upload: ${effectiveRev}`,
|
||||
);
|
||||
} catch (e) {
|
||||
|
|
@ -176,7 +176,7 @@ export class Dropbox implements SyncProviderServiceInterface<SyncProviderId.Drop
|
|||
throw e;
|
||||
}
|
||||
// File doesn't exist - proceed without rev (will create new)
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`${Dropbox.L}.${this.uploadFile.name}() file does not exist, will create new`,
|
||||
);
|
||||
}
|
||||
|
|
@ -199,7 +199,7 @@ export class Dropbox implements SyncProviderServiceInterface<SyncProviderId.Drop
|
|||
};
|
||||
} catch (e) {
|
||||
if (this._isTokenError(e)) {
|
||||
PFLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
SyncLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
await this._api.updateAccessTokenFromRefreshTokenIfAvailable();
|
||||
return this.uploadFile(targetPath, dataStr, revToMatch, isForceOverwrite);
|
||||
}
|
||||
|
|
@ -218,7 +218,7 @@ export class Dropbox implements SyncProviderServiceInterface<SyncProviderId.Drop
|
|||
await this._api.remove(this._getPath(targetPath));
|
||||
} catch (e) {
|
||||
if (this._isTokenError(e)) {
|
||||
PFLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
SyncLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
await this._api.updateAccessTokenFromRefreshTokenIfAvailable();
|
||||
return this.removeFile(targetPath);
|
||||
}
|
||||
|
|
@ -236,13 +236,13 @@ export class Dropbox implements SyncProviderServiceInterface<SyncProviderId.Drop
|
|||
}
|
||||
|
||||
async listFiles(dirPath: string): Promise<string[]> {
|
||||
PFLog.normal(`${Dropbox.L}.${this.listFiles.name}()`, { dirPath });
|
||||
SyncLog.normal(`${Dropbox.L}.${this.listFiles.name}()`, { dirPath });
|
||||
try {
|
||||
// DropboxApi.listFiles now returns full paths, so no need to prepend _getPath
|
||||
return await this._api.listFiles(this._getPath(dirPath));
|
||||
} catch (e) {
|
||||
if (this._isTokenError(e)) {
|
||||
PFLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
SyncLog.critical('EXPIRED or INVALID TOKEN, trying to refresh');
|
||||
await this._api.updateAccessTokenFromRefreshTokenIfAvailable();
|
||||
return this.listFiles(dirPath);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ describe('SafFileAdapter', () => {
|
|||
await adapter.deleteFile('missing.json');
|
||||
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'[pf]',
|
||||
'[sync]',
|
||||
'File not found for deletion: missing.json',
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { FileAdapter } from '../file-adapter.interface';
|
||||
import { SafService } from './saf.service';
|
||||
import { PFLog } from '../../../../../core/log';
|
||||
import { SyncLog } from '../../../../../core/log';
|
||||
|
||||
export class SafFileAdapter implements FileAdapter {
|
||||
constructor(private getUri: () => Promise<string | undefined>) {}
|
||||
|
|
@ -38,7 +38,7 @@ export class SafFileAdapter implements FileAdapter {
|
|||
} catch (error) {
|
||||
// Ignore file not found errors
|
||||
if (error?.toString?.().includes('File not found')) {
|
||||
PFLog.err(`File not found for deletion: ${filePath}`);
|
||||
SyncLog.err(`File not found for deletion: ${filePath}`);
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
|
|
@ -53,7 +53,7 @@ export class SafFileAdapter implements FileAdapter {
|
|||
|
||||
// TODO: implement for operation log sync
|
||||
async listFiles?(dirPath: string): Promise<string[]> {
|
||||
PFLog.warn('SafFileAdapter: listFiles is not yet implemented for Android SAF.');
|
||||
SyncLog.warn('SafFileAdapter: listFiles is not yet implemented for Android SAF.');
|
||||
throw new Error('SafFileAdapter: listFiles is not yet implemented.');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable */
|
||||
import { Capacitor, registerPlugin } from '@capacitor/core';
|
||||
import { PFLog } from '../../../../../core/log';
|
||||
import { SyncLog } from '../../../../../core/log';
|
||||
|
||||
// Define the plugin interface for SAF operations
|
||||
export interface SafPlugin {
|
||||
|
|
@ -71,7 +71,7 @@ export class SafService {
|
|||
const result = await SafBridge.checkUriPermission({ uri });
|
||||
return result.hasPermission;
|
||||
} catch (error) {
|
||||
PFLog.err('Error checking SAF permission:', error);
|
||||
SyncLog.err('Error checking SAF permission:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -110,7 +110,7 @@ export class SafService {
|
|||
const result = await SafBridge.checkFileExists({ uri, fileName });
|
||||
return result.exists;
|
||||
} catch (error) {
|
||||
PFLog.err('Error checking file existence:', error);
|
||||
SyncLog.err('Error checking file existence:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ export class ElectronFileAdapter implements FileAdapter {
|
|||
// }
|
||||
// return result;
|
||||
// } catch (e) {
|
||||
// PFLog.critical( `ElectronFileAdapter.checkDirExists() error`, e);
|
||||
// SyncLog.critical( `ElectronFileAdapter.checkDirExists() error`, e);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
|
@ -69,7 +69,7 @@ export class ElectronFileAdapter implements FileAdapter {
|
|||
// try {
|
||||
// return await this.ea.pickDirectory();
|
||||
// } catch (e) {
|
||||
// PFLog.critical( `ElectronFileAdapter.pickDirectory() error`, e);
|
||||
// SyncLog.critical( `ElectronFileAdapter.pickDirectory() error`, e);
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { LocalFileSyncBase } from './local-file-sync-base';
|
|||
import { LocalFileSyncPrivateCfg } from '../../../core/types/sync.types';
|
||||
import { SafService } from './droid-saf/saf.service';
|
||||
import { SafFileAdapter } from './droid-saf/saf-file-adapter';
|
||||
import { PFLog } from '../../../../core/log';
|
||||
import { SyncLog } from '../../../../core/log';
|
||||
|
||||
export class LocalFileSyncAndroid extends LocalFileSyncBase {
|
||||
constructor(public directory = Directory.Documents) {
|
||||
|
|
@ -38,7 +38,7 @@ export class LocalFileSyncAndroid extends LocalFileSyncBase {
|
|||
});
|
||||
return uri;
|
||||
} catch (error) {
|
||||
PFLog.err('Failed to setup SAF:', error);
|
||||
SyncLog.err('Failed to setup SAF:', error);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
WebCryptoNotAvailableError,
|
||||
} from '../../../core/errors/sync-errors';
|
||||
import { md5HashPromise } from '../../../../util/md5-hash';
|
||||
import { PFLog } from '../../../../core/log';
|
||||
import { SyncLog } from '../../../../core/log';
|
||||
import { PrivateCfgByProviderId } from '../../../core/types/sync.types';
|
||||
|
||||
export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<SyncProviderId.LocalFile> {
|
||||
|
|
@ -36,7 +36,7 @@ export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<
|
|||
protected abstract getFilePath(targetPath: string): Promise<string>;
|
||||
|
||||
async listFiles(dirPath: string): Promise<string[]> {
|
||||
PFLog.normal(`${LocalFileSyncBase.LB}.${this.listFiles.name}()`, { dirPath });
|
||||
SyncLog.normal(`${LocalFileSyncBase.LB}.${this.listFiles.name}()`, { dirPath });
|
||||
if (!this.fileAdapter.listFiles) {
|
||||
throw new Error('FileAdapter does not support listFiles');
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<
|
|||
}
|
||||
|
||||
async getFileRev(targetPath: string, localRev: string): Promise<{ rev: string }> {
|
||||
PFLog.normal(`${LocalFileSyncBase.LB}.${this.getFileRev.name}`, {
|
||||
SyncLog.normal(`${LocalFileSyncBase.LB}.${this.getFileRev.name}`, {
|
||||
targetPath,
|
||||
localRev,
|
||||
});
|
||||
|
|
@ -54,13 +54,13 @@ export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<
|
|||
const r = await this.downloadFile(targetPath);
|
||||
return { rev: r.rev };
|
||||
} catch (e) {
|
||||
PFLog.critical(`${LocalFileSyncBase.LB}.${this.getFileRev.name} error`, e);
|
||||
SyncLog.critical(`${LocalFileSyncBase.LB}.${this.getFileRev.name} error`, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async downloadFile(targetPath: string): Promise<{ rev: string; dataStr: string }> {
|
||||
PFLog.normal(`${LocalFileSyncBase.LB}.${this.downloadFile.name}()`, {
|
||||
SyncLog.normal(`${LocalFileSyncBase.LB}.${this.downloadFile.name}()`, {
|
||||
targetPath,
|
||||
});
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<
|
|||
throw new RemoteFileNotFoundAPIError(targetPath);
|
||||
}
|
||||
|
||||
PFLog.critical(`${LocalFileSyncBase.LB}.${this.downloadFile.name}() error`, e);
|
||||
SyncLog.critical(`${LocalFileSyncBase.LB}.${this.downloadFile.name}() error`, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
@ -101,7 +101,7 @@ export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<
|
|||
revToMatch: string | null,
|
||||
isForceOverwrite: boolean = false,
|
||||
): Promise<{ rev: string }> {
|
||||
PFLog.normal(`${LocalFileSyncBase.LB}.${this.uploadFile.name}()`, {
|
||||
SyncLog.normal(`${LocalFileSyncBase.LB}.${this.uploadFile.name}()`, {
|
||||
targetPath,
|
||||
dataLength: dataStr?.length,
|
||||
revToMatch,
|
||||
|
|
@ -114,7 +114,7 @@ export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<
|
|||
try {
|
||||
const existingFile = await this.downloadFile(targetPath);
|
||||
if (existingFile.rev !== revToMatch) {
|
||||
PFLog.critical(
|
||||
SyncLog.critical(
|
||||
`${LocalFileSyncBase.LB}.${this.uploadFile.name}() rev mismatch`,
|
||||
existingFile.rev,
|
||||
revToMatch,
|
||||
|
|
@ -135,13 +135,13 @@ export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<
|
|||
const newRev = await this._getLocalRev(dataStr);
|
||||
return { rev: newRev };
|
||||
} catch (e) {
|
||||
PFLog.critical(`${LocalFileSyncBase.LB}.${this.uploadFile.name}() error`, e);
|
||||
SyncLog.critical(`${LocalFileSyncBase.LB}.${this.uploadFile.name}() error`, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async removeFile(targetPath: string): Promise<void> {
|
||||
PFLog.normal(`${LocalFileSyncBase.LB}.${this.removeFile.name}`, { targetPath });
|
||||
SyncLog.normal(`${LocalFileSyncBase.LB}.${this.removeFile.name}`, { targetPath });
|
||||
try {
|
||||
const filePath = await this.getFilePath(targetPath);
|
||||
await this.fileAdapter.deleteFile(filePath);
|
||||
|
|
@ -152,7 +152,7 @@ export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<
|
|||
e?.toString?.().includes('File does not exist') ||
|
||||
e?.toString?.().includes('ENOENT')
|
||||
) {
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`${LocalFileSyncBase.LB}.${this.removeFile.name} - file doesn't exist`,
|
||||
{
|
||||
targetPath,
|
||||
|
|
@ -161,7 +161,7 @@ export abstract class LocalFileSyncBase implements SyncProviderServiceInterface<
|
|||
return;
|
||||
}
|
||||
|
||||
PFLog.critical(`${LocalFileSyncBase.LB}.${this.removeFile.name} error`, e);
|
||||
SyncLog.critical(`${LocalFileSyncBase.LB}.${this.removeFile.name} error`, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { LocalFileSyncBase } from './local-file-sync-base';
|
||||
import { IS_ELECTRON } from '../../../../app.constants';
|
||||
import { PFLog } from '../../../../core/log';
|
||||
import { SyncLog } from '../../../../core/log';
|
||||
import { ElectronFileAdapter } from './electron-file-adapter';
|
||||
import { LocalFileSyncPrivateCfg } from '../../../core/types/sync.types';
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ export class LocalFileSyncElectron extends LocalFileSyncBase {
|
|||
}
|
||||
|
||||
private async _checkDirAndOpenPickerIfNotExists(): Promise<void> {
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`${LocalFileSyncElectron.L}.${this._checkDirAndOpenPickerIfNotExists.name}`,
|
||||
);
|
||||
|
||||
|
|
@ -42,11 +42,13 @@ export class LocalFileSyncElectron extends LocalFileSyncBase {
|
|||
const isDirExists = await this._checkDirExists(folderPath);
|
||||
|
||||
if (!isDirExists) {
|
||||
PFLog.critical(`${LocalFileSyncElectron.L} - No valid directory, opening picker`);
|
||||
SyncLog.critical(
|
||||
`${LocalFileSyncElectron.L} - No valid directory, opening picker`,
|
||||
);
|
||||
await this.pickDirectory();
|
||||
}
|
||||
} catch (err) {
|
||||
PFLog.error(
|
||||
SyncLog.error(
|
||||
`${LocalFileSyncElectron.L}.${this._checkDirAndOpenPickerIfNotExists.name}() error`,
|
||||
err,
|
||||
);
|
||||
|
|
@ -73,7 +75,7 @@ export class LocalFileSyncElectron extends LocalFileSyncBase {
|
|||
}
|
||||
return r;
|
||||
} catch (e) {
|
||||
PFLog.critical(
|
||||
SyncLog.critical(
|
||||
`${LocalFileSyncElectron.L}.${this._checkDirExists.name}() error`,
|
||||
e,
|
||||
);
|
||||
|
|
@ -82,7 +84,7 @@ export class LocalFileSyncElectron extends LocalFileSyncBase {
|
|||
}
|
||||
|
||||
async pickDirectory(): Promise<string | void> {
|
||||
PFLog.normal(`${LocalFileSyncElectron.L}.pickDirectory()`);
|
||||
SyncLog.normal(`${LocalFileSyncElectron.L}.pickDirectory()`);
|
||||
|
||||
try {
|
||||
const dir = await (window as any).ea.pickDirectory();
|
||||
|
|
@ -91,7 +93,7 @@ export class LocalFileSyncElectron extends LocalFileSyncBase {
|
|||
}
|
||||
return dir;
|
||||
} catch (e) {
|
||||
PFLog.critical(`${LocalFileSyncElectron.L}.pickDirectory() error`, e);
|
||||
SyncLog.critical(`${LocalFileSyncElectron.L}.pickDirectory() error`, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { WebdavPrivateCfg } from './webdav.model';
|
||||
import { Log, PFLog } from '../../../../core/log';
|
||||
import { Log, SyncLog } from '../../../../core/log';
|
||||
import { FileMeta, WebdavXmlParser } from './webdav-xml-parser';
|
||||
import { WebDavHttpAdapter, WebDavHttpResponse } from './webdav-http-adapter';
|
||||
import {
|
||||
|
|
@ -63,7 +63,7 @@ export class WebdavApi {
|
|||
});
|
||||
throw new HttpNotOkAPIError(errorResponse); // Other errors
|
||||
} catch (e) {
|
||||
PFLog.error(`${WebdavApi.L}.listFiles() error for path: ${dirPath}`, e);
|
||||
SyncLog.error(`${WebdavApi.L}.listFiles() error for path: ${dirPath}`, e);
|
||||
// Handle "Not Found" error specifically to return empty array
|
||||
if (
|
||||
e instanceof HttpNotOkAPIError &&
|
||||
|
|
@ -102,7 +102,7 @@ export class WebdavApi {
|
|||
const files = this.xmlParser.parseMultiplePropsFromXml(response.data, path);
|
||||
if (files && files.length > 0) {
|
||||
const meta = files[0];
|
||||
PFLog.verbose(`${WebdavApi.L}.getFileMeta() PROPFIND success for ${path}`, {
|
||||
SyncLog.verbose(`${WebdavApi.L}.getFileMeta() PROPFIND success for ${path}`, {
|
||||
lastmod: meta.lastmod,
|
||||
});
|
||||
return meta;
|
||||
|
|
@ -111,14 +111,14 @@ export class WebdavApi {
|
|||
} catch (e) {
|
||||
// If PROPFIND fails and fallback is enabled, try HEAD
|
||||
if (useGetFallback) {
|
||||
PFLog.verbose(
|
||||
SyncLog.verbose(
|
||||
`${WebdavApi.L}.getFileMeta() PROPFIND failed, trying HEAD fallback`,
|
||||
e,
|
||||
);
|
||||
try {
|
||||
return await this._getFileMetaViaHead(fullPath);
|
||||
} catch (headErr) {
|
||||
PFLog.warn(
|
||||
SyncLog.warn(
|
||||
`${WebdavApi.L}.getFileMeta() HEAD fallback failed for ${path}`,
|
||||
headErr,
|
||||
);
|
||||
|
|
@ -126,7 +126,7 @@ export class WebdavApi {
|
|||
// Usually the original PROPFIND error is more informative about connectivity
|
||||
}
|
||||
}
|
||||
PFLog.error(`${WebdavApi.L}.getFileMeta() error`, { path, error: e });
|
||||
SyncLog.error(`${WebdavApi.L}.getFileMeta() error`, { path, error: e });
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +183,7 @@ export class WebdavApi {
|
|||
|
||||
// Fallback: Some servers may omit Last-Modified on GET, so request metadata separately
|
||||
if (isLastModifiedMissing) {
|
||||
PFLog.verbose(
|
||||
SyncLog.verbose(
|
||||
`${WebdavApi.L}.download() missing Last-Modified header, trying metadata fallback for ${path}`,
|
||||
);
|
||||
try {
|
||||
|
|
@ -199,20 +199,23 @@ export class WebdavApi {
|
|||
}
|
||||
}
|
||||
} catch (e) {
|
||||
PFLog.warn(`${WebdavApi.L}.download() metadata fallback failed for ${path}`, e);
|
||||
SyncLog.warn(
|
||||
`${WebdavApi.L}.download() metadata fallback failed for ${path}`,
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to ETag if Last-Modified is still not available
|
||||
if (!rev && legacyRev) {
|
||||
rev = legacyRev;
|
||||
PFLog.warn(
|
||||
SyncLog.warn(
|
||||
`${WebdavApi.L}.download() no Last-Modified for ${path}, using ETag as revision.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!rev) {
|
||||
PFLog.err(
|
||||
SyncLog.err(
|
||||
`${WebdavApi.L}.download() no revision markers (Last-Modified or ETag) found for ${path}. ` +
|
||||
`Check your WebDAV server or reverse proxy configuration.`,
|
||||
);
|
||||
|
|
@ -226,7 +229,7 @@ export class WebdavApi {
|
|||
lastModified,
|
||||
};
|
||||
} catch (e) {
|
||||
PFLog.error(`${WebdavApi.L}.download() error`, { path, error: e });
|
||||
SyncLog.error(`${WebdavApi.L}.download() error`, { path, error: e });
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
@ -308,7 +311,7 @@ export class WebdavApi {
|
|||
// If we get a 409 Conflict, it might be because parent directory doesn't exist
|
||||
uploadError.response.status === WebDavHttpStatus.CONFLICT)
|
||||
) {
|
||||
PFLog.debug(
|
||||
SyncLog.debug(
|
||||
`${WebdavApi.L}.upload() got 409 Conflict for ${fullPath}. ` +
|
||||
`This often indicates the sync folder path is misconfigured. ` +
|
||||
`Attempting to create parent directory...`,
|
||||
|
|
@ -332,7 +335,7 @@ export class WebdavApi {
|
|||
retryError.response &&
|
||||
retryError.response.status === WebDavHttpStatus.CONFLICT
|
||||
) {
|
||||
PFLog.err(
|
||||
SyncLog.err(
|
||||
`${WebdavApi.L}.upload() 409 Conflict persists for ${fullPath} after creating parent directory. ` +
|
||||
`Verify your syncFolderPath is relative to the WebDAV server root, ` +
|
||||
`not your server's internal directory path.`,
|
||||
|
|
@ -358,7 +361,7 @@ export class WebdavApi {
|
|||
if (!rev) {
|
||||
// Some WebDAV servers don't return Last-Modified on PUT
|
||||
// Try to get it from a HEAD request first (cheaper than PROPFIND)
|
||||
PFLog.verbose(
|
||||
SyncLog.verbose(
|
||||
`${WebdavApi.L}.upload() no Last-Modified in PUT response, fetching via HEAD`,
|
||||
);
|
||||
try {
|
||||
|
|
@ -378,7 +381,7 @@ export class WebdavApi {
|
|||
return { rev, legacyRev: headLegacyRev, lastModified: rev };
|
||||
}
|
||||
} catch (headError) {
|
||||
PFLog.verbose(
|
||||
SyncLog.verbose(
|
||||
`${WebdavApi.L}.upload() HEAD request failed, falling back to PROPFIND`,
|
||||
headError,
|
||||
);
|
||||
|
|
@ -398,7 +401,7 @@ export class WebdavApi {
|
|||
|
||||
return { rev, legacyRev, lastModified };
|
||||
} catch (e) {
|
||||
PFLog.error(`${WebdavApi.L}.upload() error`, { path, error: e });
|
||||
SyncLog.error(`${WebdavApi.L}.upload() error`, { path, error: e });
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
@ -427,9 +430,9 @@ export class WebdavApi {
|
|||
headers,
|
||||
});
|
||||
|
||||
PFLog.verbose(`${WebdavApi.L}.remove() success for ${path}`);
|
||||
SyncLog.verbose(`${WebdavApi.L}.remove() success for ${path}`);
|
||||
} catch (e) {
|
||||
PFLog.error(`${WebdavApi.L}.remove() error`, { path, error: e });
|
||||
SyncLog.error(`${WebdavApi.L}.remove() error`, { path, error: e });
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
@ -438,7 +441,7 @@ export class WebdavApi {
|
|||
cfg: WebdavPrivateCfg,
|
||||
): Promise<{ success: boolean; error?: string; fullUrl: string }> {
|
||||
const fullPath = this._buildFullPath(cfg.baseUrl, cfg.syncFolderPath || '/');
|
||||
PFLog.verbose(`${WebdavApi.L}.testConnection() testing ${fullPath}`);
|
||||
SyncLog.verbose(`${WebdavApi.L}.testConnection() testing ${fullPath}`);
|
||||
|
||||
try {
|
||||
// Build authorization header
|
||||
|
|
@ -461,7 +464,7 @@ export class WebdavApi {
|
|||
response.status === WebDavHttpStatus.MULTI_STATUS ||
|
||||
response.status === WebDavHttpStatus.OK
|
||||
) {
|
||||
PFLog.verbose(`${WebdavApi.L}.testConnection() success for ${fullPath}`);
|
||||
SyncLog.verbose(`${WebdavApi.L}.testConnection() success for ${fullPath}`);
|
||||
return { success: true, fullUrl: fullPath };
|
||||
}
|
||||
|
||||
|
|
@ -472,7 +475,7 @@ export class WebdavApi {
|
|||
};
|
||||
} catch (e) {
|
||||
const errorMessage = e instanceof Error ? e.message : 'Unknown error occurred';
|
||||
PFLog.warn(`${WebdavApi.L}.testConnection() failed for ${fullPath}`, e);
|
||||
SyncLog.warn(`${WebdavApi.L}.testConnection() failed for ${fullPath}`, e);
|
||||
return { success: false, error: errorMessage, fullUrl: fullPath };
|
||||
}
|
||||
}
|
||||
|
|
@ -492,7 +495,7 @@ export class WebdavApi {
|
|||
*/
|
||||
async testConditionalHeaders(testPath: string): Promise<boolean> {
|
||||
const testContent = `test-${Date.now()}`;
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`${WebdavApi.L}.testConditionalHeaders() testing with path: ${testPath}`,
|
||||
);
|
||||
|
||||
|
|
@ -509,7 +512,7 @@ export class WebdavApi {
|
|||
const currentRev = meta.lastmod;
|
||||
|
||||
if (!currentRev) {
|
||||
PFLog.warn(
|
||||
SyncLog.warn(
|
||||
`${WebdavApi.L}.testConditionalHeaders() Server did not return lastmod - cannot test conditional headers`,
|
||||
);
|
||||
return false;
|
||||
|
|
@ -524,13 +527,13 @@ export class WebdavApi {
|
|||
expectedRev: oldDate,
|
||||
});
|
||||
// Upload succeeded when it should have failed with 412
|
||||
PFLog.warn(
|
||||
SyncLog.warn(
|
||||
`${WebdavApi.L}.testConditionalHeaders() Server ignored If-Unmodified-Since header - conditional headers NOT supported`,
|
||||
);
|
||||
return false; // Headers NOT supported
|
||||
} catch (e) {
|
||||
if (e instanceof RemoteFileChangedUnexpectedly) {
|
||||
PFLog.normal(
|
||||
SyncLog.normal(
|
||||
`${WebdavApi.L}.testConditionalHeaders() Server properly returned 412 - conditional headers ARE supported`,
|
||||
);
|
||||
return true; // Headers ARE supported (got 412 as expected)
|
||||
|
|
@ -594,7 +597,7 @@ export class WebdavApi {
|
|||
// Check if we're already creating this directory
|
||||
const existingPromise = this.directoryCreationQueue.get(parentPath);
|
||||
if (existingPromise) {
|
||||
PFLog.verbose(
|
||||
SyncLog.verbose(
|
||||
`${WebdavApi.L}._ensureParentDirectory() waiting for existing creation of ${parentPath}`,
|
||||
);
|
||||
await existingPromise;
|
||||
|
|
@ -620,7 +623,7 @@ export class WebdavApi {
|
|||
url: path,
|
||||
method: WebDavHttpMethod.MKCOL,
|
||||
});
|
||||
PFLog.verbose(`${WebdavApi.L}._createDirectory() created ${path}`);
|
||||
SyncLog.verbose(`${WebdavApi.L}._createDirectory() created ${path}`);
|
||||
} catch (e) {
|
||||
// Check if error is due to directory already existing (405 Method Not Allowed or 409 Conflict)
|
||||
if (
|
||||
|
|
@ -631,12 +634,12 @@ export class WebdavApi {
|
|||
e.response.status === WebDavHttpStatus.MOVED_PERMANENTLY || // Moved permanently - directory exists
|
||||
e.response.status === WebDavHttpStatus.OK) // OK - directory exists
|
||||
) {
|
||||
PFLog.verbose(
|
||||
SyncLog.verbose(
|
||||
`${WebdavApi.L}._createDirectory() directory likely exists: ${path} (status: ${e.response.status})`,
|
||||
);
|
||||
} else {
|
||||
// Log other errors but don't throw - we'll let the actual upload fail if needed
|
||||
PFLog.warn(`${WebdavApi.L}._createDirectory() unexpected error for ${path}`, e);
|
||||
SyncLog.warn(`${WebdavApi.L}._createDirectory() unexpected error for ${path}`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -742,7 +745,7 @@ export class WebdavApi {
|
|||
let effectiveLastmod = lastModified;
|
||||
if (!lastModified && etag) {
|
||||
effectiveLastmod = this._cleanRev(etag);
|
||||
PFLog.warn(
|
||||
SyncLog.warn(
|
||||
`${WebdavApi.L}._getFileMetaViaHead() No Last-Modified header for ${fullPath}, using ETag as revision. ` +
|
||||
`This may indicate a reverse proxy or server configuration issue.`,
|
||||
);
|
||||
|
|
@ -767,7 +770,7 @@ export class WebdavApi {
|
|||
size = parsedSize;
|
||||
}
|
||||
} catch (e) {
|
||||
PFLog.warn(
|
||||
SyncLog.warn(
|
||||
`${WebdavApi.L}._getFileMetaViaHead() invalid content-length: ${contentLength}`,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { registerPlugin } from '@capacitor/core';
|
||||
import { PFLog } from '../../../../core/log';
|
||||
import { SyncLog } from '../../../../core/log';
|
||||
import {
|
||||
AuthFailSPError,
|
||||
PotentialCorsError,
|
||||
|
|
@ -59,7 +59,7 @@ export class WebDavHttpAdapter {
|
|||
// On native platforms (Android + iOS), use the WebDavHttp plugin.
|
||||
// This bypasses CapacitorHttp which has issues with WebDAV responses
|
||||
// (empty bodies on Android/Koofr, broken JSON auto-parsing on iOS).
|
||||
PFLog.log(
|
||||
SyncLog.log(
|
||||
`${WebDavHttpAdapter.L}.request() using WebDavHttp for ${options.method}`,
|
||||
);
|
||||
const webdavResponse = await WebDavHttp.request({
|
||||
|
|
@ -105,7 +105,7 @@ export class WebDavHttpAdapter {
|
|||
throw e;
|
||||
}
|
||||
|
||||
PFLog.error(`${WebDavHttpAdapter.L}.request() error`, {
|
||||
SyncLog.error(`${WebDavHttpAdapter.L}.request() error`, {
|
||||
url: options.url,
|
||||
method: options.method,
|
||||
error: e,
|
||||
|
|
@ -198,7 +198,7 @@ export class WebDavHttpAdapter {
|
|||
// However, without making a test request, we can't be certain
|
||||
|
||||
// Log a warning about the ambiguity
|
||||
PFLog.warn(
|
||||
SyncLog.warn(
|
||||
`${WebDavHttpAdapter.L}._isCorsError() Ambiguous network error - might be CORS:`,
|
||||
error,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { PFLog } from '../../../../core/log';
|
||||
import { SyncLog } from '../../../../core/log';
|
||||
import { RemoteFileNotFoundAPIError } from '../../../core/errors/sync-errors';
|
||||
|
||||
export interface FileMeta {
|
||||
|
|
@ -48,7 +48,7 @@ export class WebdavXmlParser {
|
|||
: WebdavXmlParser.MAX_XML_SIZE * 10; // Allow larger files for actual file content (100MB)
|
||||
|
||||
if (content.length > maxSize) {
|
||||
PFLog.error(
|
||||
SyncLog.error(
|
||||
`${WebdavXmlParser.L}.validateResponseContent() Content too large: ${content.length} bytes`,
|
||||
);
|
||||
throw new Error(
|
||||
|
|
@ -57,7 +57,7 @@ export class WebdavXmlParser {
|
|||
}
|
||||
|
||||
if (this.isHtmlResponse(content)) {
|
||||
PFLog.error(
|
||||
SyncLog.error(
|
||||
`${WebdavXmlParser.L}.${operation}() received HTML error page instead of ${expectedContentDescription}`,
|
||||
{
|
||||
path,
|
||||
|
|
@ -86,7 +86,7 @@ export class WebdavXmlParser {
|
|||
parseMultiplePropsFromXml(xmlText: string, basePath: string): FileMeta[] {
|
||||
// Validate XML size
|
||||
if (xmlText.length > WebdavXmlParser.MAX_XML_SIZE) {
|
||||
PFLog.error(
|
||||
SyncLog.error(
|
||||
`${WebdavXmlParser.L}.parseMultiplePropsFromXml() XML too large: ${xmlText.length} bytes`,
|
||||
);
|
||||
throw new RemoteFileNotFoundAPIError(
|
||||
|
|
@ -96,7 +96,7 @@ export class WebdavXmlParser {
|
|||
|
||||
// Basic XML validation
|
||||
if (!xmlText.trim().startsWith('<?xml') && !xmlText.trim().startsWith('<')) {
|
||||
PFLog.error(
|
||||
SyncLog.error(
|
||||
`${WebdavXmlParser.L}.parseMultiplePropsFromXml() Invalid XML: doesn't start with <?xml or <`,
|
||||
);
|
||||
return [];
|
||||
|
|
@ -108,7 +108,7 @@ export class WebdavXmlParser {
|
|||
|
||||
const parserError = xmlDoc.querySelector('parsererror');
|
||||
if (parserError) {
|
||||
PFLog.err(
|
||||
SyncLog.err(
|
||||
`${WebdavXmlParser.L}.parseMultiplePropsFromXml() XML parsing error`,
|
||||
parserError.textContent,
|
||||
);
|
||||
|
|
@ -147,7 +147,10 @@ export class WebdavXmlParser {
|
|||
|
||||
return results;
|
||||
} catch (error) {
|
||||
PFLog.err(`${WebdavXmlParser.L}.parseMultiplePropsFromXml() parsing error`, error);
|
||||
SyncLog.err(
|
||||
`${WebdavXmlParser.L}.parseMultiplePropsFromXml() parsing error`,
|
||||
error,
|
||||
);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
import { Store } from '@ngrx/store';
|
||||
import { selectSyncConfig } from '../../features/config/store/global-config.reducer';
|
||||
import { DataInitStateService } from '../../core/data-init/data-init-state.service';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { SyncLog } from '../../core/log';
|
||||
import { SyncProviderId, toSyncProviderId } from './provider.const';
|
||||
import { SyncProviderServiceInterface } from './provider.interface';
|
||||
import {
|
||||
|
|
@ -177,11 +177,11 @@ export class SyncProviderManager {
|
|||
};
|
||||
}
|
||||
} catch (e) {
|
||||
PFLog.err('SyncProviderManager: Failed to set sync provider:', e);
|
||||
SyncLog.err('SyncProviderManager: Failed to set sync provider:', e);
|
||||
}
|
||||
});
|
||||
|
||||
PFLog.normal('SyncProviderManager: Initialized');
|
||||
SyncLog.normal('SyncProviderManager: Initialized');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -296,9 +296,9 @@ export class SyncProviderManager {
|
|||
});
|
||||
});
|
||||
|
||||
PFLog.normal(`SyncProviderManager: Active provider set to ${providerId}`);
|
||||
SyncLog.normal(`SyncProviderManager: Active provider set to ${providerId}`);
|
||||
} else {
|
||||
PFLog.err(`SyncProviderManager: Provider not found: ${providerId}`);
|
||||
SyncLog.err(`SyncProviderManager: Provider not found: ${providerId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { createAppDataCompleteMock } from '../../util/app-data-mock';
|
|||
import { createValidate } from 'typia';
|
||||
import { initialTaskState } from '../../features/tasks/store/task.reducer';
|
||||
import { DEFAULT_TASK, TaskState } from '../../features/tasks/task.model';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
|
||||
interface TestInterface {
|
||||
globalConfig: {
|
||||
|
|
@ -24,8 +24,8 @@ describe('autoFixTypiaErrors', () => {
|
|||
let errSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
// Spy on PFLog.err to prevent test output cluttering
|
||||
errSpy = spyOn(PFLog, 'err').and.stub();
|
||||
// Spy on OpLog.err to prevent test output cluttering
|
||||
errSpy = spyOn(OpLog, 'err').and.stub();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { AppDataComplete } from '../model/model-config';
|
||||
import { IValidation } from 'typia';
|
||||
import { DEFAULT_GLOBAL_CONFIG } from '../../features/config/default-global-config.const';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
|
||||
export const autoFixTypiaErrors = (
|
||||
data: AppDataComplete,
|
||||
|
|
@ -16,7 +16,7 @@ export const autoFixTypiaErrors = (
|
|||
const path = error.path.replace('$input.', '');
|
||||
const keys = parsePath(path);
|
||||
const value = getValueByPath(data, keys);
|
||||
PFLog.err('Auto-fixing error:', error, keys, value);
|
||||
OpLog.err('Auto-fixing error:', error, keys, value);
|
||||
|
||||
if (
|
||||
error.expected.includes('number') &&
|
||||
|
|
@ -25,38 +25,38 @@ export const autoFixTypiaErrors = (
|
|||
) {
|
||||
const parsedValue = parseFloat(value);
|
||||
setValueByPath(data, keys, parsedValue);
|
||||
PFLog.err(`Fixed: ${path} from string "${value}" to number ${parsedValue}`);
|
||||
OpLog.err(`Fixed: ${path} from string "${value}" to number ${parsedValue}`);
|
||||
} else if (keys[0] === 'globalConfig') {
|
||||
const defaultValue = getValueByPath(DEFAULT_GLOBAL_CONFIG, keys.slice(1));
|
||||
setValueByPath(data, keys, defaultValue);
|
||||
PFLog.warn(
|
||||
OpLog.warn(
|
||||
`Warning: ${path} had an invalid value and was set to default: ${defaultValue}`,
|
||||
);
|
||||
} else if (error.expected.includes('undefined') && value === null) {
|
||||
setValueByPath(data, keys, undefined);
|
||||
PFLog.err(`Fixed: ${path} from null to undefined`);
|
||||
OpLog.err(`Fixed: ${path} from null to undefined`);
|
||||
} else if (error.expected.includes('null') && value === 'null') {
|
||||
setValueByPath(data, keys, null);
|
||||
PFLog.err(`Fixed: ${path} from string null to null`);
|
||||
OpLog.err(`Fixed: ${path} from string null to null`);
|
||||
} else if (error.expected.includes('undefined') && value === 'null') {
|
||||
setValueByPath(data, keys, undefined);
|
||||
PFLog.err(`Fixed: ${path} from string null to null`);
|
||||
OpLog.err(`Fixed: ${path} from string null to null`);
|
||||
} else if (error.expected.includes('null') && value === undefined) {
|
||||
setValueByPath(data, keys, null);
|
||||
PFLog.err(`Fixed: ${path} from undefined to null`);
|
||||
OpLog.err(`Fixed: ${path} from undefined to null`);
|
||||
} else if (error.expected.includes('boolean') && !value) {
|
||||
setValueByPath(data, keys, false);
|
||||
PFLog.err(`Fixed: ${path} to false (was ${value})`);
|
||||
OpLog.err(`Fixed: ${path} to false (was ${value})`);
|
||||
} else if (keys[0] === 'task' && error.expected.includes('number')) {
|
||||
// If the value is a string that can be parsed to a number, parse it
|
||||
if (typeof value === 'string' && !isNaN(parseFloat(value))) {
|
||||
setValueByPath(data, keys, parseFloat(value));
|
||||
PFLog.err(
|
||||
OpLog.err(
|
||||
`Fixed: ${path} from string "${value}" to number ${parseFloat(value)}`,
|
||||
);
|
||||
} else {
|
||||
setValueByPath(data, keys, 0);
|
||||
PFLog.err(`Fixed: ${path} to 0 (was ${value})`);
|
||||
OpLog.err(`Fixed: ${path} to 0 (was ${value})`);
|
||||
}
|
||||
} else if (
|
||||
keys[0] === 'simpleCounter' &&
|
||||
|
|
@ -68,7 +68,7 @@ export const autoFixTypiaErrors = (
|
|||
) {
|
||||
// Fix for issue #4593: simpleCounter countOnDay null value
|
||||
setValueByPath(data, keys, 0);
|
||||
PFLog.err(`Fixed: ${path} from null to 0 for simpleCounter`);
|
||||
OpLog.err(`Fixed: ${path} from null to 0 for simpleCounter`);
|
||||
} else if (
|
||||
keys[0] === 'taskRepeatCfg' &&
|
||||
keys[1] === 'entities' &&
|
||||
|
|
@ -84,7 +84,7 @@ export const autoFixTypiaErrors = (
|
|||
const orderIndex = ids.indexOf(entityId);
|
||||
const orderValue = orderIndex >= 0 ? orderIndex : 0;
|
||||
setValueByPath(data, keys, orderValue);
|
||||
PFLog.err(`Fixed: ${path} from null to ${orderValue} for taskRepeatCfg order`);
|
||||
OpLog.err(`Fixed: ${path} from null to ${orderValue} for taskRepeatCfg order`);
|
||||
} else if (
|
||||
keys[0] === 'metric' &&
|
||||
keys[1] === 'entities' &&
|
||||
|
|
@ -97,7 +97,7 @@ export const autoFixTypiaErrors = (
|
|||
// Fix deprecated metric array fields (obstructions, improvements, improvementsTomorrow)
|
||||
// These fields are marked "TODO remove" and will be removed in future
|
||||
setValueByPath(data, keys, []);
|
||||
PFLog.err(`Fixed: ${path} to empty array for deprecated metric field`);
|
||||
OpLog.err(`Fixed: ${path} to empty array for deprecated metric field`);
|
||||
} else if (
|
||||
keys[0] === 'improvement' &&
|
||||
keys[1] === 'hiddenImprovementBannerItems' &&
|
||||
|
|
@ -105,7 +105,7 @@ export const autoFixTypiaErrors = (
|
|||
) {
|
||||
// Fix improvement.hiddenImprovementBannerItems (deprecated)
|
||||
setValueByPath(data, keys, []);
|
||||
PFLog.err(`Fixed: ${path} to empty array for deprecated improvement field`);
|
||||
OpLog.err(`Fixed: ${path} to empty array for deprecated improvement field`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -159,7 +159,7 @@ const setValueByPath = (
|
|||
value: unknown,
|
||||
): void => {
|
||||
if (!Array.isArray(path) || path.length === 0) return;
|
||||
PFLog.err('Auto-fixing error =>', path, value);
|
||||
OpLog.err('Auto-fixing error =>', path, value);
|
||||
|
||||
let current: Record<string | number, unknown> = obj;
|
||||
for (let i = 0; i < path.length - 1; i++) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { AppDataComplete } from '../model/model-config';
|
|||
import { INBOX_PROJECT } from '../../features/project/project.const';
|
||||
import { autoFixTypiaErrors } from './auto-fix-typia-errors';
|
||||
import { IValidation } from 'typia';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import { repairMenuTree } from './repair-menu-tree';
|
||||
import { initialTimeTrackingState } from '../../features/time-tracking/store/time-tracking.reducer';
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ const _fixTaskRepeatCfgInvalidQuickSetting = (data: AppDataComplete): AppDataCom
|
|||
quickSettingsRequiringStartDate.includes(cfg.quickSetting) &&
|
||||
!cfg.startDate
|
||||
) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
`Fixing repeat config ${cfg.id}: ${cfg.quickSetting} with missing startDate -> CUSTOM`,
|
||||
);
|
||||
cfg.quickSetting = 'CUSTOM';
|
||||
|
|
@ -203,7 +203,7 @@ const _removeDuplicatesFromArchive = (data: AppDataComplete): AppDataComplete =>
|
|||
}
|
||||
});
|
||||
if (duplicateYoungIds.length > 0) {
|
||||
PFLog.log(duplicateYoungIds.length + ' duplicates removed from archiveYoung.');
|
||||
OpLog.log(duplicateYoungIds.length + ' duplicates removed from archiveYoung.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ const _removeDuplicatesFromArchive = (data: AppDataComplete): AppDataComplete =>
|
|||
}
|
||||
});
|
||||
if (duplicateOldIds.length > 0) {
|
||||
PFLog.log(duplicateOldIds.length + ' duplicates removed from archiveOld.');
|
||||
OpLog.log(duplicateOldIds.length + ' duplicates removed from archiveOld.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ const _removeDuplicatesFromArchive = (data: AppDataComplete): AppDataComplete =>
|
|||
}
|
||||
});
|
||||
if (duplicateBetweenArchives.length > 0) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
duplicateBetweenArchives.length +
|
||||
' duplicates removed from archiveYoung (kept in archiveOld).',
|
||||
);
|
||||
|
|
@ -280,7 +280,7 @@ const _moveArchivedSubTasksToUnarchivedParents = (
|
|||
!taskArchiveOldState.ids.includes(t.parentId),
|
||||
);
|
||||
|
||||
PFLog.log('orphanArchivedYoungSubTasks', orphanArchivedYoungSubTasks);
|
||||
OpLog.log('orphanArchivedYoungSubTasks', orphanArchivedYoungSubTasks);
|
||||
const promotedYoungSubTaskIds: string[] = [];
|
||||
orphanArchivedYoungSubTasks.forEach((t: TaskCopy) => {
|
||||
// delete archived if duplicate
|
||||
|
|
@ -312,7 +312,7 @@ const _moveArchivedSubTasksToUnarchivedParents = (
|
|||
}
|
||||
});
|
||||
if (promotedYoungSubTaskIds.length > 0) {
|
||||
PFLog.warn(
|
||||
OpLog.warn(
|
||||
`[data-repair] ${promotedYoungSubTaskIds.length} archived subtask(s) promoted to standalone tasks due to missing parent:`,
|
||||
promotedYoungSubTaskIds,
|
||||
);
|
||||
|
|
@ -328,7 +328,7 @@ const _moveArchivedSubTasksToUnarchivedParents = (
|
|||
!taskArchiveYoungState.ids.includes(t.parentId),
|
||||
);
|
||||
|
||||
PFLog.log('orphanArchivedOldSubTasks', orphanArchivedOldSubTasks);
|
||||
OpLog.log('orphanArchivedOldSubTasks', orphanArchivedOldSubTasks);
|
||||
const promotedOldSubTaskIds: string[] = [];
|
||||
orphanArchivedOldSubTasks.forEach((t: TaskCopy) => {
|
||||
// delete archived if duplicate
|
||||
|
|
@ -360,7 +360,7 @@ const _moveArchivedSubTasksToUnarchivedParents = (
|
|||
}
|
||||
});
|
||||
if (promotedOldSubTaskIds.length > 0) {
|
||||
PFLog.warn(
|
||||
OpLog.warn(
|
||||
`[data-repair] ${promotedOldSubTaskIds.length} old archived subtask(s) promoted to standalone tasks due to missing parent:`,
|
||||
promotedOldSubTaskIds,
|
||||
);
|
||||
|
|
@ -380,7 +380,7 @@ const _moveUnArchivedSubTasksToArchivedParents = (
|
|||
.map((id: string) => taskState.entities[id] as TaskCopy)
|
||||
.filter((t: TaskCopy) => t.parentId && !taskState.ids.includes(t.parentId));
|
||||
|
||||
PFLog.log('orphanUnArchivedSubTasks', orphanUnArchivedSubTasks);
|
||||
OpLog.log('orphanUnArchivedSubTasks', orphanUnArchivedSubTasks);
|
||||
const promotedUnArchivedSubTaskIds: string[] = [];
|
||||
orphanUnArchivedSubTasks.forEach((t: TaskCopy) => {
|
||||
// delete un-archived if duplicate in either archive
|
||||
|
|
@ -434,7 +434,7 @@ const _moveUnArchivedSubTasksToArchivedParents = (
|
|||
}
|
||||
});
|
||||
if (promotedUnArchivedSubTaskIds.length > 0) {
|
||||
PFLog.warn(
|
||||
OpLog.warn(
|
||||
`[data-repair] ${promotedUnArchivedSubTaskIds.length} unarchived subtask(s) promoted to standalone tasks due to missing parent:`,
|
||||
promotedUnArchivedSubTaskIds,
|
||||
);
|
||||
|
|
@ -498,7 +498,7 @@ const _removeMissingTasksFromListsOrRestoreFromArchive = (
|
|||
);
|
||||
|
||||
if (taskIdsToRestoreFromArchive.length > 0) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
taskIdsToRestoreFromArchive.length + ' missing tasks restored from archive.',
|
||||
);
|
||||
}
|
||||
|
|
@ -561,7 +561,7 @@ const _addOrphanedTasksToProjectLists = (data: AppDataComplete): AppDataComplete
|
|||
});
|
||||
|
||||
if (orphanedTaskIds.length > 0) {
|
||||
PFLog.log(orphanedTaskIds.length + ' orphaned tasks found & restored.');
|
||||
OpLog.log(orphanedTaskIds.length + ' orphaned tasks found & restored.');
|
||||
}
|
||||
|
||||
return data;
|
||||
|
|
@ -584,7 +584,7 @@ const _addInboxProjectIdIfNecessary = (data: AppDataComplete): AppDataComplete =
|
|||
taskIds.forEach((id) => {
|
||||
const t = task.entities[id] as TaskCopy;
|
||||
if (!t.projectId) {
|
||||
PFLog.log('Set inbox project id for task ' + t.id);
|
||||
OpLog.log('Set inbox project id for task ' + t.id);
|
||||
|
||||
const inboxProject = data.project.entities[INBOX_PROJECT.id]!;
|
||||
data.project.entities[INBOX_PROJECT.id] = {
|
||||
|
|
@ -600,13 +600,13 @@ const _addInboxProjectIdIfNecessary = (data: AppDataComplete): AppDataComplete =
|
|||
}
|
||||
});
|
||||
|
||||
PFLog.log(taskArchiveYoungIds);
|
||||
PFLog.log(Object.keys(archiveYoung.task.entities));
|
||||
OpLog.log(taskArchiveYoungIds);
|
||||
OpLog.log(Object.keys(archiveYoung.task.entities));
|
||||
|
||||
taskArchiveYoungIds.forEach((id) => {
|
||||
const t = archiveYoung.task.entities[id] as TaskCopy;
|
||||
if (!t.projectId) {
|
||||
PFLog.log('Set inbox project for missing project id from archive task ' + t.id);
|
||||
OpLog.log('Set inbox project for missing project id from archive task ' + t.id);
|
||||
t.projectId = INBOX_PROJECT.id;
|
||||
}
|
||||
// while we are at it, we also cleanup the today tag
|
||||
|
|
@ -615,13 +615,13 @@ const _addInboxProjectIdIfNecessary = (data: AppDataComplete): AppDataComplete =
|
|||
}
|
||||
});
|
||||
|
||||
PFLog.log(taskArchiveOldIds);
|
||||
PFLog.log(Object.keys(archiveOld.task.entities));
|
||||
OpLog.log(taskArchiveOldIds);
|
||||
OpLog.log(Object.keys(archiveOld.task.entities));
|
||||
|
||||
taskArchiveOldIds.forEach((id) => {
|
||||
const t = archiveOld.task.entities[id] as TaskCopy;
|
||||
if (!t.projectId) {
|
||||
PFLog.log('Set inbox project for missing project id from old archive task ' + t.id);
|
||||
OpLog.log('Set inbox project for missing project id from old archive task ' + t.id);
|
||||
t.projectId = INBOX_PROJECT.id;
|
||||
}
|
||||
// while we are at it, we also cleanup the today tag
|
||||
|
|
@ -659,29 +659,29 @@ const _removeNonExistentProjectIdsFromTasks = (
|
|||
taskIds.forEach((id) => {
|
||||
const t = task.entities[id] as TaskCopy;
|
||||
if (t.projectId && !projectIds.includes(t.projectId)) {
|
||||
PFLog.log('Delete missing project id from task ' + t.projectId);
|
||||
OpLog.log('Delete missing project id from task ' + t.projectId);
|
||||
t.projectId = INBOX_PROJECT.id;
|
||||
}
|
||||
});
|
||||
|
||||
PFLog.log(taskArchiveYoungIds);
|
||||
PFLog.log(Object.keys(archiveYoung.task.entities));
|
||||
OpLog.log(taskArchiveYoungIds);
|
||||
OpLog.log(Object.keys(archiveYoung.task.entities));
|
||||
|
||||
taskArchiveYoungIds.forEach((id) => {
|
||||
const t = archiveYoung.task.entities[id] as TaskCopy;
|
||||
if (t.projectId && !projectIds.includes(t.projectId)) {
|
||||
PFLog.log('Delete missing project id from archive task ' + t.projectId);
|
||||
OpLog.log('Delete missing project id from archive task ' + t.projectId);
|
||||
t.projectId = INBOX_PROJECT.id;
|
||||
}
|
||||
});
|
||||
|
||||
PFLog.log(taskArchiveOldIds);
|
||||
PFLog.log(Object.keys(archiveOld.task.entities));
|
||||
OpLog.log(taskArchiveOldIds);
|
||||
OpLog.log(Object.keys(archiveOld.task.entities));
|
||||
|
||||
taskArchiveOldIds.forEach((id) => {
|
||||
const t = archiveOld.task.entities[id] as TaskCopy;
|
||||
if (t.projectId && !projectIds.includes(t.projectId)) {
|
||||
PFLog.log('Delete missing project id from old archive task ' + t.projectId);
|
||||
OpLog.log('Delete missing project id from old archive task ' + t.projectId);
|
||||
t.projectId = INBOX_PROJECT.id;
|
||||
}
|
||||
});
|
||||
|
|
@ -719,7 +719,7 @@ const _removeNonExistentTagsFromTasks = (data: AppDataComplete): AppDataComplete
|
|||
(tagId) => !tagIds.includes(tagId) && tagId !== TODAY_TAG.id,
|
||||
);
|
||||
if (removedTags.length > 0) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
`Removing non-existent tags from task ${t.id}: ${removedTags.join(', ')}`,
|
||||
);
|
||||
removedCount += removedTags.length;
|
||||
|
|
@ -739,7 +739,7 @@ const _removeNonExistentTagsFromTasks = (data: AppDataComplete): AppDataComplete
|
|||
(tagId) => !tagIds.includes(tagId) && tagId !== TODAY_TAG.id,
|
||||
);
|
||||
if (removedTags.length > 0) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
`Removing non-existent tags from archive task ${t.id}: ${removedTags.join(', ')}`,
|
||||
);
|
||||
removedCount += removedTags.length;
|
||||
|
|
@ -759,7 +759,7 @@ const _removeNonExistentTagsFromTasks = (data: AppDataComplete): AppDataComplete
|
|||
(tagId) => !tagIds.includes(tagId) && tagId !== TODAY_TAG.id,
|
||||
);
|
||||
if (removedTags.length > 0) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
`Removing non-existent tags from old archive task ${t.id}: ${removedTags.join(', ')}`,
|
||||
);
|
||||
removedCount += removedTags.length;
|
||||
|
|
@ -770,7 +770,7 @@ const _removeNonExistentTagsFromTasks = (data: AppDataComplete): AppDataComplete
|
|||
});
|
||||
|
||||
if (removedCount > 0) {
|
||||
PFLog.log(`Total non-existent tags removed from tasks: ${removedCount}`);
|
||||
OpLog.log(`Total non-existent tags removed from tasks: ${removedCount}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
|
|
@ -785,7 +785,7 @@ const _removeNonExistentProjectIdsFromIssueProviders = (
|
|||
issueProviderIds.forEach((id) => {
|
||||
const t = issueProvider.entities[id] as IssueProvider;
|
||||
if (t.defaultProjectId && !projectIds.includes(t.defaultProjectId)) {
|
||||
PFLog.log('Delete missing project id from issueProvider ' + t.defaultProjectId);
|
||||
OpLog.log('Delete missing project id from issueProvider ' + t.defaultProjectId);
|
||||
t.defaultProjectId = null;
|
||||
}
|
||||
});
|
||||
|
|
@ -803,7 +803,7 @@ const _removeNonExistentProjectIdsFromTaskRepeatCfg = (
|
|||
const repeatCfg = taskRepeatCfg.entities[id] as TaskRepeatCfgCopy;
|
||||
if (repeatCfg.projectId && !projectIds.includes(repeatCfg.projectId)) {
|
||||
if (repeatCfg.tagIds.length) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
'Delete missing project id from task repeat cfg ' + repeatCfg.projectId,
|
||||
);
|
||||
repeatCfg.projectId = null;
|
||||
|
|
@ -812,7 +812,7 @@ const _removeNonExistentProjectIdsFromTaskRepeatCfg = (
|
|||
(rid: string) => rid !== repeatCfg.id,
|
||||
);
|
||||
delete taskRepeatCfg.entities[repeatCfg.id];
|
||||
PFLog.log('Delete task repeat cfg with missing project id' + repeatCfg.projectId);
|
||||
OpLog.log('Delete task repeat cfg with missing project id' + repeatCfg.projectId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -833,7 +833,7 @@ const _removeNonExistentRepeatCfgIdsFromTasks = (
|
|||
taskIds.forEach((id) => {
|
||||
const t = task.entities[id] as TaskCopy;
|
||||
if (t.repeatCfgId && !repeatCfgIds.includes(t.repeatCfgId)) {
|
||||
PFLog.log(`Clearing non-existent repeatCfgId from task ${t.id}: ${t.repeatCfgId}`);
|
||||
OpLog.log(`Clearing non-existent repeatCfgId from task ${t.id}: ${t.repeatCfgId}`);
|
||||
t.repeatCfgId = undefined;
|
||||
removedCount++;
|
||||
}
|
||||
|
|
@ -843,7 +843,7 @@ const _removeNonExistentRepeatCfgIdsFromTasks = (
|
|||
taskArchiveYoungIds.forEach((id) => {
|
||||
const t = archiveYoung.task.entities[id] as TaskCopy;
|
||||
if (t.repeatCfgId && !repeatCfgIds.includes(t.repeatCfgId)) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
`Clearing non-existent repeatCfgId from archive task ${t.id}: ${t.repeatCfgId}`,
|
||||
);
|
||||
t.repeatCfgId = undefined;
|
||||
|
|
@ -855,7 +855,7 @@ const _removeNonExistentRepeatCfgIdsFromTasks = (
|
|||
taskArchiveOldIds.forEach((id) => {
|
||||
const t = archiveOld.task.entities[id] as TaskCopy;
|
||||
if (t.repeatCfgId && !repeatCfgIds.includes(t.repeatCfgId)) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
`Clearing non-existent repeatCfgId from old archive task ${t.id}: ${t.repeatCfgId}`,
|
||||
);
|
||||
t.repeatCfgId = undefined;
|
||||
|
|
@ -864,7 +864,7 @@ const _removeNonExistentRepeatCfgIdsFromTasks = (
|
|||
});
|
||||
|
||||
if (removedCount > 0) {
|
||||
PFLog.log(`Total non-existent repeatCfgIds cleared from tasks: ${removedCount}`);
|
||||
OpLog.log(`Total non-existent repeatCfgIds cleared from tasks: ${removedCount}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
|
|
@ -875,7 +875,7 @@ const _cleanupNonExistingTasksFromLists = (data: AppDataComplete): AppDataComple
|
|||
projectIds.forEach((pid) => {
|
||||
const projectItem = data.project.entities[pid];
|
||||
if (!projectItem) {
|
||||
PFLog.log(data.project);
|
||||
OpLog.log(data.project);
|
||||
throw new Error('No project');
|
||||
}
|
||||
(projectItem as ProjectCopy).taskIds = projectItem.taskIds.filter(
|
||||
|
|
@ -890,7 +890,7 @@ const _cleanupNonExistingTasksFromLists = (data: AppDataComplete): AppDataComple
|
|||
.map((id) => data.tag.entities[id])
|
||||
.forEach((tagItem) => {
|
||||
if (!tagItem) {
|
||||
PFLog.log(data.tag);
|
||||
OpLog.log(data.tag);
|
||||
throw new Error('No tag');
|
||||
}
|
||||
(tagItem as TagCopy).taskIds = tagItem.taskIds.filter(
|
||||
|
|
@ -905,7 +905,7 @@ const _cleanupNonExistingNotesFromLists = (data: AppDataComplete): AppDataComple
|
|||
projectIds.forEach((pid) => {
|
||||
const projectItem = data.project.entities[pid];
|
||||
if (!projectItem) {
|
||||
PFLog.log(data.project);
|
||||
OpLog.log(data.project);
|
||||
throw new Error('No project');
|
||||
}
|
||||
(projectItem as ProjectCopy).noteIds = (projectItem as ProjectCopy).noteIds
|
||||
|
|
@ -926,14 +926,14 @@ const _fixOrphanedNotes = (data: AppDataComplete): AppDataComplete => {
|
|||
noteIds.forEach((nId) => {
|
||||
const note = data.note.entities[nId];
|
||||
if (!note) {
|
||||
PFLog.log(data.note);
|
||||
OpLog.log(data.note);
|
||||
throw new Error('No note');
|
||||
}
|
||||
// missing project case
|
||||
if (note.projectId) {
|
||||
if (data.project.entities[note.projectId]) {
|
||||
if (!data.project.entities[note.projectId]!.noteIds.includes(note.id)) {
|
||||
PFLog.log(
|
||||
OpLog.log(
|
||||
'Add orphaned note back to project list ' + note.projectId + ' ' + note.id,
|
||||
);
|
||||
|
||||
|
|
@ -944,7 +944,7 @@ const _fixOrphanedNotes = (data: AppDataComplete): AppDataComplete => {
|
|||
};
|
||||
}
|
||||
} else {
|
||||
PFLog.log('Delete missing project id from note ' + note.id);
|
||||
OpLog.log('Delete missing project id from note ' + note.id);
|
||||
note.projectId = null;
|
||||
|
||||
if (!data.note.todayOrder.includes(note.id)) {
|
||||
|
|
@ -953,7 +953,7 @@ const _fixOrphanedNotes = (data: AppDataComplete): AppDataComplete => {
|
|||
}
|
||||
} // orphaned note case
|
||||
else if (!data.note.todayOrder.includes(note.id)) {
|
||||
PFLog.log('Add orphaned note to today list ' + note.id);
|
||||
OpLog.log('Add orphaned note to today list ' + note.id);
|
||||
|
||||
if (!data.note.todayOrder.includes(note.id)) {
|
||||
data.note.todayOrder = [...data.note.todayOrder, note.id];
|
||||
|
|
@ -970,7 +970,7 @@ const _fixInconsistentProjectId = (data: AppDataComplete): AppDataComplete => {
|
|||
.map((id) => data.project.entities[id])
|
||||
.forEach((projectItem) => {
|
||||
if (!projectItem) {
|
||||
PFLog.log(data.project);
|
||||
OpLog.log(data.project);
|
||||
throw new Error('No project');
|
||||
}
|
||||
projectItem.taskIds.forEach((tid) => {
|
||||
|
|
@ -1015,7 +1015,7 @@ const _fixInconsistentTagId = (data: AppDataComplete): AppDataComplete => {
|
|||
.map((id) => data.tag.entities[id])
|
||||
.forEach((tagItem) => {
|
||||
if (!tagItem) {
|
||||
PFLog.log(data.tag);
|
||||
OpLog.log(data.tag);
|
||||
throw new Error('No tag');
|
||||
}
|
||||
tagItem.taskIds.forEach((tid) => {
|
||||
|
|
@ -1037,7 +1037,7 @@ const _setTaskProjectIdAccordingToParent = (data: AppDataComplete): AppDataCompl
|
|||
.map((id) => data.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
PFLog.log(data.task);
|
||||
OpLog.log(data.task);
|
||||
throw new Error('No task');
|
||||
}
|
||||
if (taskItem.subTaskIds) {
|
||||
|
|
@ -1059,7 +1059,7 @@ const _setTaskProjectIdAccordingToParent = (data: AppDataComplete): AppDataCompl
|
|||
.map((id) => data.archiveYoung.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
PFLog.log(data.archiveYoung.task);
|
||||
OpLog.log(data.archiveYoung.task);
|
||||
throw new Error('No archive task');
|
||||
}
|
||||
if (taskItem.subTaskIds) {
|
||||
|
|
@ -1081,7 +1081,7 @@ const _setTaskProjectIdAccordingToParent = (data: AppDataComplete): AppDataCompl
|
|||
.map((id) => data.archiveOld.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
PFLog.log(data.archiveOld.task);
|
||||
OpLog.log(data.archiveOld.task);
|
||||
throw new Error('No old archive task');
|
||||
}
|
||||
if (taskItem.subTaskIds) {
|
||||
|
|
@ -1108,7 +1108,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataComplete): AppDataComplete => {
|
|||
.map((id) => data.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
PFLog.log(data.task);
|
||||
OpLog.log(data.task);
|
||||
throw new Error('No task');
|
||||
}
|
||||
|
||||
|
|
@ -1117,7 +1117,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataComplete): AppDataComplete => {
|
|||
while (i >= 0) {
|
||||
const sid = taskItem.subTaskIds[i];
|
||||
if (!data.task.entities[sid]) {
|
||||
PFLog.log('Delete orphaned sub task for ', taskItem);
|
||||
OpLog.log('Delete orphaned sub task for ', taskItem);
|
||||
taskItem.subTaskIds.splice(i, 1);
|
||||
}
|
||||
i -= 1;
|
||||
|
|
@ -1130,7 +1130,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataComplete): AppDataComplete => {
|
|||
.map((id) => data.archiveYoung.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
PFLog.log(data.archiveYoung.task);
|
||||
OpLog.log(data.archiveYoung.task);
|
||||
throw new Error('No archive task');
|
||||
}
|
||||
|
||||
|
|
@ -1139,7 +1139,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataComplete): AppDataComplete => {
|
|||
while (i >= 0) {
|
||||
const sid = taskItem.subTaskIds[i];
|
||||
if (!data.archiveYoung.task.entities[sid]) {
|
||||
PFLog.log('Delete orphaned archive sub task for ', taskItem);
|
||||
OpLog.log('Delete orphaned archive sub task for ', taskItem);
|
||||
taskItem.subTaskIds.splice(i, 1);
|
||||
}
|
||||
i -= 1;
|
||||
|
|
@ -1152,7 +1152,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataComplete): AppDataComplete => {
|
|||
.map((id) => data.archiveOld.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
PFLog.log(data.archiveOld.task);
|
||||
OpLog.log(data.archiveOld.task);
|
||||
throw new Error('No old archive task');
|
||||
}
|
||||
|
||||
|
|
@ -1161,7 +1161,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataComplete): AppDataComplete => {
|
|||
while (i >= 0) {
|
||||
const sid = taskItem.subTaskIds[i];
|
||||
if (!data.archiveOld.task.entities[sid]) {
|
||||
PFLog.log('Delete orphaned old archive sub task for ', taskItem);
|
||||
OpLog.log('Delete orphaned old archive sub task for ', taskItem);
|
||||
taskItem.subTaskIds.splice(i, 1);
|
||||
}
|
||||
i -= 1;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import { AppDataComplete } from '../model/model-config';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import { TODAY_TAG } from '../../features/tag/tag.const';
|
||||
|
||||
describe('isRelatedModelDataValid', () => {
|
||||
let isRelatedModelDataValid: any;
|
||||
|
||||
beforeEach(() => {
|
||||
// Suppress PFLog output during tests by spying on the methods
|
||||
spyOn(PFLog, 'log');
|
||||
spyOn(PFLog, 'info');
|
||||
spyOn(PFLog, 'error');
|
||||
spyOn(PFLog, 'warn');
|
||||
spyOn(PFLog, 'err');
|
||||
spyOn(PFLog, 'critical');
|
||||
// Suppress OpLog output during tests by spying on the methods
|
||||
spyOn(OpLog, 'log');
|
||||
spyOn(OpLog, 'info');
|
||||
spyOn(OpLog, 'error');
|
||||
spyOn(OpLog, 'warn');
|
||||
spyOn(OpLog, 'err');
|
||||
spyOn(OpLog, 'critical');
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
// Reset modules to allow re-importing with mocks
|
||||
// @ts-ignore
|
||||
|
|
@ -158,7 +158,7 @@ describe('isRelatedModelDataValid', () => {
|
|||
// Should pass because TODAY_TAG orphans are harmless (virtual tag)
|
||||
expect(result).toBe(true);
|
||||
// Verify warning was logged
|
||||
expect(PFLog.info).toHaveBeenCalledWith(
|
||||
expect(OpLog.info).toHaveBeenCalledWith(
|
||||
jasmine.stringContaining('TODAY_TAG has 2 orphaned task IDs (harmless)'),
|
||||
jasmine.any(Object),
|
||||
);
|
||||
|
|
@ -290,7 +290,7 @@ describe('isRelatedModelDataValid', () => {
|
|||
|
||||
expect(result).toBe(true);
|
||||
// Should not log any self-healing warning
|
||||
expect(PFLog.warn).not.toHaveBeenCalled();
|
||||
expect(OpLog.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { devError } from '../../util/dev-error';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { AppDataComplete } from '../model/model-config';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import {
|
||||
MenuTreeKind,
|
||||
MenuTreeTreeNode,
|
||||
|
|
@ -100,12 +100,12 @@ export const getLastValidityError = (): string | undefined => lastValidityError;
|
|||
|
||||
const _validityError = (errTxt: string, additionalInfo?: any): void => {
|
||||
if (additionalInfo) {
|
||||
PFLog.log('Validity Error Info: ', additionalInfo);
|
||||
OpLog.log('Validity Error Info: ', additionalInfo);
|
||||
if (environment.production) {
|
||||
try {
|
||||
PFLog.log('Validity Error Info string: ', JSON.stringify(additionalInfo));
|
||||
OpLog.log('Validity Error Info string: ', JSON.stringify(additionalInfo));
|
||||
} catch (e) {
|
||||
PFLog.warn('Failed to stringify validity error info:', e);
|
||||
OpLog.warn('Failed to stringify validity error info:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -113,9 +113,9 @@ const _validityError = (errTxt: string, additionalInfo?: any): void => {
|
|||
devError(errTxt);
|
||||
} else {
|
||||
if (errorCount === 4) {
|
||||
PFLog.err('too many validity errors, only logging from now on');
|
||||
OpLog.err('too many validity errors, only logging from now on');
|
||||
}
|
||||
PFLog.err(errTxt);
|
||||
OpLog.err(errTxt);
|
||||
}
|
||||
lastValidityError = errTxt;
|
||||
errorCount++;
|
||||
|
|
@ -288,7 +288,7 @@ const validateTasksToProjectsAndTags = (
|
|||
if (tagId === TODAY_TAG.id) {
|
||||
const orphanedIds = tag.taskIds.filter((tid) => !taskIds.has(tid));
|
||||
if (orphanedIds.length > 0) {
|
||||
PFLog.info(
|
||||
OpLog.info(
|
||||
`[ValidateState] TODAY_TAG has ${orphanedIds.length} orphaned task IDs (harmless)`,
|
||||
{ orphanedIds },
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import {
|
|||
MenuTreeState,
|
||||
MenuTreeTreeNode,
|
||||
} from '../../features/menu-tree/store/menu-tree.model';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
|
||||
/**
|
||||
* Repairs menuTree by removing orphaned project/tag references
|
||||
|
|
@ -17,7 +17,7 @@ export const repairMenuTree = (
|
|||
validProjectIds: Set<string>,
|
||||
validTagIds: Set<string>,
|
||||
): MenuTreeState => {
|
||||
PFLog.log('Repairing menuTree - removing orphaned references');
|
||||
OpLog.log('Repairing menuTree - removing orphaned references');
|
||||
|
||||
/**
|
||||
* Recursively filters tree nodes, removing orphaned project/tag references
|
||||
|
|
@ -41,18 +41,18 @@ export const repairMenuTree = (
|
|||
if (validProjectIds.has(node.id)) {
|
||||
filtered.push(node);
|
||||
} else {
|
||||
PFLog.log(`Removing orphaned project reference ${node.id} from ${treeType}`);
|
||||
OpLog.log(`Removing orphaned project reference ${node.id} from ${treeType}`);
|
||||
}
|
||||
} else if (treeType === 'tagTree' && node.k === MenuTreeKind.TAG) {
|
||||
// Keep tag only if it exists
|
||||
if (validTagIds.has(node.id)) {
|
||||
filtered.push(node);
|
||||
} else {
|
||||
PFLog.log(`Removing orphaned tag reference ${node.id} from ${treeType}`);
|
||||
OpLog.log(`Removing orphaned tag reference ${node.id} from ${treeType}`);
|
||||
}
|
||||
} else {
|
||||
// kind mismatch or unknown
|
||||
PFLog.warn(`Removing invalid node from ${treeType}:`, node);
|
||||
OpLog.warn(`Removing invalid node from ${treeType}:`, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import {
|
|||
tagSharedMetaReducer,
|
||||
plannerSharedMetaReducer,
|
||||
} from '../../root-store/meta/task-shared-meta-reducers';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import { getDbDateStr } from '../../util/get-db-date-str';
|
||||
import { TaskWithSubTasks } from '../../features/tasks/task.model';
|
||||
import {
|
||||
|
|
@ -82,13 +82,13 @@ import {
|
|||
} from '../../features/menu-tree/store/menu-tree.model';
|
||||
|
||||
describe('State Validity After Actions', () => {
|
||||
// Suppress PFLog output during tests
|
||||
// Suppress OpLog output during tests
|
||||
beforeAll(() => {
|
||||
spyOn(PFLog, 'log');
|
||||
spyOn(PFLog, 'error');
|
||||
spyOn(PFLog, 'warn');
|
||||
spyOn(PFLog, 'err');
|
||||
spyOn(PFLog, 'critical');
|
||||
spyOn(OpLog, 'log');
|
||||
spyOn(OpLog, 'error');
|
||||
spyOn(OpLog, 'warn');
|
||||
spyOn(OpLog, 'err');
|
||||
spyOn(OpLog, 'critical');
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import { MetricState } from '../../features/metric/metric.model';
|
|||
import { GlobalConfigState } from '../../features/config/global-config.model';
|
||||
import { AppDataComplete } from '../model/model-config';
|
||||
import { ValidationResult } from '../core/types/sync.types';
|
||||
import { PFLog } from '../../core/log';
|
||||
import { OpLog } from '../../core/log';
|
||||
import {
|
||||
PluginMetaDataState,
|
||||
PluginUserDataState,
|
||||
|
|
@ -106,7 +106,7 @@ export const appDataValidators: {
|
|||
const validateArchiveModel = <R>(d: ArchiveModel | R): ValidationResult<ArchiveModel> => {
|
||||
const r = _validateArchive(d);
|
||||
if (!r.success) {
|
||||
PFLog.log('Validation failed', (r as any)?.errors, r.data);
|
||||
OpLog.log('Validation failed', (r as any)?.errors, r.data);
|
||||
}
|
||||
if (!isEntityStateConsistent((d as ArchiveModel).task)) {
|
||||
return {
|
||||
|
|
@ -131,7 +131,7 @@ const _wrapValidate = <R>(
|
|||
isEntityCheck = false,
|
||||
): ValidationResult<R> => {
|
||||
if (!result.success) {
|
||||
PFLog.log('Validation failed', (result as any)?.errors, result, d);
|
||||
OpLog.log('Validation failed', (result as any)?.errors, result, d);
|
||||
}
|
||||
if (isEntityCheck && !isEntityStateConsistent(d as any)) {
|
||||
return {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue