mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 00:46:45 +00:00
refactor(sync): sanitize menu tree repair logging
This commit is contained in:
parent
78f3a1e180
commit
01d4e6be6f
3 changed files with 85 additions and 5 deletions
|
|
@ -466,6 +466,9 @@ Initial candidate-file audit:
|
|||
applied fixes now route through `SyncLogger` with path/type/count metadata
|
||||
only; raw invalid values, defaults, and full Typia error objects stay out of
|
||||
exportable logs.
|
||||
- `op-log/validation/repair-menu-tree.ts`: menu-tree repair logs now use
|
||||
`SyncLogger` metadata for removed references/invalid nodes; raw node objects
|
||||
and folder names stay out of exportable logs.
|
||||
- `op-log/util/sync-file-prefix.ts`: now delegates to the package helper with
|
||||
app-supplied prefix and error construction. The app-facing shim should remain
|
||||
until consumers are deliberately switched to injected/configured helpers.
|
||||
|
|
|
|||
|
|
@ -3,8 +3,17 @@ import {
|
|||
MenuTreeKind,
|
||||
MenuTreeState,
|
||||
} from '../../features/menu-tree/store/menu-tree.model';
|
||||
import { OP_LOG_SYNC_LOGGER } from '../core/sync-logger.adapter';
|
||||
|
||||
describe('repairMenuTree', () => {
|
||||
let logSpy: jasmine.Spy;
|
||||
let warnSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
logSpy = spyOn(OP_LOG_SYNC_LOGGER, 'log').and.stub();
|
||||
warnSpy = spyOn(OP_LOG_SYNC_LOGGER, 'warn').and.stub();
|
||||
});
|
||||
|
||||
it('should remove orphaned project references from projectTree', () => {
|
||||
const validProjectIds = new Set(['project1', 'project2']);
|
||||
const validTagIds = new Set<string>();
|
||||
|
|
@ -188,4 +197,40 @@ describe('repairMenuTree', () => {
|
|||
expect(result.projectTree).toEqual([{ k: MenuTreeKind.PROJECT, id: 'project1' }]);
|
||||
expect(result.tagTree).toEqual([{ k: MenuTreeKind.TAG, id: 'tag1' }]);
|
||||
});
|
||||
|
||||
it('should log invalid nodes without raw node values', () => {
|
||||
const privateNodeName = 'Private Folder Name';
|
||||
const validProjectIds = new Set<string>();
|
||||
const validTagIds = new Set<string>();
|
||||
|
||||
const menuTree: MenuTreeState = {
|
||||
projectTree: [
|
||||
{
|
||||
k: 'unexpected',
|
||||
id: 'invalid-node-id',
|
||||
name: privateNodeName,
|
||||
} as any,
|
||||
],
|
||||
tagTree: [],
|
||||
};
|
||||
|
||||
const result = repairMenuTree(menuTree, validProjectIds, validTagIds);
|
||||
|
||||
expect(result.projectTree).toEqual([]);
|
||||
expect(warnSpy).toHaveBeenCalledWith(
|
||||
'[repair-menu-tree] Removed invalid node',
|
||||
jasmine.objectContaining({
|
||||
treeType: 'projectTree',
|
||||
nodeKind: 'unknown',
|
||||
hasNodeId: true,
|
||||
}),
|
||||
);
|
||||
|
||||
const serializedLogArgs = JSON.stringify([
|
||||
...logSpy.calls.allArgs(),
|
||||
...warnSpy.calls.allArgs(),
|
||||
]);
|
||||
expect(serializedLogArgs).not.toContain(privateNodeName);
|
||||
expect(serializedLogArgs).not.toContain('invalid-node-id');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,7 +3,39 @@ import {
|
|||
MenuTreeState,
|
||||
MenuTreeTreeNode,
|
||||
} from '../../features/menu-tree/store/menu-tree.model';
|
||||
import { OpLog } from '../../core/log';
|
||||
import { OP_LOG_SYNC_LOGGER } from '../core/sync-logger.adapter';
|
||||
|
||||
const KNOWN_MENU_TREE_KINDS = new Set<string>(Object.values(MenuTreeKind));
|
||||
|
||||
const getNodeKindForLog = (kind: unknown): string =>
|
||||
typeof kind === 'string' && KNOWN_MENU_TREE_KINDS.has(kind) ? kind : 'unknown';
|
||||
|
||||
const logOrphanedReferenceRemoval = (
|
||||
treeType: 'projectTree' | 'tagTree',
|
||||
referenceType: 'project' | 'tag',
|
||||
referenceId: string,
|
||||
): void => {
|
||||
OP_LOG_SYNC_LOGGER.log('[repair-menu-tree] Removed orphaned reference', {
|
||||
treeType,
|
||||
referenceType,
|
||||
referenceId,
|
||||
});
|
||||
};
|
||||
|
||||
const logInvalidNodeRemoval = (
|
||||
treeType: 'projectTree' | 'tagTree',
|
||||
node: MenuTreeTreeNode,
|
||||
): void => {
|
||||
OP_LOG_SYNC_LOGGER.warn('[repair-menu-tree] Removed invalid node', {
|
||||
treeType,
|
||||
nodeKind: getNodeKindForLog(node.k),
|
||||
hasNodeId: typeof node.id === 'string',
|
||||
childCount:
|
||||
node.k === MenuTreeKind.FOLDER && Array.isArray(node.children)
|
||||
? node.children.length
|
||||
: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Repairs menuTree by removing orphaned project/tag references
|
||||
|
|
@ -17,7 +49,7 @@ export const repairMenuTree = (
|
|||
validProjectIds: Set<string>,
|
||||
validTagIds: Set<string>,
|
||||
): MenuTreeState => {
|
||||
OpLog.log('Repairing menuTree - removing orphaned references');
|
||||
OP_LOG_SYNC_LOGGER.log('[repair-menu-tree] Repairing orphaned references');
|
||||
|
||||
/**
|
||||
* Recursively filters tree nodes, removing orphaned project/tag references
|
||||
|
|
@ -41,18 +73,18 @@ export const repairMenuTree = (
|
|||
if (validProjectIds.has(node.id)) {
|
||||
filtered.push(node);
|
||||
} else {
|
||||
OpLog.log(`Removing orphaned project reference ${node.id} from ${treeType}`);
|
||||
logOrphanedReferenceRemoval(treeType, 'project', node.id);
|
||||
}
|
||||
} else if (treeType === 'tagTree' && node.k === MenuTreeKind.TAG) {
|
||||
// Keep tag only if it exists
|
||||
if (validTagIds.has(node.id)) {
|
||||
filtered.push(node);
|
||||
} else {
|
||||
OpLog.log(`Removing orphaned tag reference ${node.id} from ${treeType}`);
|
||||
logOrphanedReferenceRemoval(treeType, 'tag', node.id);
|
||||
}
|
||||
} else {
|
||||
// kind mismatch or unknown
|
||||
OpLog.warn(`Removing invalid node from ${treeType}:`, node);
|
||||
logInvalidNodeRemoval(treeType, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue