Files
noteflow/.rag/13-common-utilities.md
Travis Vasceannie 1ce24cdf7b feat: reorganize Claude hooks and add RAG documentation structure with error handling policies
- Moved all hookify configuration files from `.claude/` to `.claude/hooks/` subdirectory for better organization
- Added four new blocking hooks to prevent common error handling anti-patterns:
  - `block-broad-exception-handler`: Prevents catching generic `Exception` with only logging
  - `block-datetime-now-fallback`: Blocks returning `datetime.now()` as fallback on parse failures to prevent data corruption
  - `block-default
2026-01-15 15:58:06 +00:00

5.5 KiB

NoteFlow Common Utilities & Patterns

Python Utilities

Domain Utilities (domain/utils/)

  • time.pyutc_now() for UTC-aware datetime
  • validation.py — Validation helpers

Config Constants (config/constants/)

  • core.py — DAYS_PER_WEEK, HOURS_PER_DAY, DEFAULT_LLM_TEMPERATURE
  • domain.py — DEFAULT_ANTHROPIC_MODEL, WEBHOOK_EVENT_TYPES
  • errors.py — Error code constants
  • http.py — HTTP-related constants

Domain Constants (domain/constants/)

  • fields.py — Field name constants (EMAIL, PROVIDER, PROJECT_ID)

Settings (config/settings/)

  • _main.py — Main settings (database, ASR, gRPC, storage)
  • _triggers.py — Trigger settings
  • _calendar.py — Calendar provider settings
  • _features.py — Feature flags

Key Env Vars:

  • NOTEFLOW_DATABASE_URL — PostgreSQL connection
  • NOTEFLOW_ASR_MODEL_SIZE — Whisper size
  • NOTEFLOW_GRPC_PORT — gRPC port (default: 50051)
  • NOTEFLOW_MEETINGS_DIR — Audio storage directory
  • NOTEFLOW_RETENTION_DAYS — Retention policy (default: 90)

TypeScript Utilities (client/src/lib/)

Configuration (config/)

  • app-config.ts — App-wide constants
  • defaults.ts — Default values
  • provider-endpoints.ts — AI provider endpoints
  • server.ts — Server connection defaults

Formatting & Time

  • format.ts — Time, duration, GB, percentages
  • time.ts — Time constants (SECONDS_PER_, MS_PER_)
  • timing-constants.ts — Polling intervals, timeouts

Logging

// NEVER use console.log - always use clientlog system
import { addClientLog } from '@/lib/client-logs';
import { debug, errorLog } from '@/lib/debug';

addClientLog({
  level: 'info',
  source: 'app',
  message: 'Event occurred',
  details: 'Context',
});

const log = debug('ComponentName');
log('Debug message', { data });

const logError = errorLog('ComponentName');
logError('Error occurred', error);

Preferences (preferences/)

import { preferences } from '@/lib/preferences';

// Initialize on app start
await preferences.initialize();

// Read/write
const prefs = preferences.get();
await preferences.set('selected_input_device', deviceId);
await preferences.replace({ ...current, theme: 'dark' });

// Subscribe to changes
const unsubscribe = preferences.subscribe((prefs) => {
  console.log('Changed:', prefs);
});

Storage

  • storage-keys.ts — localStorage key constants
  • storage-utils.ts — localStorage helpers

Caching

  • cache/meeting-cache.ts — Meeting cache with TTL & events

Event System

  • tauri-events.ts — Tauri event subscriptions
  • event-emitter.ts — Generic event emitter

Other Utilities

  • utils.ts — Generic TypeScript utilities
  • object-utils.ts — Object manipulation
  • speaker-utils.ts — Speaker ID formatting
  • integration-utils.ts — Integration helpers
  • entity-store.ts — Entity caching for NER
  • crypto.ts — Client-side encryption
  • oauth-utils.ts — OAuth flow helpers

Rust Constants (constants.rs)

pub mod grpc {
    pub const CONNECTION_TIMEOUT: Duration = Duration::from_secs(5);
    pub const REQUEST_TIMEOUT: Duration = Duration::from_secs(300);
    pub const DEFAULT_PORT: u16 = 50051;
    pub const MAX_RETRY_ATTEMPTS: u32 = 3;
}

pub mod audio {
    pub const DEFAULT_SAMPLE_RATE: u32 = 16000;
    pub const DEFAULT_CHANNELS: u32 = 1;
    pub const DEFAULT_BUFFER_SIZE: usize = 1600;  // 100ms
    pub const MIN_DB_LEVEL: f32 = -60.0;
    pub const MAX_DB_LEVEL: f32 = 0.0;
}

pub mod storage {
    pub const MAX_AUDIO_SIZE_BYTES: u64 = 5 * 1024 * 1024 * 1024;  // 5GB
}

pub mod triggers {
    pub const POLL_INTERVAL: Duration = Duration::from_secs(5);
    pub const DEFAULT_SNOOZE_DURATION: Duration = Duration::from_secs(600);
    pub const AUTO_START_THRESHOLD: f32 = 0.7;
}

pub mod crypto {
    pub const KEY_SIZE: usize = 32;  // 256-bit AES
    pub const KEYCHAIN_SERVICE: &str = "NoteFlow";
}

pub mod identity {
    pub const DEFAULT_USER_ID: &str = "local-user";
    pub const DEFAULT_WORKSPACE_ID: &str = "local-workspace";
}

Key Patterns

Python: Protocol-Based Dependency Injection

class MeetingService:
    def __init__(self, uow: UnitOfWork):
        self._uow = uow

    async def create_meeting(self, params: MeetingCreateParams) -> Meeting:
        async with self._uow:
            meeting = Meeting.create(params)
            await self._uow.meetings.add(meeting)
            await self._uow.commit()
            return meeting

TypeScript: Connection-Aware Components

function MyComponent() {
  const { isConnected, isReadOnly } = useConnection();

  if (isReadOnly) return <OfflineBanner />;
  return <ConnectedUI />;
}

Rust: Lazy Initialization

pub struct CryptoManager {
    crypto: OnceLock<Result<CryptoBox>>,
}

impl CryptoManager {
    pub fn get_or_init(&self) -> Result<&CryptoBox> {
        self.crypto.get_or_try_init(CryptoBox::new)
    }
}

Rust: State Access via RwLock

let mut rec = state.recording.write();
*rec = Some(session);

Feature Flags

Flag Default Controls
NOTEFLOW_FEATURE_TEMPLATES_ENABLED true AI templates
NOTEFLOW_FEATURE_PDF_EXPORT_ENABLED true PDF export
NOTEFLOW_FEATURE_NER_ENABLED false Entity extraction
NOTEFLOW_FEATURE_CALENDAR_ENABLED false Calendar sync
NOTEFLOW_FEATURE_WEBHOOKS_ENABLED true Webhooks

Access: get_feature_flags().<flag_name> or get_settings().feature_flags.<flag_name>