fix: address all Obsidian plugin submission code review issues

This commit resolves all required and optional issues from the plugin
submission review to comply with Obsidian plugin guidelines.

Required Changes:
- Type Safety: Added eslint-disable comments with justifications for
  necessary any types in JSON-RPC tool argument handling
- Command IDs: Removed redundant "mcp-server" prefix from command
  identifiers (BREAKING CHANGE):
  - start-mcp-server → start-server
  - stop-mcp-server → stop-server
  - restart-mcp-server → restart-server
- Promise Handling: Added void operator for intentional fire-and-forget
  promise in notification queue processing
- ESLint Directives: Added descriptive explanations to all
  eslint-disable comments
- Switch Statement Scope: Wrapped case blocks in braces to fix lexical
  declaration warnings in glob pattern matcher
- Regular Expression: Added eslint-disable comment for control character
  validation in Windows path checking
- Type Definitions: Changed empty object type {} to object in MCP
  capabilities interface
- Import Statements: Added comprehensive justifications for require()
  usage in Electron/Node.js modules (synchronous access required)

Optional Improvements:
- Code Cleanup: Removed unused imports (MCPPluginSettings, TFile,
  VaultInfo)

Documentation:
- Enhanced inline code documentation for ESLint suppressions and
  require() statements
- Added detailed rationale for synchronous module loading requirements
  in Obsidian plugin context
- Updated CHANGELOG.md for version 1.1.2

All changes verified:
- Build: Successful with no TypeScript errors
- Tests: All 760 tests passing
- ESLint: All review-required issues resolved

Version bumped to 1.1.2 in package.json and manifest.json

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-15 19:30:49 -05:00
parent 8bf8a956f4
commit c62e256331
15 changed files with 62 additions and 29 deletions

View File

@@ -18,9 +18,9 @@ function getCrypto(): Crypto {
// Node.js environment (15+) - uses Web Crypto API standard
if (typeof global !== 'undefined') {
try {
// Note: require() is necessary here for synchronous crypto access in Node.js
// This module is loaded conditionally and esbuild will handle this correctly during bundling
// eslint-disable-next-line @typescript-eslint/no-var-requires
// Using require() is necessary for synchronous crypto access in Obsidian desktop plugins
// ES6 dynamic imports would create race conditions as crypto must be available synchronously
// eslint-disable-next-line @typescript-eslint/no-var-requires -- Synchronous Node.js crypto API access required
const nodeCrypto = require('crypto') as typeof import('crypto');
if (nodeCrypto?.webcrypto) {
return nodeCrypto.webcrypto as unknown as Crypto;

View File

@@ -8,10 +8,9 @@ interface ElectronSafeStorage {
// Safely import safeStorage - may not be available in all environments
let safeStorage: ElectronSafeStorage | null = null;
try {
// Note: require() is necessary here for synchronous access to Electron's safeStorage
// This module is loaded conditionally and may not be available in all environments
// esbuild will handle this correctly during bundling
// eslint-disable-next-line @typescript-eslint/no-var-requires
// Using require() is necessary for synchronous access to Electron's safeStorage API in Obsidian desktop plugins
// ES6 dynamic imports would create race conditions as this module must be available synchronously
// eslint-disable-next-line @typescript-eslint/no-var-requires -- Synchronous Electron API access required for Obsidian plugin
const electron = require('electron') as typeof import('electron');
safeStorage = electron.safeStorage || null;
} catch (error) {

View File

@@ -45,7 +45,7 @@ export class GlobUtils {
i++;
break;
case '[':
case '[': {
// Character class
const closeIdx = pattern.indexOf(']', i);
if (closeIdx === -1) {
@@ -57,8 +57,9 @@ export class GlobUtils {
i = closeIdx + 1;
}
break;
case '{':
}
case '{': {
// Alternatives {a,b,c}
const closeIdx2 = pattern.indexOf('}', i);
if (closeIdx2 === -1) {
@@ -67,13 +68,14 @@ export class GlobUtils {
i++;
} else {
const alternatives = pattern.substring(i + 1, closeIdx2).split(',');
regexStr += '(' + alternatives.map(alt =>
regexStr += '(' + alternatives.map(alt =>
this.escapeRegex(alt)
).join('|') + ')';
i = closeIdx2 + 1;
}
break;
}
case '/':
case '.':
case '(':

View File

@@ -66,7 +66,8 @@ export class PathUtils {
// Check for invalid characters (Windows restrictions)
// Invalid chars: < > : " | ? * and ASCII control characters (0-31)
const invalidChars = /[<>:"|?*\u0000-\u001F]/;
// eslint-disable-next-line no-control-regex -- Control characters \x00-\x1F required for Windows path validation
const invalidChars = /[<>:"|?*\x00-\x1F]/;
if (invalidChars.test(normalized)) {
return false;
}