Compare commits

..

66 Commits

Author SHA1 Message Date
Matthew Raymer
981920dd7a feat(electron): enhance SQLite operation logging and debugging
WIP: Debugging sqlite-run/dbExec hanging issue

- Add renderer-to-main process log forwarding
- Implement operation tracking with unique IDs
- Add detailed timing and retry logging
- Enhance error capture and formatting
- Move logs to app user data directory
- Add exponential backoff for retries

This commit adds comprehensive logging to help diagnose
why dbExec operations are hanging when sent through the
sqlite-run channel. Changes include:

- Forward all renderer process logs to main process
- Track SQLite operations with unique IDs
- Log operation timing and retry attempts
- Capture detailed error information
- Implement exponential backoff for retries
- Centralize logs in app user data directory

Security:
- Logs are stored in app user data directory
- Sensitive data is sanitized in logs
- Error stacks are properly captured

Testing:
- Manual testing of logging system
- Verify log capture in both processes
- Check log rotation and file sizes

TODO:
- Monitor logs to identify root cause
- Add specific logging for settings table
- Consider connection pooling if needed
2025-06-05 13:28:35 +00:00
Matthew Raymer
d189c39062 chore(linting): more linting and debugging 2025-06-05 10:34:49 +00:00
Matthew Raymer
8edddb1a57 chore(linting): some linting problems fixed 2025-06-05 10:00:14 +00:00
Matthew Raymer
9eb07b3258 fix: improve API server update reliability and logging
- Refactor dbExec in ElectronPlatformService to use proper connection management
- Add comprehensive logging throughout API server update flow
- Fix connection handling in database operations
- Add user feedback notifications for success/failure
- Add verification step after settings update

The main issue was that dbExec wasn't using the same robust connection
management as dbQuery, leading to "SQLite not initialized" errors. Now both
methods use the same connection lifecycle management through enqueueOperation.

Also added detailed logging at each step to help diagnose any future issues:
- AccountViewView component logging
- Database utility operations logging
- Connection state tracking
- Update verification

This should make the API server update more reliable and easier to debug.
2025-06-05 08:44:42 +00:00
Matthew Raymer
e5dffc30ff fix(sqlite): centralize database connection management
- Add proper connection state tracking (disconnected/connecting/connected/error)
- Implement connection promise to prevent race conditions
- Centralize connection lifecycle in getConnection() and releaseConnection()
- Remove redundant queue operations
- Improve error handling and state management

This fixes race conditions where multiple components (main process, renderer,
platform service) were interfering with each other's database operations.
Connection state is now properly tracked and operations are queued correctly.

Fixes: #<issue_number> (if applicable)
2025-06-05 07:37:44 +00:00
Matthew Raymer
0b4e885edd fix(electron): correct SQLite IPC bridge implementation
- Replace generic execute method with specific IPC handlers
- Fix database operations by using proper IPC methods (createConnection, query, run, execute)
- Update type definitions to match actual IPC bridge interface
- Fix "Must provide statements" error by using correct method signatures

This change ensures proper communication between renderer and main processes
for SQLite operations, resolving database initialization and query issues.
2025-06-05 06:52:26 +00:00
Matthew Raymer
b6d9b29720 refactor(sqlite): align database implementation with sacred-sql
BREAKING CHANGE: Removes database encryption in favor of simpler implementation

- Remove encryption from SQLite initialization and connection options
- Change journal mode from WAL to MEMORY to match sacred-sql
- Simplify PRAGMA settings and remove WAL-specific configurations
- Remove secret table and encryption-related migrations
- Update database schema to use non-encrypted storage
- Clean up database initialization process

This change aligns the TimeSafari Electron SQLite implementation with
sacred-sql, improving compatibility and simplifying the database layer.
Existing databases will need to be cleared and recreated due to the
removal of encryption support.

Migration:
1. Delete existing database at ~/Databases/TimeSafari/timesafariSQLite.db
2. Restart application to create fresh database with new schema
2025-06-05 05:37:18 +00:00
Matthew Raymer
b5348e42a7 chore(config): revert encrypted sqlite db 2025-06-05 03:25:09 +00:00
Matthew Raymer
a4fb3eea2d chore(config): add encryption settings for SQLite 2025-06-05 03:15:10 +00:00
Matthew Raymer
5d12c76693 fix(sqlite): enable database encryption in Electron app
The app is failing to initialize encryption because:
- Database is created with 'no-encryption' mode
- Capacitor SQLite plugin's encryption methods are available but unused
- Secret table exists but encryption isn't properly initialized

This commit will:
- Enable encryption in database connection options
- Initialize encryption secret before database open
- Use Capacitor SQLite plugin's encryption methods
- Ensure secret table is properly initialized

This fixes the "No initial encryption supported" error that occurs
when trying to save new identities or access encrypted data.

Technical details:
- Changes connection options to use 'secret' encryption mode
- Adds setEncryptionSecret call before database open
- Maintains existing secret table structure
- Uses Capacitor SQLite plugin's native encryption support
2025-06-05 03:07:47 +00:00
Matthew Raymer
d426f9c4ac refactor(experiment.sh): streamline build process for Capacitor-based Electron app
- Remove all commented-out legacy build steps (TypeScript compilation, AppImage packaging)
- Add Capacitor sync and Electron start sequence
- Update script documentation and dependencies
- Add proper error handling for Capacitor workflow
- Add git command check for capacitor config restoration
- Remove unused AppImage-related functions

This change aligns the build process with our Capacitor-based Electron architecture,
replacing the direct file copying approach with Capacitor's sync mechanism.
2025-06-05 02:27:44 +00:00
340a574325 adjust timeout length for startup 2025-06-04 17:04:31 -06:00
Matthew Raymer
98b3a35e3c refactor: consolidate Electron API type definitions
- Create unified ElectronAPI interface in debug-electron.ts
- Export SQLiteAPI, IPCRenderer, and ElectronEnv interfaces
- Update Window.electron type declarations to use shared interface
- Fix type conflicts between debug-electron.ts and ElectronPlatformService.ts

This change improves type safety and maintainability by centralizing
Electron API type definitions in a single location.
2025-06-04 13:48:27 +00:00
Matthew Raymer
409de21fc4 fix(db): resolve SQLite channel and initialization issues
- Add sqlite-status to valid IPC channels
- Fix SQLite ready signal handling
- Improve database status tracking
- Add proper error handling for status updates
- Keep database connection open during initialization

Technical Details:
- Added sqlite-status to VALID_CHANNELS.invoke list
- Implemented sqlite-status handler with proper verification
- Added database open state verification
- Improved error handling and logging
- Fixed premature database closing

Testing Notes:
- Verify SQLite ready signal is received correctly
- Confirm database stays open after initialization
- Check status updates are processed properly
- Verify error handling for invalid states

Security:
- Validates all IPC channels
- Verifies database state before operations
- Maintains proper connection lifecycle
- Implements proper error boundaries

Author: Matthew Raymer
2025-06-04 13:05:24 +00:00
Matthew Raymer
17c9d32f49 feat(db): temporarily mock dbQuery for connection testing
- Temporarily modified dbQuery to return empty results for testing
- Added detailed logging of attempted queries with timestamps
- Preserved original implementation as commented code for easy restoration
- Helps isolate database connection issues from query execution issues

Testing Notes:
- Database connection and initialization appears successful
- Empty results causing cascading failures in settings and identity
- Router initialization timing needs review
- SQLite timeout error may be false positive

Security Impact:
- No security implications as this is a temporary test change
- Original implementation preserved for quick rollback
- No sensitive data exposed in logs

Related Issues:
- Database connection timing
- Router initialization sequence
- Settings initialization failures
2025-06-04 12:37:11 +00:00
Matthew Raymer
25e4db395a refactor(sqlite): enhance dbQuery with robust connection lifecycle
This commit significantly improves the dbQuery function in ElectronPlatformService
with proper connection lifecycle management and error handling. Key changes:

- Add SQLite availability check before operations
- Implement proper connection lifecycle:
  - Create connection
  - Open database
  - Verify database state
  - Execute query
  - Ensure cleanup
- Enhance error handling:
  - Check SQLite availability
  - Verify IPC renderer
  - Handle database state
  - Proper cleanup in finally block
- Improve logging:
  - Add [dbQuery] tag for better tracing
  - Log all connection lifecycle events
  - Enhanced error logging
- Add type safety:
  - SQLiteQueryResult interface
  - Proper type casting
  - Maintain generic type support

Technical details:
- Add SQLiteQueryResult interface for type safety
- Implement proper connection state verification
- Add comprehensive error messages
- Ensure proper resource cleanup
- Follow same pattern as main.electron.ts

Testing:
- All database operations properly logged
- Connection lifecycle verified
- Error conditions handled
- Resources properly cleaned up

Author: Matthew Raymer
2025-06-04 09:31:08 +00:00
Matthew Raymer
b6ee30892f feat(sqlite): enhance SQLite initialization and IPC handlers
This commit significantly improves SQLite database management and IPC communication
in the TimeSafari Electron app. Key changes include:

- Add new IPC handlers for database lifecycle management:
  - sqlite-open: Open database connections
  - sqlite-close: Close database connections
  - sqlite-is-db-open: Check database connection status
  - get-path: Retrieve database path
  - get-base-path: Get base directory path

- Enhance SQLite initialization with:
  - Improved error handling and recovery mechanisms
  - Detailed logging for all database operations
  - State verification and tracking
  - Proper cleanup of IPC handlers
  - Transaction state management

- Security improvements:
  - Validate all IPC channels
  - Implement proper file permissions (0o755)
  - Add connection state verification
  - Secure error handling and logging

- Performance optimizations:
  - Implement WAL journal mode
  - Configure optimal PRAGMA settings
  - Add connection pooling support
  - Implement retry logic with exponential backoff

Technical details:
- Add SQLiteError class for detailed error tracking
- Implement handler registration tracking
- Add comprehensive logging with operation tagging
- Update preload script with new valid channels
- Add type definitions for all SQLite operations

Testing:
- All handlers include proper error handling
- State verification before operations
- Recovery mechanisms for failed operations
- Logging for debugging and monitoring

Author: Matthew Raymer
2025-06-04 09:10:58 +00:00
Matthew Raymer
b01a450733 debug(ipc): HomeView errors added function level labels noting that we're catching a function level exception but we're also logging it globally. 2025-06-03 14:00:32 +00:00
Matthew Raymer
596f3355bf chore(logging): turn off logToDB since it was blowing up and hiding real errors in noise. 2025-06-03 13:33:08 +00:00
Matthew Raymer
e1f9a6fa08 refactor(sqlite): disable verbose logging in migration system
- Comment out all info and debug logs in sqlite-migrations.ts
- Maintain logging structure for future debugging
- Reduce console output during normal operation
- Keep error handling and logging infrastructure intact

This change reduces noise in the console while maintaining the ability
to re-enable detailed logging for debugging purposes.
2025-06-03 13:28:39 +00:00
Matthew Raymer
340e718199 feat(logging): enhance SQLite logging and IPC handler management
- Add Winston-based structured logging system with:
  - Separate console and file output formats
  - Custom SQLite and migration loggers
  - Configurable log levels and verbosity
  - Log rotation and file management
  - Type-safe logger extensions

- Improve IPC handler management:
  - Add handler registration tracking
  - Implement proper cleanup before re-registration
  - Fix handler registration conflicts
  - Add better error handling for IPC operations

- Add migration logging controls:
  - Configurable via DEBUG_MIGRATIONS env var
  - Reduced console noise while maintaining file logs
  - Structured migration status reporting

Security:
- Add proper log file permissions (0o755)
- Implement log rotation to prevent disk space issues
- Add type safety for all logging operations
- Prevent handler registration conflicts

Dependencies:
- Add winston for enhanced logging
- Remove deprecated @types/winston

This change improves debugging capabilities while reducing console noise
and fixing IPC handler registration issues that could cause database
operation failures.
2025-06-03 13:05:40 +00:00
Matthew Raymer
5d97c98ae8 fix(electron): improve SQLite initialization and timing handling
- Add structured SQLite configuration in main process with separate settings for
  initialization and operations
- Implement proper retry logic with configurable attempts and delays
- Add connection pool management to prevent resource exhaustion
- Reduce initialization timeout from 30s to 10s for faster feedback
- Add proper cleanup of timeouts and resources
- Maintain consistent retry behavior in preload script

This change addresses the cascade of SQLite timeout errors seen in the logs
by implementing proper timing controls and resource management. The main
process now handles initialization more robustly with configurable retries,
while the preload script maintains its existing retry behavior for
compatibility.

Security Impact:
- No security implications
- Improves application stability
- Prevents resource exhaustion

Testing:
- Verify SQLite initialization completes within new timeout
- Confirm retry behavior works as expected
- Check that connection pool limits are respected
- Ensure proper cleanup of resources
2025-06-03 12:25:36 +00:00
Matthew Raymer
ec74fff892 refactor: enhance SQLite error handling and type safety
Current State:
- SQLite initialization completes successfully
- API exposure and IPC bridge working correctly
- Type definitions and interfaces properly implemented
- Enhanced error handling with specific error codes
- Comprehensive logging system in place

Critical Issue Identified:
SQLite initialization timeout causing cascading failures:
- Components attempting database operations before initialization complete
- Error logging failing due to database unavailability
- Multiple components affected (HomeView, AccountView, ImageMethodDialog)
- User experience impacted with cache clear prompts

Changes Made:
- Added proper TypeScript interfaces for SQLite operations
- Enhanced SQLiteError class with error codes and context
- Implemented input validation utilities
- Added detailed logging with timestamps
- Improved error categorization and handling
- Added result structure validation

Type Definitions Added:
- SQLiteConnectionOptions
- SQLiteQueryOptions
- SQLiteExecuteOptions
- SQLiteResult
- SQLiteEchoResult

Error Codes Implemented:
- SQLITE_BUSY
- SQLITE_NO_TABLE
- SQLITE_SYNTAX_ERROR
- SQLITE_PLUGIN_UNAVAILABLE
- SQLITE_INVALID_OPTIONS
- SQLITE_MIGRATION_FAILED
- SQLITE_INVALID_RESULT
- SQLITE_ECHO_MISMATCH

Next Steps:
1. Implement initialization synchronization
2. Add component loading states
3. Improve error recovery mechanisms
4. Add proper error boundaries
5. Implement fallback UI states

Affected Files:
- electron/src/rt/sqlite-init.ts
- src/types/electron.d.ts

Note: This is a transitional commit. While the structure and type safety
are improved, the initialization timeout issue needs to be addressed in
the next commit to prevent cascading failures.

Testing Required:
- SQLite initialization timing
- Component loading sequences
- Error recovery scenarios
- Database operation retries
2025-06-03 04:31:27 +00:00
Matthew Raymer
1e88c0e26f refactor(electron): enhance SQLite integration and debug logging
Current Status:
- SQLite plugin successfully initializes in main process
- Preload script and context bridge working correctly
- IPC handlers for SQLite operations not registered
- Type definitions out of sync with implementation

Changes Made:
- Added comprehensive debug logging in preload script
- Implemented retry logic for SQLite operations (3 attempts, 1s delay)
- Added proper type definitions for SQLite connection options
- Defined strict channel validation for IPC communication
- Enhanced error handling and logging throughout

Type Definitions Updates:
- Aligned ElectronAPI interface with actual implementation
- Added proper typing for SQLite operations
- Structured IPC renderer interface with correct method signatures

Next Steps:
- Register missing IPC handlers in main process
- Update type definitions to match implementation
- Add proper error recovery for SQLite operations
- Address Content Security Policy warnings

Affected Files:
- electron/src/preload.ts
- src/types/electron.d.ts
- src/utils/debug-electron.ts
- src/services/platforms/ElectronPlatformService.ts

Note: This is a transitional commit. While the structure is improved,
database operations are not yet functional due to missing IPC handlers.
2025-06-03 04:18:39 +00:00
Matthew Raymer
3ec2364394 refactor: update electron preload script and type definitions
This commit updates the Electron preload script and type definitions to improve
SQLite integration and IPC communication. The changes include:

- Enhanced preload script (electron/src/preload.ts):
  * Added detailed logging for SQLite operations and IPC communication
  * Implemented retry logic for SQLite operations (3 attempts, 1s delay)
  * Added proper type definitions for SQLite connection options
  * Defined strict channel validation for IPC communication
  * Improved error handling and logging throughout

- Updated type definitions (src/types/electron.d.ts):
  * Aligned ElectronAPI interface with actual implementation
  * Added proper typing for all SQLite operations
  * Added environment variables (platform, isDev)
  * Structured IPC renderer interface with proper method signatures

Current Status:
- Preload script initializes successfully
- SQLite availability check works (returns true)
- SQLite ready signal is properly received
- Database operations are failing with two types of errors:
  1. "CapacitorSQLite not available" during initialization
  2. "Cannot read properties of undefined" for SQLite methods

Next Steps:
- Verify context bridge exposure in renderer process
- Check main process SQLite handlers
- Debug database initialization
- Address Content Security Policy warning

Affected Files:
- Modified: electron/src/preload.ts
- Modified: src/types/electron.d.ts

Note: This is a transitional commit. While the preload script and type
definitions are now properly structured, database operations are not yet
functional. Further debugging and fixes are required to resolve the
SQLite integration issues.
2025-06-03 04:06:24 +00:00
Matthew Raymer
8b215c909d refactor: remove electron preload script and update database handling
The preload script (src/electron/preload.js) was removed as part of a refactor to
separate web and electron builds. This script was previously responsible for:

- Secure IPC communication between electron main and renderer processes
- SQLite database access bridge for the renderer process
- Context isolation and API exposure for electron-specific features

Current state:
- Web app builds successfully without preload script
- Electron builds fail due to missing preload script
- SQLite initialization works in main process but renderer can't access it
- Database operations fail with "Cannot read properties of undefined"

This commit is a breaking change for electron builds. The preload script will need
to be recreated to restore electron database functionality.

Affected files:
- Deleted: src/electron/preload.js
- Modified: src/main.electron.ts (removed DatabaseManager import)
- Modified: src/utils/logger.ts (simplified logging implementation)
- Modified: src/types/electron.d.ts (updated ElectronAPI interface)
- Modified: src/types/global.d.ts (updated window.electron type definition)

Next steps:
- Recreate preload script with proper SQLite bridge
- Update electron build configuration
- Restore database access in renderer process
2025-06-03 03:48:36 +00:00
Matthew Raymer
91a1c05473 fix(electron): consolidate SQLite initialization and IPC handling
- Consolidate preload script with secure IPC bridge and channel validation
- Ensure single initialization path in main process
- Add robust error handling and user feedback
- Fix race conditions in window creation and SQLite ready signal

Current state:
- SQLite initializes successfully in main process
- IPC bridge is established and events are transmitted
- Window creation and loading sequence is correct
- Renderer receives ready signal and mounts app
- Database operations still fail in renderer due to connection issues

Known issues:
- SQLite proxy not properly initialized in renderer
- Database connection not established in renderer
- Error logging attempts to use database before ready
- Connection state management needs improvement

This commit represents a stable point where IPC communication
is working but database operations need to be fixed.
2025-06-03 02:52:17 +00:00
Matthew Raymer
66929d9b14 refactor(electron): WIP - use window.CapacitorSQLite API for all DB ops in ElectronPlatformService
- Remove connection object and connection pool logic
- Call all database methods directly on window.CapacitorSQLite with db name
- Refactor migrations, queries, and exec to match Capacitor SQLite Electron API
- Ensure preload script exposes both window.electron and window.CapacitorSQLite
- Fixes runtime errors related to missing query/run methods on connection
- Improves security and cross-platform compatibility

Co-authored-by: Matthew Raymer
2025-06-02 13:17:48 +00:00
Matthew Raymer
1e63ddcb6e feat(sqlite): enhance migration system and database initialization
- Add robust logging and error tracking to migration system
- Implement idempotent migrations with transaction safety
- Add detailed progress tracking and state verification
- Improve error handling with recoverable/non-recoverable states
- Add migration version validation and sequential checks
- Implement proper rollback handling with error recording
- Add table state verification and debugging
- Fix migration SQL parsing and parameter handling
- Add connection pool management and retry logic
- Add proper transaction isolation and state tracking

The migration system now provides:
- Atomic transactions per migration
- Automatic rollback on failure
- Detailed error logging and context
- State verification before/after operations
- Proper connection management
- Idempotent operations for safety

This commit improves database reliability and makes debugging
easier while maintaining proper process isolation. The changes
are focused on the migration system and do not require
restructuring the existing ElectronPlatformService architecture.

Technical details:
- Added MigrationError interface for better error tracking
- Added logMigrationProgress helper for consistent logging
- Added debugTableState for verification
- Added executeWithRetry for connection resilience
- Added validateMigrationVersions for safety
- Enhanced SQL parsing with better error handling
- Added proper transaction state management
- Added connection pool with retry logic
- Added detailed logging throughout migration process

Note: This commit addresses the database initialization issues
while maintaining the current architecture. Further improvements
to the ElectronPlatformService initialization will be handled
in a separate commit to maintain clear separation of concerns.
2025-06-02 10:00:41 +00:00
Matthew Raymer
51f5755f5c Merge branch 'elec-tweak' into sql-absurd-sql-further 2025-06-02 03:29:22 +00:00
Matthew Raymer
e5a3d622b6 Merge branch 'elec-tweak' of ssh://173.199.124.46:222/trent_larson/crowd-funder-for-time-pwa into elec-tweak 2025-06-02 03:26:57 +00:00
Matthew Raymer
a6edcd6269 feat(db): add secure secret generation and initial data setup
Add proper secret generation using Node's crypto module and initial data setup
for the electron environment. This commit:

- Implements secure random secret generation using crypto.randomBytes()
- Adds initial data migrations (002) with:
  - Secret table with cryptographically secure random key
  - Settings table with default API server
  - Contacts, logs, and temp tables
- Improves SQL parameter handling for migrations
- Adds proper transaction safety and rollback support
- Includes comprehensive logging and error handling

Security:
- Uses Node's crypto module for secure random generation
- Implements proper base64 encoding for secrets
- Maintains transaction safety for all operations

Testing:
- Verified database structure via sqlite3 CLI
- Confirmed successful migration execution
- Validated initial data insertion
- Checked index creation and constraints

Note: This is a temporary solution for secret storage until a more
secure storage mechanism is implemented.
2025-06-02 03:19:09 +00:00
Matthew Raymer
b7b6be5831 fix(sqlite): resolve duplicate table creation in migrations
Split initial schema into two sequential migrations to prevent duplicate
table creation and improve migration clarity.

Changes:
- Separate initial schema into two distinct migrations:
  * 001_initial_accounts (v1): Create accounts table & index
  * 002_secret_and_settings (v2): Create remaining tables (secret, settings, contacts, logs, temp)
- Add version conflict detection to prevent duplicate migration versions
- Ensure migrations are sequential (no gaps)
- Update rollback scripts to only drop relevant tables

Technical Details:
- Add validateMigrationVersions() to check for:
  * Duplicate version numbers
  * Sequential version ordering
  * Gaps in version numbers
- Validate migrations both at definition time and runtime
- Update schema_version tracking to reflect new versioning

Testing:
- Verified no duplicate table creation
- Confirmed migrations run in correct order
- Validated rollback procedures
- Checked version conflict detection
2025-06-02 02:48:08 +00:00
Matthew Raymer
cbaca0304d feat(sqlite): implement initial database migrations
Add robust SQLite migration system with initial schema for TimeSafari desktop app.
Includes comprehensive error handling, transaction safety, and detailed logging.

Key Changes:
- Add migration system with version tracking and rollback support
- Implement initial schema with accounts, secret, settings, contacts tables
- Configure SQLite PRAGMAs for optimal performance and reliability
- Add detailed logging and state verification
- Set up WAL journal mode and connection pooling

Technical Details:
- Use @capacitor-community/sqlite for native SQLite integration
- Implement atomic transactions per migration
- Add SQL validation and parsing utilities
- Configure PRAGMAs:
  * foreign_keys = ON
  * journal_mode = WAL
  * synchronous = NORMAL
  * temp_store = MEMORY
  * page_size = 4096
  * cache_size = 2000
  * busy_timeout = 15000
  * wal_autocheckpoint = 1000

Note: Current version has duplicate migration v1 entries that need to be
addressed in a follow-up commit to ensure proper versioning.

Testing:
- Verified migrations run successfully
- Confirmed table creation and index setup
- Validated transaction safety and rollback
- Checked logging and error handling
2025-06-02 02:30:58 +00:00
59d711bd90 make fixes to help my Mac build electron 2025-06-01 11:24:52 -06:00
Matthew Raymer
c355de6e33 Merge branch 'sql-absurd-sql-further' of ssh://173.199.124.46:222/trent_larson/crowd-funder-for-time-pwa into sql-absurd-sql-further 2025-06-01 12:37:19 +00:00
Matthew Raymer
28c114a2c7 fix(sqlite): resolve migration issues and enhance documentation
This commit addresses critical SQLite migration issues and significantly improves
code documentation and error handling. The changes include both functional fixes
and comprehensive documentation updates.

Key Changes:
- Fix migration name binding issue by switching to direct SQL statements
- Add proper SQL value escaping to prevent injection
- Implement comprehensive error handling and recovery
- Add detailed logging throughout migration process
- Enhance transaction safety and state verification

Documentation Updates:
- Add comprehensive module-level documentation
- Document all major functions with JSDoc
- Add security and performance considerations
- Include detailed process flows
- Document error handling strategies

Technical Details:
- Switch from parameterized queries to direct SQL for schema_version updates
- Add proper string escaping for SQL values
- Implement state verification before/after operations
- Add detailed debug logging for migration process
- Enhance error recovery with proper state tracking

Security:
- Add SQL injection prevention
- Implement proper value escaping
- Add transaction isolation
- Enhance state verification
- Add error sanitization

Performance:
- Optimize transaction handling
- Implement efficient SQL parsing
- Add connection pooling
- Reduce locking contention
- Optimize statement reuse

Testing:
- Verified migration process with fresh database
- Tested error recovery scenarios
- Validated transaction safety
- Confirmed proper state tracking
- Verified logging completeness

Breaking Changes: None
Migration Required: Yes (database will be recreated)

Author: Matthew Raymer
2025-06-01 12:36:57 +00:00
dabfe33fbe add Python dependency for electron on Mac 2025-06-01 06:34:32 -06:00
d8f2587d1c fix some errors and correct recent type duplications & bloat 2025-05-31 22:36:15 -06:00
Matthew Raymer
3946a8a27a fix(database): improve SQLite connection handling and initialization
- Add connection readiness check to ensure proper initialization
- Implement retry logic for connection attempts
- Fix database path handling to use consistent location
- Add proper error handling for connection state
- Ensure WAL journal mode for better performance
- Consolidate database initialization logic

The changes address several issues:
- Prevent "query is not a function" errors by waiting for connection readiness
- Ensure database is properly initialized before use
- Maintain consistent database path across application
- Improve error handling and connection state management
- Add proper cleanup of database connections

Technical details:
- Database path: ~/.local/share/TimeSafari/timesafariSQLite.db
- Journal mode: WAL (Write-Ahead Logging)
- Connection options: non-encrypted, read-write mode
- Tables: users, time_entries, time_goals, time_goal_entries, schema_version

This commit improves database reliability and prevents connection-related errors
that were occurring during application startup.
2025-06-01 03:47:20 +00:00
4c40b80718 rename script files that would fail in the prebuild step 2025-05-31 16:39:37 -06:00
74989c2b64 fix linting 2025-05-31 16:25:22 -06:00
7e17b41444 rename a js config file to avoid an error running lint 2025-05-31 16:24:10 -06:00
83acb028c7 fix more logic for tests 2025-05-31 16:20:41 -06:00
Matthew Raymer
786f07e067 feat(electron): Implement SQLite database initialization with proper logging
- Add comprehensive logging for database operations
- Implement proper database path handling and permissions
- Set up WAL journal mode and PRAGMA configurations
- Create initial database schema with tables and triggers
- Add retry logic for database operations
- Implement proper error handling and state management

Current state:
- Database initialization works in main process
- Connection creation succeeds with proper permissions
- Schema creation and table setup complete
- Logging system fully implemented
- Known issue: Property name mismatch between main process and renderer
  causing read-only mode conflicts (to be fixed in next commit)

Technical details:
- Uses WAL journal mode for better concurrency
- Implements proper file permissions checking
- Sets up foreign key constraints
- Creates tables: users, time_entries, time_goals, time_goal_entries
- Adds automatic timestamp triggers
- Implements proper connection lifecycle management

Security:
- Proper file permissions (755 for directory)
- No hardcoded credentials
- Proper error handling and logging
- Safe file path handling

Author: Matthew Raymer
2025-05-31 13:56:14 +00:00
Matthew Raymer
710cc1683c fix(sqlite): Standardize connection options and improve error handling
Changes to sqlite-init.ts:
- Standardized connection options format between main and renderer processes
- Added explicit mode: 'rwc' to force read-write-create mode
- Added connection registration verification
- Added detailed logging of actual file paths
- Added journal mode verification to detect read-only state
- Removed redundant PRAGMA settings (now handled in main process)
- Added more detailed error reporting for connection failures

Security:
- Ensures consistent read-write permissions across processes
- Verifies database is not opened in read-only mode
- Maintains proper file permissions (644) and directory permissions (755)

Testing:
- Verified connection creation in both main and renderer processes
- Confirmed journal mode is set correctly
- Validated connection registration
- Tested error handling for invalid states

Author: Matthew Raymer
2025-05-31 13:03:05 +00:00
Matthew Raymer
ebef5d6c8d feat(sqlite): Initialize database with complete schema and PRAGMAs
Initial database setup with:
- Created database at /home/matthew/Databases/TimeSafari/timesafariSQLite.db
- Set optimized PRAGMAs for performance and safety:
  * WAL journal mode for better concurrency
  * Foreign key constraints enabled
  * Normal synchronous mode
  * Memory temp store
  * 4KB page size
  * 2000 page cache (8MB)
- Created core tables:
  * schema_version (for migration tracking)
  * users (for user management)
  * time_entries (for time tracking)
  * time_goals (for goal setting)
  * time_goal_entries (for goal tracking)
- Added automatic timestamp triggers for:
  * users.updated_at
  * time_entries.updated_at
  * time_goals.updated_at
- Fixed connection handling to work with plugin's undefined return pattern
- Added rich logging throughout initialization process

Security:
- Database created with proper permissions (644)
- Directory permissions set to 755
- No encryption (as per requirements)
- Foreign key constraints enabled for data integrity

Testing:
- Verified table creation
- Confirmed schema version tracking
- Validated connection registration
- Tested WAL mode activation

Author: Matthew Raymer
2025-05-31 12:54:55 +00:00
Matthew Raymer
43ea7ee610 Merge branch 'sql-absurd-sql-further' of ssh://173.199.124.46:222/trent_larson/crowd-funder-for-time-pwa into sql-absurd-sql-further 2025-05-31 12:19:32 +00:00
Matthew Raymer
57191df416 feat(sqlite): Database file creation working, connection pending
- Successfully creates database file using plugin's open() method
- Directory permissions and path handling verified working
- Plugin initialization and echo test passing
- Database file created at /home/matthew/Databases/TimeSafari/timesafariSQLite.db

Key findings:
- createConnection() returns undefined but doesn't error
- open() silently creates the database file
- Connection retrieval still needs work (getDatabaseConnectionOrThrowError fails)
- Plugin structure confirmed: both class and default export available

Next steps:
- Refine connection handling after database creation
- Add connection state verification
- Consider adding retry logic for connection retrieval

Technical details:
- Using CapacitorSQLite from @capacitor-community/sqlite/electron
- Database path: /home/matthew/Databases/TimeSafari/timesafariSQLite.db
- Directory permissions: 755 (rwxr-xr-x)
- Plugin version: 6.x (Capacitor 6+ compatible)
2025-05-31 12:17:58 +00:00
644593a5f4 fix linting 2025-05-30 21:12:41 -06:00
Matthew Raymer
900c2521c7 WIP: Improve SQLite initialization and error handling
- Implement XDG Base Directory Specification for data storage
  - Use $XDG_DATA_HOME (defaults to ~/.local/share) for data files
  - Add proper directory permissions (700) for security
  - Fallback to ~/.timesafari if XDG paths fail

- Add graceful degradation for SQLite failures
  - Allow app to boot even if SQLite initialization fails
  - Track and expose initialization errors via IPC
  - Add availability checks to all SQLite operations
  - Improve error reporting and logging

- Security improvements
  - Set secure permissions (700) on data directories
  - Verify directory permissions on existing paths
  - Add proper error handling for permission issues

TODO:
- Fix database creation
- Add retry logic for initialization
- Add reinitialization capability
- Add more detailed error reporting
- Consider fallback storage options
2025-05-30 14:01:24 +00:00
Matthew Raymer
182cff2b16 fix(typescript): resolve linter violations and improve type safety
- Remove unused isDev variable
- Add proper type annotations for event handlers
- Add explicit Promise<void> return type for loadIndexHtml
- Use unknown type for error parameters instead of any
- Fix event handler parameters by prefixing unused params with underscore
- Improve error handling type safety throughout the file

This commit improves type safety and removes unused code while maintaining
existing functionality. All TypeScript linter violations have been addressed
without changing the core behavior of the application.

Database paths are still broken here.

Security Impact: None - changes are type-level only
Testing: No functional changes, existing tests should pass
2025-05-30 09:30:34 +00:00
Matthew Raymer
3b4ef908f3 feat(electron): improve window and database initialization
- Make database initialization non-blocking to prevent app crashes

- Add proper window lifecycle management and error handling

- Implement retry logic for index.html loading

- Add detailed logging for debugging

- Fix type safety issues in error handling

- Add proper cleanup on window close

WIP: Database path resolution still needs fixing

- Current issue: Path conflict between ~/.local/share and ~/.config

- Database connection failing with invalid response

- Multiple connection attempts occurring

This commit improves app stability but database connectivity needs to be addressed in a follow-up commit.
2025-05-30 09:10:01 +00:00
Matthew Raymer
a5a9e15ece WIP: Refactor Electron SQLite initialization and database path handling
- Add logic in main process to resolve and create the correct database directory and file path using Electron's app, path, and fs modules
- Pass absolute dbPath to CapacitorSQLite plugin for reliable database creation
- Add extensive logging for debugging database location, permissions, and initialization
- Remove redundant open() call after createConnection in Electron platform service
- Add IPC handlers for essential SQLite operations (echo, createConnection, execute, query, closeConnection, isAvailable)
- Improve error handling and logging throughout initialization and IPC
- Still investigating database file creation and permissions issues
2025-05-30 08:16:31 +00:00
Matthew Raymer
a6d8f0eb8a fix(electron): assign sqlitePlugin globally and improve error logging
- Assign CapacitorSQLite instance to the global sqlitePlugin variable so it is accessible in IPC handlers.
- Enhance error logging in the IPC handler to include JSON stringification and stack trace for better debugging.
- Reveal that the generic .handle() method is not available on the plugin, clarifying the next steps for correct IPC wiring.
2025-05-30 06:01:56 +00:00
Matthew Raymer
3997a88b44 fix: rename postcss.config.js to .cjs for ES module compatibility
- Added "type": "module" to package.json to support ES module imports for Electron SQLite
- Renamed postcss.config.js to postcss.config.cjs to maintain CommonJS syntax
- This ensures build tools can properly load the PostCSS configuration
2025-05-30 05:10:26 +00:00
5eeeae32c6 fix some incorrect logic & things AI hallucinated 2025-05-29 19:36:35 -06:00
Matthew Raymer
d9895086e6 experiment(electron): different vite build script for web application 2025-05-29 13:09:36 +00:00
Matthew Raymer
fb8d1cb8b2 fix(electron): add null check for devToolsWebContents to prevent TypeScript error
- Ensures devToolsWebContents is not null before calling focus() after opening DevTools in detached mode.
- Prevents runtime and linter errors in Electron main process.
2025-05-29 12:18:04 +00:00
Matthew Raymer
70c0edbed0 fix: SQLite plugin initialization in Electron main process
- Changed from direct plugin usage to SQLiteConnection pattern
- Matches how platform services use the SQLite plugin
- Removed handle() method dependency
- Added proper method routing in IPC handler

The app now launches without initialization errors. Next steps:
- Test actual SQLite operations (createConnection, query, etc.)
- Verify database creation and access
- Add error handling for database operations
2025-05-29 10:18:07 +00:00
Matthew Raymer
55cc08d675 chore: linting 2025-05-29 09:33:29 +00:00
Matthew Raymer
688a5be76e Merge branch 'sql-absurd-sql-further' of ssh://173.199.124.46:222/trent_larson/crowd-funder-for-time-pwa into sql-absurd-sql-further 2025-05-29 09:28:01 +00:00
Matthew Raymer
014341f320 fix(electron): simplify SQLite plugin initialization
- Remove worker thread approach in favor of direct plugin initialization
- Initialize CapacitorSQLiteElectron in main process
- Set up IPC handler to forward SQLite operations
- Remove unused worker files and build config

This reverts to a simpler, more reliable approach for SQLite in Electron,
using the plugin as intended in the main process.
2025-05-29 09:27:47 +00:00
Matthew Raymer
1d5e062c76 fix(electron): app loads 2025-05-29 07:24:20 +00:00
Matthew Raymer
2c5c15108a debug(electron): missing main.ts 2025-05-29 07:06:11 +00:00
Matthew Raymer
26df0fb671 debug(electron): app index loads but problem with preload script 2025-05-29 07:05:23 +00:00
531 changed files with 27050 additions and 79506 deletions

View File

@@ -1,310 +0,0 @@
# Cursor Markdown Ruleset for TimeSafari Documentation
## Overview
This ruleset enforces consistent markdown formatting standards across all project
documentation, ensuring readability, maintainability, and compliance with
markdownlint best practices.
## General Formatting Standards
### Line Length
- **Maximum line length**: 80 characters
- **Exception**: Code blocks (JSON, shell, TypeScript, etc.) - no line length
enforcement
- **Rationale**: Ensures readability across different screen sizes and terminal
widths
### Blank Lines
- **Headings**: Must be surrounded by blank lines above and below
- **Lists**: Must be surrounded by blank lines above and below
- **Code blocks**: Must be surrounded by blank lines above and below
- **Maximum consecutive blank lines**: 1 (no multiple blank lines)
- **File start**: No blank lines at the beginning of the file
- **File end**: Single newline character at the end
### Whitespace
- **No trailing spaces**: Remove all trailing whitespace from lines
- **No tabs**: Use spaces for indentation
- **Consistent indentation**: 2 spaces for list items and nested content
## Heading Standards
### Format
- **Style**: ATX-style headings (`#`, `##`, `###`, etc.)
- **Case**: Title case for general headings
- **Code references**: Use backticks for file names and technical terms
-`### Current package.json Scripts`
-`### Current Package.json Scripts`
### Hierarchy
- **H1 (#)**: Document title only
- **H2 (##)**: Major sections
- **H3 (###)**: Subsections
- **H4 (####)**: Sub-subsections
- **H5+**: Avoid deeper nesting
## List Standards
### Unordered Lists
- **Marker**: Use `-` (hyphen) consistently
- **Indentation**: 2 spaces for nested items
- **Blank lines**: Surround lists with blank lines
### Ordered Lists
- **Format**: `1.`, `2.`, `3.` (sequential numbering)
- **Indentation**: 2 spaces for nested items
- **Blank lines**: Surround lists with blank lines
### Task Lists
- **Format**: `- [ ]` for incomplete, `- [x]` for complete
- **Use case**: Project planning, checklists, implementation tracking
## Code Block Standards
### Fenced Code Blocks
- **Syntax**: Triple backticks with language specification
- **Languages**: `json`, `bash`, `typescript`, `javascript`, `yaml`, `markdown`
- **Blank lines**: Must be surrounded by blank lines above and below
- **Line length**: No enforcement within code blocks
### Inline Code
- **Format**: Single backticks for inline code references
- **Use case**: File names, commands, variables, properties
## Special Content Standards
### JSON Examples
```json
{
"property": "value",
"nested": {
"property": "value"
}
}
```
### Shell Commands
```bash
# Command with comment
npm run build:web
# Multi-line command
VITE_GIT_HASH=`git log -1 --pretty=format:%h` \
vite build --config vite.config.web.mts
```
### TypeScript Examples
```typescript
// Function with JSDoc
/**
* Get environment configuration
* @param env - Environment name
* @returns Environment config object
*/
const getEnvironmentConfig = (env: string) => {
switch (env) {
case 'prod':
return { /* production settings */ };
default:
return { /* development settings */ };
}
};
```
## File Structure Standards
### Document Header
```markdown
# Document Title
**Author**: Matthew Raymer
**Date**: YYYY-MM-DD
**Status**: 🎯 **STATUS** - Brief description
## Overview
Brief description of the document's purpose and scope.
```
### Section Organization
1. **Overview/Introduction**
2. **Current State Analysis**
3. **Implementation Plan**
4. **Technical Details**
5. **Testing & Validation**
6. **Next Steps**
## Markdownlint Configuration
### Required Rules
```json
{
"MD013": { "code_blocks": false },
"MD012": true,
"MD022": true,
"MD031": true,
"MD032": true,
"MD047": true,
"MD009": true
}
```
### Rule Explanations
- **MD013**: Line length (disabled for code blocks)
- **MD012**: No multiple consecutive blank lines
- **MD022**: Headings should be surrounded by blank lines
- **MD031**: Fenced code blocks should be surrounded by blank lines
- **MD032**: Lists should be surrounded by blank lines
- **MD047**: Files should end with a single newline
- **MD009**: No trailing spaces
## Validation Commands
### Check Single File
```bash
npx markdownlint docs/filename.md
```
### Check All Documentation
```bash
npx markdownlint docs/
```
### Auto-fix Common Issues
```bash
# Remove trailing spaces
sed -i 's/[[:space:]]*$//' docs/filename.md
# Remove multiple blank lines
sed -i '/^$/N;/^\n$/D' docs/filename.md
# Add newline at end if missing
echo "" >> docs/filename.md
```
## Common Patterns
### Implementation Plans
```markdown
## Implementation Plan
### Phase 1: Foundation (Day 1)
#### 1.1 Component Setup
- [ ] Create new component file
- [ ] Add basic structure
- [ ] Implement core functionality
#### 1.2 Configuration
- [ ] Update configuration files
- [ ] Add environment variables
- [ ] Test configuration loading
```
### Status Tracking
```markdown
**Status**: ✅ **COMPLETE** - All phases finished
**Progress**: 75% (15/20 components)
**Next**: Ready for testing phase
```
### Performance Metrics
```markdown
#### 📊 Performance Metrics
- **Build Time**: 2.3 seconds (50% faster than baseline)
- **Bundle Size**: 1.2MB (30% reduction)
- **Success Rate**: 100% (no failures in 50 builds)
```
## Enforcement
### Pre-commit Hooks
- Run markdownlint on all changed markdown files
- Block commits with linting violations
- Auto-fix common issues when possible
### CI/CD Integration
- Include markdownlint in build pipeline
- Generate reports for documentation quality
- Fail builds with critical violations
### Team Guidelines
- All documentation PRs must pass markdownlint
- Use provided templates for new documents
- Follow established patterns for consistency
## Templates
### New Document Template
```markdown
# Document Title
**Author**: Matthew Raymer
**Date**: YYYY-MM-DD
**Status**: 🎯 **PLANNING** - Ready for Implementation
## Overview
Brief description of the document's purpose and scope.
## Current State
Description of current situation or problem.
## Implementation Plan
### Phase 1: Foundation
- [ ] Task 1
- [ ] Task 2
## Next Steps
1. **Review and approve plan**
2. **Begin implementation**
3. **Test and validate**
---
**Status**: Ready for implementation
**Priority**: Medium
**Estimated Effort**: X days
**Dependencies**: None
**Stakeholders**: Development team
```
---
**Last Updated**: 2025-07-09
**Version**: 1.0
**Maintainer**: Matthew Raymer

View File

@@ -7,13 +7,13 @@ alwaysApply: true
## 1. Platform Support Matrix
| Feature | Web (PWA) | Capacitor (Mobile) | Electron (Desktop) |
|---------|-----------|-------------------|-------------------|
| QR Code Scanning | WebInlineQRScanner | @capacitor-mlkit/barcode-scanning | Not Implemented |
| Deep Linking | URL Parameters | App URL Open Events | Not Implemented |
| File System | Limited (Browser API) | Capacitor Filesystem | Electron fs |
| Camera Access | MediaDevices API | Capacitor Camera | Not Implemented |
| Platform Detection | Web APIs | Capacitor.isNativePlatform() | process.env checks |
| Feature | Web (PWA) | Capacitor (Mobile) | Electron (Desktop) | PyWebView (Desktop) |
|---------|-----------|-------------------|-------------------|-------------------|
| QR Code Scanning | WebInlineQRScanner | @capacitor-mlkit/barcode-scanning | Not Implemented | Not Implemented |
| Deep Linking | URL Parameters | App URL Open Events | Not Implemented | Not Implemented |
| File System | Limited (Browser API) | Capacitor Filesystem | Electron fs | PyWebView Python Bridge |
| Camera Access | MediaDevices API | Capacitor Camera | Not Implemented | Not Implemented |
| Platform Detection | Web APIs | Capacitor.isNativePlatform() | process.env checks | process.env checks |
## 2. Project Structure
@@ -42,6 +42,7 @@ src/
├── main.common.ts # Shared initialization
├── main.capacitor.ts # Mobile entry
├── main.electron.ts # Electron entry
├── main.pywebview.ts # PyWebView entry
└── main.web.ts # Web/PWA entry
```
@@ -51,7 +52,9 @@ root/
├── vite.config.common.mts # Shared config
├── vite.config.capacitor.mts # Mobile build
├── vite.config.electron.mts # Electron build
── vite.config.web.mts # Web/PWA build
── vite.config.pywebview.mts # PyWebView build
├── vite.config.web.mts # Web/PWA build
└── vite.config.utils.mts # Build utilities
```
## 3. Service Architecture
@@ -65,7 +68,8 @@ services/
├── platforms/ # Platform-specific services
│ ├── WebPlatformService.ts
│ ├── CapacitorPlatformService.ts
── ElectronPlatformService.ts
── ElectronPlatformService.ts
│ └── PyWebViewPlatformService.ts
└── factory/ # Service factories
└── PlatformServiceFactory.ts
```
@@ -149,7 +153,7 @@ export function createBuildConfig(mode: string) {
return {
define: {
'process.env.VITE_PLATFORM': JSON.stringify(mode),
// PWA is automatically enabled for web platforms via build configuration
'process.env.VITE_PWA_ENABLED': JSON.stringify(!isNative),
__IS_MOBILE__: JSON.stringify(isCapacitor),
__USE_QR_READER__: JSON.stringify(!isCapacitor)
}
@@ -163,7 +167,8 @@ export function createBuildConfig(mode: string) {
# Build commands from package.json
"build:web": "vite build --config vite.config.web.mts",
"build:capacitor": "vite build --config vite.config.capacitor.mts",
"build:electron": "vite build --config vite.config.electron.mts"
"build:electron": "vite build --config vite.config.electron.mts",
"build:pywebview": "vite build --config vite.config.pywebview.mts"
```
## 6. Testing Strategy

View File

@@ -1,10 +0,0 @@
---
description: rules used while developing
globs:
alwaysApply: true
---
✅ use system date command to timestamp all interactions with accurate date and time
✅ python script files must always have a blank line at their end
✅ remove whitespace at the end of lines
✅ use npm run lint-fix to check for warnings
✅ do not use npm run dev let me handle running and supplying feedback

View File

@@ -1,14 +0,0 @@
---
alwaysApply: true
---
# Directive for Documentation Generation
1. Produce a **small, focused set of documents** rather than an overwhelming volume.
2. Ensure the content is **maintainable and worth preserving**, so that humans
are motivated to keep it up to date.
3. Prioritize **educational value**: the documents must clearly explain the
workings of the system.
4. Avoid **shallow, generic, or filler explanations** often found in
AI-generated documentation.
5. Aim for **clarity, depth, and usefulness**, so readers gain genuine understanding.
6. Always check the local system date to determine current date.

View File

@@ -1,6 +0,0 @@
---
description:
globs:
alwaysApply: true
---
All references in the codebase to Dexie apply only to migration from IndexedDb to Sqlite and will be deprecated in future versions.

View File

@@ -1,332 +0,0 @@
---
globs: *.md
alwaysApply: false
---
# Cursor Markdown Ruleset for TimeSafari Documentation
## Overview
This ruleset enforces consistent markdown formatting standards across all project
documentation, ensuring readability, maintainability, and compliance with
markdownlint best practices.
## General Formatting Standards
### Line Length
- **Maximum line length**: 80 characters
- **Exception**: Code blocks (JSON, shell, TypeScript, etc.) - no line length
enforcement
- **Rationale**: Ensures readability across different screen sizes and terminal
widths
### Blank Lines
- **Headings**: Must be surrounded by blank lines above and below
- **Lists**: Must be surrounded by blank lines above and below
- **Code blocks**: Must be surrounded by blank lines above and below
- **Maximum consecutive blank lines**: 1 (no multiple blank lines)
- **File start**: No blank lines at the beginning of the file
- **File end**: Single newline character at the end
### Whitespace
- **No trailing spaces**: Remove all trailing whitespace from lines
- **No tabs**: Use spaces for indentation
- **Consistent indentation**: 2 spaces for list items and nested content
## Heading Standards
### Format
- **Style**: ATX-style headings (`#`, `##`, `###`, etc.)
- **Case**: Title case for general headings
- **Code references**: Use backticks for file names and technical terms
- ✅ `### Current package.json Scripts`
- ❌ `### Current Package.json Scripts`
### Hierarchy
- **H1 (#)**: Document title only
- **H2 (##)**: Major sections
- **H3 (###)**: Subsections
- **H4 (####)**: Sub-subsections
- **H5+**: Avoid deeper nesting
## List Standards
### Unordered Lists
- **Marker**: Use `-` (hyphen) consistently
- **Indentation**: 2 spaces for nested items
- **Blank lines**: Surround lists with blank lines
### Ordered Lists
- **Format**: `1.`, `2.`, `3.` (sequential numbering)
- **Indentation**: 2 spaces for nested items
- **Blank lines**: Surround lists with blank lines
### Task Lists
- **Format**: `- [ ]` for incomplete, `- [x]` for complete
- **Use case**: Project planning, checklists, implementation tracking
## Code Block Standards
### Fenced Code Blocks
- **Syntax**: Triple backticks with language specification
- **Languages**: `json`, `bash`, `typescript`, `javascript`, `yaml`, `markdown`
- **Blank lines**: Must be surrounded by blank lines above and below
- **Line length**: No enforcement within code blocks
### Inline Code
- **Format**: Single backticks for inline code references
- **Use case**: File names, commands, variables, properties
## Special Content Standards
### JSON Examples
```json
{
"property": "value",
"nested": {
"property": "value"
}
}
```
### Shell Commands
```bash
# Command with comment
npm run build:web
# Multi-line command
VITE_GIT_HASH=`git log -1 --pretty=format:%h` \
vite build --config vite.config.web.mts
```
### TypeScript Examples
```typescript
// Function with JSDoc
/**
* Get environment configuration
* @param env - Environment name
* @returns Environment config object
*/
const getEnvironmentConfig = (env: string) => {
switch (env) {
case 'prod':
return { /* production settings */ };
default:
return { /* development settings */ };
}
};
```
## File Structure Standards
### Document Header
```markdown
# Document Title
**Author**: Matthew Raymer
**Date**: YYYY-MM-DD
**Status**: 🎯 **STATUS** - Brief description
## Overview
Brief description of the document's purpose and scope.
```
### Section Organization
1. **Overview/Introduction**
2. **Current State Analysis**
3. **Implementation Plan**
4. **Technical Details**
5. **Testing & Validation**
6. **Next Steps**
## Markdownlint Configuration
### Required Rules
```json
{
"MD013": { "code_blocks": false },
"MD012": true,
"MD022": true,
"MD031": true,
"MD032": true,
"MD047": true,
"MD009": true
}
```
### Rule Explanations
- **MD013**: Line length (disabled for code blocks)
- **MD012**: No multiple consecutive blank lines
- **MD022**: Headings should be surrounded by blank lines
- **MD031**: Fenced code blocks should be surrounded by blank lines
- **MD032**: Lists should be surrounded by blank lines
- **MD047**: Files should end with a single newline
- **MD009**: No trailing spaces
## Validation Commands
### Check Single File
```bash
npx markdownlint docs/filename.md
```
### Check All Documentation
```bash
npx markdownlint docs/
```
### Auto-fix Common Issues
```bash
# Remove trailing spaces
sed -i 's/[[:space:]]*$//' docs/filename.md
# Remove multiple blank lines
sed -i '/^$/N;/^\n$/D' docs/filename.md
# Add newline at end if missing
echo "" >> docs/filename.md
```
## Common Patterns
### Implementation Plans
```markdown
## Implementation Plan
### Phase 1: Foundation (Day 1)
#### 1.1 Component Setup
- [ ] Create new component file
- [ ] Add basic structure
- [ ] Implement core functionality
#### 1.2 Configuration
- [ ] Update configuration files
- [ ] Add environment variables
- [ ] Test configuration loading
```
### Status Tracking
```markdown
**Status**: ✅ **COMPLETE** - All phases finished
**Progress**: 75% (15/20 components)
**Next**: Ready for testing phase
```
### Performance Metrics
```markdown
#### 📊 Performance Metrics
- **Build Time**: 2.3 seconds (50% faster than baseline)
- **Bundle Size**: 1.2MB (30% reduction)
- **Success Rate**: 100% (no failures in 50 builds)
```
## Enforcement
### Pre-commit Hooks
- Run markdownlint on all changed markdown files
- Block commits with linting violations
- Auto-fix common issues when possible
### CI/CD Integration
- Include markdownlint in build pipeline
- Generate reports for documentation quality
- Fail builds with critical violations
### Team Guidelines
- All documentation PRs must pass markdownlint
- Use provided templates for new documents
- Follow established patterns for consistency
## Templates
### New Document Template
```markdown
# Document Title
**Author**: Matthew Raymer
**Date**: YYYY-MM-DD
**Status**: 🎯 **PLANNING** - Ready for Implementation
## Overview
Brief description of the document's purpose and scope.
## Current State
Description of current situation or problem.
## Implementation Plan
### Phase 1: Foundation
- [ ] Task 1
- [ ] Task 2
## Next Steps
1. **Review and approve plan**
2. **Begin implementation**
3. **Test and validate**
---
**Status**: Ready for implementation
**Priority**: Medium
**Estimated Effort**: X days
**Dependencies**: None
**Stakeholders**: Development team
```
---
**Last Updated**: 2025-07-09
**Version**: 1.0
**Maintainer**: Matthew Raymer
### Heading Uniqueness
- **Rule**: No duplicate heading content at the same level
- **Scope**: Within a single document
- **Rationale**: Maintains clear document structure and navigation
- **Example**:
```markdown
## Features ✅
### Authentication
### Authorization
## Features ❌ (Duplicate heading)
### Security
### Performance
```

View File

@@ -1,96 +1,70 @@
---
description:
globs:
description:
globs:
alwaysApply: true
---
---
description:
globs:
alwaysApply: true
---
# Time Safari Context
## Project Overview
Time Safari is an application designed to foster community building through gifts,
gratitude, and collaborative projects. The app should make it extremely easy and
intuitive for users of any age and capability to recognize contributions, build
trust networks, and organize collective action. It is built on services that
preserve privacy and data sovereignty.
Time Safari is an application designed to foster community building through gifts, gratitude, and collaborative projects. The app should make it extremely easy and intuitive for users of any age and capability to recognize contributions, build trust networks, and organize collective action. It is built on services that preserve privacy and data sovereignty.
The ultimate goals of Time Safari are two-fold:
1. **Connect** Make it easy, rewarding, and non-threatening for people to
connect with others who have similar interests, and to initiate activities
together. This helps people accomplish and learn from other individuals in
less-structured environments; moreover, it helps them discover who they want
to continue to support and with whom they want to maintain relationships.
1. **Connect** Make it easy, rewarding, and non-threatening for people to connect with others who have similar interests, and to initiate activities together. This helps people accomplish and learn from other individuals in less-structured environments; moreover, it helps them discover who they want to continue to support and with whom they want to maintain relationships.
2. **Reveal** Widely advertise the great support and rewards that are being
given and accepted freely, especially non-monetary ones. Using visuals and text,
display the kind of impact that gifts are making in the lives of others. Also
show useful and engaging reports of project statistics and personal accomplishments.
2. **Reveal** Widely advertise the great support and rewards that are being given and accepted freely, especially non-monetary ones. Using visuals and text, display the kind of impact that gifts are making in the lives of others. Also show useful and engaging reports of project statistics and personal accomplishments.
## Core Approaches
Time Safari should help everyday users build meaningful connections and organize
collective efforts by:
Time Safari should help everyday users build meaningful connections and organize collective efforts by:
1. **Recognizing Contributions**: Creating permanent, verifiable records of gifts
and contributions people give to each other and their communities.
1. **Recognizing Contributions**: Creating permanent, verifiable records of gifts and contributions people give to each other and their communities.
2. **Facilitating Collaboration**: Making it ridiculously easy for people to ask
for or propose help on projects and interests that matter to them.
2. **Facilitating Collaboration**: Making it ridiculously easy for people to ask for or propose help on projects and interests that matter to them.
3. **Building Trust Networks**: Enabling users to maintain their network and activity
visibility. Developing reputation through verified contributions and references,
which can be selectively shown to others outside the network.
3. **Building Trust Networks**: Enabling users to maintain their network and activity visibility. Developing reputation through verified contributions and references, which can be selectively shown to others outside the network.
4. **Preserving Privacy**: Ensuring personal identifiers are only shared with
explicitly authorized contacts, allowing private individuals including children
to participate safely.
4. **Preserving Privacy**: Ensuring personal identifiers are only shared with explicitly authorized contacts, allowing private individuals including children to participate safely.
5. **Engaging Content**: Displaying people's records in compelling stories, and
highlighting those projects that are lifting people's lives long-term, both in
physical support and in emotional-spiritual-creative thriving.
5. **Engaging Content**: Displaying people's records in compelling stories, and highlighting those projects that are lifting people's lives long-term, both in physical support and in emotional-spiritual-creative thriving.
## Technical Foundation
This application is built on a privacy-preserving claims architecture (via
endorser.ch) with these key characteristics:
This application is built on a privacy-preserving claims architecture (via endorser.ch) with these key characteristics:
- **Decentralized Identifiers (DIDs)**: User identities are based on public/private
key pairs stored on their devices
- **Cryptographic Verification**: All claims and confirmations are
cryptographically signed
- **User-Controlled Visibility**: Users explicitly control who can see their
identifiers and data
- **Merkle-Chained Claims**: Claims are cryptographically chained for verification
and integrity
- **Native and Web App**: Works on Capacitor (iOS, Android), Desktop (Electron
and CEFPython), and web browsers
- **Decentralized Identifiers (DIDs)**: User identities are based on public/private key pairs stored on their devices
- **Cryptographic Verification**: All claims and confirmations are cryptographically signed
- **User-Controlled Visibility**: Users explicitly control who can see their identifiers and data
- **Merkle-Chained Claims**: Claims are cryptographically chained for verification and integrity
- **Native and Web App**: Works on Capacitor (iOS, Android), Desktop (Electron and CEFPython), and web browsers
## User Journey
The typical progression of usage follows these stages:
1. **Gratitude & Recognition**: Users begin by expressing and recording gratitude
for gifts received, building a foundation of acknowledgment.
1. **Gratitude & Recognition**: Users begin by expressing and recording gratitude for gifts received, building a foundation of acknowledgment.
2. **Project Proposals**: Users propose projects and ideas, reaching out to connect
with others who share similar interests.
2. **Project Proposals**: Users propose projects and ideas, reaching out to connect with others who share similar interests.
3. **Action Triggers**: Offers of help serve as triggers and motivations to execute
proposed projects, moving from ideas to action.
3. **Action Triggers**: Offers of help serve as triggers and motivations to execute proposed projects, moving from ideas to action.
## Context for LLM Development
When developing new functionality for Time Safari, consider these design principles:
1. **Accessibility First**: Features should be usable by non-technical users with
minimal learning curve.
1. **Accessibility First**: Features should be usable by non-technical users with minimal learning curve.
2. **Privacy by Design**: All features must respect user privacy and data sovereignty.
3. **Progressive Enhancement**: Core functionality should work across all devices,
with richer experiences where supported.
3. **Progressive Enhancement**: Core functionality should work across all devices, with richer experiences where supported.
4. **Voluntary Collaboration**: The system should enable but never coerce participation.
@@ -98,40 +72,31 @@ with richer experiences where supported.
6. **Network Effects**: Consider how features scale as more users join the platform.
7. **Low Resource Requirements**: The system should be lightweight enough to run
on inexpensive devices users already own.
7. **Low Resource Requirements**: The system should be lightweight enough to run on inexpensive devices users already own.
## Use Cases to Support
LLM development should focus on enhancing these key use cases:
1. **Community Building**: Tools that help people find others with shared
interests and values.
1. **Community Building**: Tools that help people find others with shared interests and values.
2. **Project Coordination**: Features that make it easy to propose collaborative
projects and to submit suggestions and offers to existing ones.
2. **Project Coordination**: Features that make it easy to propose collaborative projects and to submit suggestions and offers to existing ones.
3. **Reputation Building**: Methods for users to showcase their contributions
and reliability, in contexts where they explicitly reveal that information.
3. **Reputation Building**: Methods for users to showcase their contributions and reliability, in contexts where they explicitly reveal that information.
4. **Governance Experimentation**: Features that facilitate decision-making and
collective governance.
4. **Governance Experimentation**: Features that facilitate decision-making and collective governance.
## Constraints
When developing new features, be mindful of these constraints:
1. **Privacy Preservation**: User identifiers must remain private except when
explicitly shared.
1. **Privacy Preservation**: User identifiers must remain private except when explicitly shared.
2. **Platform Limitations**: Features must work within the constraints of the target
app platforms, while aiming to leverage the best platform technology available.
2. **Platform Limitations**: Features must work within the constraints of the target app platforms, while aiming to leverage the best platform technology available.
3. **Endorser API Limitations**: Backend features are constrained by the endorser.ch
API capabilities.
3. **Endorser API Limitations**: Backend features are constrained by the endorser.ch API capabilities.
4. **Performance on Low-End Devices**: The application should remain performant
on older/simpler devices.
4. **Performance on Low-End Devices**: The application should remain performant on older/simpler devices.
5. **Offline-First When Possible**: Key functionality should work offline when feasible.
@@ -151,14 +116,12 @@ on older/simpler devices.
## Project Architecture
- The application must work on web browser, PWA (Progressive Web Application),
desktop via Electron, and mobile via Capacitor
- The application must work on web browser, PWA (Progressive Web Application), desktop via Electron, and mobile via Capacitor
- Building for each platform is managed via Vite
## Core Development Principles
### DRY development
- **Code Reuse**
- Extract common functionality into utility functions
- Create reusable components for UI patterns
@@ -214,24 +177,14 @@ on older/simpler devices.
- Use shared test configurations
- Create reusable test helpers
- Implement consistent test patterns
- F.I.R.S.T. (for Unit Tests)
F Fast
I Independent
R Repeatable
S Self-validating
T Timely
### SOLID Principles
- **Single Responsibility**: Each class/component should have only one reason to
change
- **Single Responsibility**: Each class/component should have only one reason to change
- Components should focus on one specific feature (e.g., QR scanning, DID management)
- Services should handle one type of functionality (e.g., platform services,
crypto services)
- Services should handle one type of functionality (e.g., platform services, crypto services)
- Utilities should provide focused helper functions
- **Open/Closed**: Software entities should be open for extension but closed for
modification
- **Open/Closed**: Software entities should be open for extension but closed for modification
- Use interfaces for service definitions
- Implement plugin architecture for platform-specific features
- Allow component behavior extension through props and events
@@ -252,7 +205,6 @@ on older/simpler devices.
- Implement factory patterns for component creation
### Law of Demeter
- Components should only communicate with immediate dependencies
- Avoid chaining method calls (e.g., `this.service.getUser().getProfile().getName()`)
- Use mediator patterns for complex component interactions
@@ -260,7 +212,6 @@ on older/simpler devices.
- Keep component communication through defined events and props
### Composition over Inheritance
- Prefer building components through composition
- Use mixins for shared functionality
- Implement feature toggles through props
@@ -268,7 +219,6 @@ on older/simpler devices.
- Use service composition for complex features
### Interface Segregation
- Define clear interfaces for services
- Keep component APIs minimal and focused
- Split large interfaces into smaller, specific ones
@@ -276,7 +226,6 @@ on older/simpler devices.
- Implement role-based interfaces for different use cases
### Fail Fast
- Validate inputs early in the process
- Use TypeScript strict mode
- Implement comprehensive error handling
@@ -284,7 +233,6 @@ on older/simpler devices.
- Use assertions for development-time validation
### Principle of Least Astonishment
- Follow Vue.js conventions consistently
- Use familiar naming patterns
- Implement predictable component behaviors
@@ -292,7 +240,6 @@ on older/simpler devices.
- Keep UI interactions intuitive
### Information Hiding
- Encapsulate implementation details
- Use private class members
- Implement proper access modifiers
@@ -300,7 +247,6 @@ on older/simpler devices.
- Use TypeScript's access modifiers effectively
### Single Source of Truth
- Use Pinia for state management
- Maintain one source for user data
- Centralize configuration management
@@ -308,9 +254,23 @@ on older/simpler devices.
- Implement proper state synchronization
### Principle of Least Privilege
- Implement proper access control
- Use minimal required permissions
- Follow privacy-by-design principles
- Restrict component access to necessary data
- Implement proper authentication/authorization
### Continuous Integration/Continuous Deployment (CI/CD)
- Automated testing on every commit
- Consistent build process across platforms
- Automated deployment pipelines
- Quality gates for code merging
- Environment-specific configurations
This expanded documentation provides:
1. Clear principles for development
2. Practical implementation guidelines
3. Real-world examples
4. TypeScript integration
5. Best practices for Time Safari

View File

@@ -1,34 +0,0 @@
---
alwaysApply: true
---
# Rules for peaceful co-existence with developers
do not add or commit for the user; let him control that process
the content of commit messages should be from the files awaiting staging
and those which have been staged. use the differences in those files
to inform the content of the commit message
always preview changes and commit message to use and allow me to copy and paste
✅ Preferred Commit Message Format
Short summary in the first line (concise and high-level).
Avoid long commit bodies unless truly necessary.
✅ Valued Content in Commit Messages
Specific fixes or features.
Symptoms or problems that were fixed.
Notes about tests passing or TS/linting errors being resolved (briefly).
❌ Avoid in Commit Messages
Vague terms: “improved”, “enhanced”, “better” — especially from AI.
Minor changes: small doc tweaks, one-liners, cleanup, or lint fixes.
Redundant blurbs: repeated across files or too generic.
Multiple overlapping purposes in a single commit — prefer narrow, focused commits.
Long explanations of what can be deduced from good in-line code comments.
Guiding Principle
Let code and inline documentation speak for themselves. Use commits to highlight what isn't obvious from reading the code.

267
.cursor/rules/wa-sqlite.mdc Normal file
View File

@@ -0,0 +1,267 @@
---
description:
globs:
alwaysApply: true
---
# wa-sqlite Usage Guide
## Table of Contents
- [1. Overview](#1-overview)
- [2. Installation](#2-installation)
- [3. Basic Setup](#3-basic-setup)
- [3.1 Import and Initialize](#31-import-and-initialize)
- [3.2 Basic Database Operations](#32-basic-database-operations)
- [4. Virtual File Systems (VFS)](#4-virtual-file-systems-vfs)
- [4.1 Available VFS Options](#41-available-vfs-options)
- [4.2 Using a VFS](#42-using-a-vfs)
- [5. Best Practices](#5-best-practices)
- [5.1 Error Handling](#51-error-handling)
- [5.2 Transaction Management](#52-transaction-management)
- [5.3 Prepared Statements](#53-prepared-statements)
- [6. Performance Considerations](#6-performance-considerations)
- [7. Common Issues and Solutions](#7-common-issues-and-solutions)
- [8. TypeScript Support](#8-typescript-support)
## 1. Overview
wa-sqlite is a WebAssembly build of SQLite that enables SQLite database operations in web browsers and JavaScript environments. It provides both synchronous and asynchronous builds, with support for custom virtual file systems (VFS) for persistent storage.
## 2. Installation
```bash
npm install wa-sqlite
# or
yarn add wa-sqlite
```
## 3. Basic Setup
### 3.1 Import and Initialize
```javascript
// Choose one of these imports based on your needs:
// - wa-sqlite.mjs: Synchronous build
// - wa-sqlite-async.mjs: Asynchronous build (required for async VFS)
// - wa-sqlite-jspi.mjs: JSPI-based async build (experimental, Chromium only)
import SQLiteESMFactory from 'wa-sqlite/dist/wa-sqlite.mjs';
import * as SQLite from 'wa-sqlite';
async function initDatabase() {
// Initialize SQLite module
const module = await SQLiteESMFactory();
const sqlite3 = SQLite.Factory(module);
// Open database (returns a Promise)
const db = await sqlite3.open_v2('myDatabase');
return { sqlite3, db };
}
```
### 3.2 Basic Database Operations
```javascript
async function basicOperations() {
const { sqlite3, db } = await initDatabase();
try {
// Create a table
await sqlite3.exec(db, `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE
)
`);
// Insert data
await sqlite3.exec(db, `
INSERT INTO users (name, email)
VALUES ('John Doe', 'john@example.com')
`);
// Query data
const results = [];
await sqlite3.exec(db, 'SELECT * FROM users', (row, columns) => {
results.push({ row, columns });
});
return results;
} finally {
// Always close the database when done
await sqlite3.close(db);
}
}
```
## 4. Virtual File Systems (VFS)
### 4.1 Available VFS Options
wa-sqlite provides several VFS implementations for persistent storage:
1. **IDBBatchAtomicVFS** (Recommended for general use)
- Uses IndexedDB with batch atomic writes
- Works in all contexts (Window, Worker, Service Worker)
- Supports WAL mode
- Best performance with `PRAGMA synchronous=normal`
2. **IDBMirrorVFS**
- Keeps files in memory, persists to IndexedDB
- Works in all contexts
- Good for smaller databases
3. **OPFS-based VFS** (Origin Private File System)
- Various implementations available:
- AccessHandlePoolVFS
- OPFSAdaptiveVFS
- OPFSCoopSyncVFS
- OPFSPermutedVFS
- Better performance but limited to Worker contexts
### 4.2 Using a VFS
```javascript
import { IDBBatchAtomicVFS } from 'wa-sqlite/src/examples/IDBBatchAtomicVFS.js';
import SQLiteESMFactory from 'wa-sqlite/dist/wa-sqlite-async.mjs';
import * as SQLite from 'wa-sqlite';
async function initDatabaseWithVFS() {
const module = await SQLiteESMFactory();
const sqlite3 = SQLite.Factory(module);
// Register VFS
const vfs = await IDBBatchAtomicVFS.create('myApp', module);
sqlite3.vfs_register(vfs, true);
// Open database with VFS
const db = await sqlite3.open_v2('myDatabase');
// Configure for better performance
await sqlite3.exec(db, 'PRAGMA synchronous = normal');
await sqlite3.exec(db, 'PRAGMA journal_mode = WAL');
return { sqlite3, db };
}
```
## 5. Best Practices
### 5.1 Error Handling
```javascript
async function safeDatabaseOperation() {
const { sqlite3, db } = await initDatabase();
try {
await sqlite3.exec(db, 'SELECT * FROM non_existent_table');
} catch (error) {
if (error.code === SQLite.SQLITE_ERROR) {
console.error('SQL error:', error.message);
} else {
console.error('Database error:', error);
}
} finally {
await sqlite3.close(db);
}
}
```
### 5.2 Transaction Management
```javascript
async function transactionExample() {
const { sqlite3, db } = await initDatabase();
try {
await sqlite3.exec(db, 'BEGIN TRANSACTION');
// Perform multiple operations
await sqlite3.exec(db, 'INSERT INTO users (name) VALUES (?)', ['Alice']);
await sqlite3.exec(db, 'INSERT INTO users (name) VALUES (?)', ['Bob']);
await sqlite3.exec(db, 'COMMIT');
} catch (error) {
await sqlite3.exec(db, 'ROLLBACK');
throw error;
} finally {
await sqlite3.close(db);
}
}
```
### 5.3 Prepared Statements
```javascript
async function preparedStatementExample() {
const { sqlite3, db } = await initDatabase();
try {
// Prepare statement
const stmt = await sqlite3.prepare(db, 'SELECT * FROM users WHERE id = ?');
// Execute with different parameters
await sqlite3.bind(stmt, 1, 1);
while (await sqlite3.step(stmt) === SQLite.SQLITE_ROW) {
const row = sqlite3.row(stmt);
console.log(row);
}
// Reset and reuse
await sqlite3.reset(stmt);
await sqlite3.bind(stmt, 1, 2);
// ... execute again
await sqlite3.finalize(stmt);
} finally {
await sqlite3.close(db);
}
}
```
## 6. Performance Considerations
1. **VFS Selection**
- Use IDBBatchAtomicVFS for general-purpose applications
- Consider OPFS-based VFS for better performance in Worker contexts
- Use MemoryVFS for temporary databases
2. **Configuration**
- Set appropriate page size (default is usually fine)
- Use WAL mode for better concurrency
- Consider `PRAGMA synchronous=normal` for better performance
- Adjust cache size based on your needs
3. **Concurrency**
- Use transactions for multiple operations
- Be aware of VFS-specific concurrency limitations
- Consider using Web Workers for heavy database operations
## 7. Common Issues and Solutions
1. **Database Locking**
- Use appropriate transaction isolation levels
- Implement retry logic for busy errors
- Consider using WAL mode
2. **Storage Limitations**
- Be aware of browser storage quotas
- Implement cleanup strategies
- Monitor database size
3. **Cross-Context Access**
- Use appropriate VFS for your context
- Consider message passing for cross-context communication
- Be aware of storage access limitations
## 8. TypeScript Support
wa-sqlite includes TypeScript definitions. The main types are:
```typescript
type SQLiteCompatibleType = number | string | Uint8Array | Array<number> | bigint | null;
interface SQLiteAPI {
open_v2(filename: string, flags?: number, zVfs?: string): Promise<number>;
exec(db: number, sql: string, callback?: (row: any[], columns: string[]) => void): Promise<number>;
close(db: number): Promise<number>;
// ... other methods
}
```
## Additional Resources
- [Official GitHub Repository](https://github.com/rhashimoto/wa-sqlite)
- [Online Demo](https://rhashimoto.github.io/wa-sqlite/demo/)
- [API Reference](https://rhashimoto.github.io/wa-sqlite/docs/)
- [FAQ](https://github.com/rhashimoto/wa-sqlite/issues?q=is%3Aissue+label%3Afaq+)
- [Discussion Forums](https://github.com/rhashimoto/wa-sqlite/discussions)

View File

@@ -1,171 +0,0 @@
# TimeSafari Docker Ignore File
# Author: Matthew Raymer
# Description: Excludes unnecessary files from Docker build context
#
# Benefits:
# - Faster build times
# - Smaller build context
# - Reduced image size
# - Better security (excludes sensitive files)
# Dependencies
node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Build outputs
# dist - Allow dist directory for Docker builds (contains pre-built assets)
dist-*
build
*.tsbuildinfo
# Development files
.git
.gitignore
README.md
CHANGELOG.md
CONTRIBUTING.md
BUILDING.md
LICENSE
# IDE and editor files
.vscode
.idea
*.swp
*.swo
*~
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Dependency directories
jspm_packages/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# Test files
test-playwright
test-playwright-results
test-results
test-scripts
# Documentation
doc
# Scripts (keep only what's needed for build)
scripts/test-*.sh
scripts/*.js
scripts/README.md
# Platform-specific files
android
ios
electron
# Docker files (avoid recursive copying)
Dockerfile*
docker-compose*
.dockerignore
# CI/CD files
.github
.gitlab-ci.yml
.travis.yml
.circleci
# Temporary files
tmp
temp
# Backup files
*.bak
*.backup
# Archive files
*.tar
*.tar.gz
*.zip
*.rar
# Certificate files
*.pem
*.key
*.crt
*.p12
# Configuration files that might contain secrets
*.secrets
secrets.json
config.local.json

View File

@@ -1,9 +1,8 @@
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
# iOS doesn't like spaces in the app title.
TIME_SAFARI_APP_TITLE="TimeSafari_Dev"
VITE_APP_SERVER=http://localhost:8080
VITE_APP_SERVER=http://localhost:3000
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production).
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000

79
.gitignore vendored
View File

@@ -51,81 +51,6 @@ vendor/
# Build logs
build_logs/
# PWA icon files generated by capacitor-assets
icons
android/app/src/main/assets/public
android/app/src/main/res
*.log
# Generated Android assets and resources (should be generated during build)
android/app/src/main/assets/public/
# Generated Android resources (icons, splash screens, etc.)
android/app/src/main/res/drawable*/
android/app/src/main/res/mipmap*/
android/app/src/main/res/values/ic_launcher_background.xml
# Keep these Android configuration files in version control:
# - android/app/src/main/assets/capacitor.plugins.json
# - android/app/src/main/res/values/strings.xml
# - android/app/src/main/res/values/styles.xml
# - android/app/src/main/res/layout/activity_main.xml
# - android/app/src/main/res/xml/config.xml
# - android/app/src/main/res/xml/file_paths.xml
sql-wasm.wasm
# Temporary and generated files
temp.*
*.tmp
*.temp
*.bak
*.cache
git.diff.*
*.har
# Development artifacts
dev-dist/
*.map
# OS generated files
Thumbs.db
ehthumbs.db
Desktop.ini
# Capacitor build outputs and generated files
android/app/build/
android/capacitor-cordova-android-plugins/build/
ios/App/App/public/assets/
ios/App/App/build/
ios/App/build/
# Capacitor build artifacts (covered by android/app/build/ above)
# Keep these Capacitor files in version control:
# - capacitor.config.json (root, electron, ios)
# - src/main.capacitor.ts
# - vite.config.capacitor.mts
# - android/capacitor.settings.gradle
# - android/app/capacitor.build.gradle
# - android/app/src/main/assets/capacitor.plugins.json
# Electron build outputs and generated files
electron/build/
electron/app/
electron/dist/
electron/out/
# Keep these Electron files in version control:
# - electron/src/preload.ts (source)
# - electron/src/index.ts (source)
# - electron/src/setup.ts (source)
# - electron/package.json
# - electron/electron-builder.config.json
# - electron/build-packages.sh
# - electron/live-runner.js
# - electron/resources/electron-publisher-custom.js
# Gradle cache files
android/.gradle/file-system.probe
android/.gradle/caches/
coverage

View File

@@ -1 +0,0 @@
{"MD013": {"code_blocks": false}}

1
.npmrc
View File

@@ -1 +0,0 @@
@jsr:registry=https://npm.jsr.io

File diff suppressed because it is too large Load Diff

View File

@@ -5,46 +5,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.3] - 2025.07.12
### Changed
- Photo is pinned to profile mode
### Fixed
- Deep link URLs (and other prod settings)
- Error in BVC begin view
## [Unreleased]
### Changed
- Photo is pinned to profile mode
## [1.0.2] - 2025.06.20 - 276e0a741bc327de3380c4e508cccb7fee58c06d
### Added
- Version on feed title
## [1.0.1] - 2025.06.20
### Added
- Allow a user to block someone else's content from view
## [1.0.0] - 2025.06.20 - 5aa693de6337e5dbb278bfddc6bd39094bc14f73
### Added
- Web-oriented migration from IndexedDB to SQLite
## [0.5.8]
### Added
- /deep-link/ path for URLs that are shared with people
### Changed
- External links now go to /deep-link/...
- Feed visuals now have arrow imagery from giver to receiver
## [0.4.7]
### Fixed
- Cameras everywhere
### Changed
- IndexedDB -> SQLite
## [0.4.5] - 2025.02.23

View File

@@ -1,170 +1,36 @@
# TimeSafari Docker Build
# Author: Matthew Raymer
# Description: Multi-stage Docker build for TimeSafari web application
#
# Build Process:
# 1. Base stage: Node.js with build dependencies
# 2. Builder stage: Copy pre-built web assets from host
# 3. Production stage: Nginx server with optimized assets
#
# Note: Web assets are built on the host using npm scripts before Docker build
#
# Security Features:
# - Non-root user execution
# - Minimal attack surface with Alpine Linux
# - Multi-stage build to reduce image size
# - No build dependencies in final image
#
# Usage:
# IMPORTANT: Build web assets first, then build Docker image
#
# Using npm scripts (recommended):
# Production: npm run build:web:docker:prod
# Test: npm run build:web:docker:test
# Development: npm run build:web:docker
#
# Manual workflow:
# 1. Build web assets: npm run build:web:build -- --mode production
# 2. Build Docker: docker build -t timesafari:latest .
#
# Note: For development, use npm run build:web directly (no Docker needed)
#
# Build Arguments:
# BUILD_MODE: development, test, or production (default: production)
# NODE_ENV: node environment (default: production)
#
# Environment Variables:
# NODE_ENV: Build environment (development/production)
# BUILD_MODE: Build mode for asset selection (development/test/production)
#
# Build Context:
# This Dockerfile is designed to work when the build context is set to
# ./crowd-funder-for-time-pwa from the parent directory (where docker-compose.yml is located)
# Build stage
FROM node:22-alpine3.20 AS builder
# =============================================================================
# BASE STAGE - Common dependencies and setup
# =============================================================================
FROM node:22-alpine3.20 AS base
# Install build dependencies
# Install system dependencies for build process
RUN apk add --no-cache \
bash \
git \
python3 \
py3-pip \
py3-setuptools \
make \
g++ \
gcc \
&& rm -rf /var/cache/apk/*
# Create non-root user for security
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
RUN apk add --no-cache bash git python3 py3-pip py3-setuptools make g++ gcc
# Set working directory
WORKDIR /app
# Copy package files for dependency installation
# Note: These files are in the project root (crowd-funder-for-time-pwa directory)
# Copy package files
COPY package*.json ./
# Install dependencies with security audit
RUN npm ci --only=production --audit --fund=false && \
npm audit fix --audit-level=moderate || true
# Install dependencies
RUN npm ci
# =============================================================================
# BUILDER STAGE - Copy pre-built assets
# =============================================================================
FROM base AS builder
# Copy source code
COPY . .
# Define build arguments with defaults
ARG BUILD_MODE=production
ARG NODE_ENV=production
# Build the application
RUN npm run build:web
# Set environment variables from build arguments
ENV BUILD_MODE=${BUILD_MODE}
ENV NODE_ENV=${NODE_ENV}
# Copy pre-built assets from host
# Note: dist/ directory is in the project root (crowd-funder-for-time-pwa directory)
COPY dist/ ./dist/
# Verify build output exists
RUN ls -la dist/ || (echo "Build output not found in dist/ directory" && exit 1)
# =============================================================================
# PRODUCTION STAGE - Nginx server
# =============================================================================
FROM nginx:alpine AS production
# Define build arguments for production stage
ARG BUILD_MODE=production
ARG NODE_ENV=production
# Set environment variables
ENV BUILD_MODE=${BUILD_MODE}
ENV NODE_ENV=${NODE_ENV}
# Install security updates and clean cache
RUN apk update && \
apk upgrade && \
apk add --no-cache \
curl \
&& rm -rf /var/cache/apk/*
# Use existing nginx user from base image (nginx user and group already exist)
# No need to create new user as nginx:alpine already has nginx user
# Copy main nginx configuration
COPY docker/nginx.conf /etc/nginx/nginx.conf
# Copy production nginx configuration
COPY docker/default.conf /etc/nginx/conf.d/default.conf
# Production stage
FROM nginx:alpine
# Copy built assets from builder stage
COPY --from=builder --chown=nginx:nginx /app/dist /usr/share/nginx/html
COPY --from=builder /app/dist /usr/share/nginx/html
# Create necessary directories with proper permissions
RUN mkdir -p /var/cache/nginx /var/log/nginx /tmp && \
chown -R nginx:nginx /var/cache/nginx /var/log/nginx /tmp && \
chown -R nginx:nginx /usr/share/nginx/html
# Switch to non-root user
USER nginx
# Copy nginx configuration if needed
# COPY nginx.conf /etc/nginx/conf.d/default.conf
# Expose port 80
EXPOSE 80
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# Start nginx with proper signal handling
CMD ["nginx", "-g", "daemon off;"]
# =============================================================================
# TEST STAGE - For test environment testing
# =============================================================================
FROM production AS test
# Define build arguments for test stage
ARG BUILD_MODE=test
ARG NODE_ENV=test
# Set environment variables
ENV BUILD_MODE=${BUILD_MODE}
ENV NODE_ENV=${NODE_ENV}
# Copy test-specific nginx configuration
COPY docker/staging.conf /etc/nginx/conf.d/default.conf
# Expose port 80
EXPOSE 80
# Health check for staging
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/health || exit 1
# Start nginx
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -1,4 +1,5 @@
source "https://rubygems.org"
gem "fastlane"
gem "cocoapods"

View File

@@ -22,7 +22,26 @@ GEM
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.3.2)
aws-partitions (1.1066.0)
aws-sdk-core (3.220.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.99.0)
aws-sdk-core (~> 3, >= 3.216.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.182.0)
aws-sdk-core (~> 3, >= 3.216.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.11.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
@@ -64,13 +83,96 @@ GEM
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
declarative (0.0.20)
digest-crc (0.7.0)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.6.20240107)
dotenv (2.8.1)
drb (2.2.1)
emoji_regex (3.2.3)
escape (0.0.4)
ethon (0.16.0)
ffi (>= 1.15.0)
excon (0.112.0)
faraday (1.10.4)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.1.0)
multipart-post (~> 2.0)
faraday-net_http (1.0.2)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.1)
faraday (~> 1.0)
fastimage (2.4.0)
fastlane (2.227.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored (~> 1.2)
commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
fastlane-sirp (>= 1.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-env (>= 1.6.0, < 2.0.0)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2)
optparse (>= 0.1.1, < 1.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.5)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (~> 3)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.4.0)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
fastlane-sirp (1.0.0)
sysrandom (~> 1.0)
ffi (1.17.1)
ffi (1.17.1-aarch64-linux-gnu)
ffi (1.17.1-aarch64-linux-musl)
@@ -85,27 +187,107 @@ GEM
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.3)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0)
google-apis-core (>= 0.11.0, < 2.a)
google-cloud-core (1.8.0)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.5.0)
google-cloud-storage (1.47.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.31.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.8.1)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.8)
domain_name (~> 0.5)
httpclient (2.9.0)
mutex_m
i18n (1.14.7)
concurrent-ruby (~> 1.0)
jmespath (1.6.2)
json (2.10.2)
jwt (2.10.1)
base64
logger (1.6.6)
mini_magick (4.13.2)
mini_mime (1.1.5)
minitest (5.25.5)
molinillo (0.8.0)
multi_json (1.15.0)
multipart-post (2.4.1)
mutex_m (0.3.0)
nanaimo (0.4.0)
nap (1.1.0)
naturally (2.2.1)
netrc (0.11.0)
nkf (0.2.0)
optparse (0.6.0)
os (1.1.4)
plist (3.7.2)
public_suffix (4.0.7)
rake (13.2.1)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.4.1)
rouge (3.28.0)
ruby-macho (2.5.1)
ruby2_keywords (0.0.5)
rubyzip (2.4.1)
securerandom (0.4.1)
security (0.1.5)
signet (0.19.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.10)
CFPropertyList
naturally
sysrandom (1.0.5)
terminal-notifier (2.0.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.2)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
typhoeus (1.4.1)
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uber (0.1.0)
unicode-display_width (2.6.0)
word_wrap (1.0.0)
xcodeproj (1.27.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
@@ -113,6 +295,10 @@ GEM
colored2 (~> 3.1)
nanaimo (~> 0.4.0)
rexml (>= 3.3.6, < 4.0)
xcpretty (0.4.0)
rouge (~> 3.28.0)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
aarch64-linux-gnu
@@ -129,6 +315,7 @@ PLATFORMS
DEPENDENCIES
cocoapods
fastlane
BUNDLED WITH
2.6.5

129
README.md
View File

@@ -3,32 +3,6 @@
[Time Safari](https://timesafari.org/) allows people to ease into collaboration: start with expressions of gratitude
and expand to crowd-fund with time & money, then record and see the impact of contributions.
## Database Migration Status
**Current Status**: The application is undergoing a migration from Dexie (IndexedDB) to SQLite using absurd-sql. This migration is in **Phase 2** with a well-defined migration fence in place.
### Migration Progress
-**SQLite Database Service**: Fully implemented with absurd-sql
-**Platform Service Layer**: Unified database interface across platforms
-**Settings Migration**: Core user settings transferred
-**Account Migration**: Identity and key management
- 🔄 **Contact Migration**: User contact data (via import interface)
- 📋 **Code Cleanup**: Remove unused Dexie imports
### Migration Fence
The migration is controlled by a **migration fence** that separates legacy Dexie code from the new SQLite implementation. See [Migration Fence Definition](doc/migration-fence-definition.md) for complete details.
**Key Points**:
- Legacy Dexie database is disabled by default
- All database operations go through `PlatformServiceMixin`
- Migration tools provide controlled access to both databases
- Clear separation between legacy and new code
### Migration Documentation
- [Migration Guide](doc/migration-to-wa-sqlite.md) - Complete migration process
- [Migration Fence Definition](doc/migration-fence-definition.md) - Fence boundaries and rules
- [Database Migration Guide](doc/database-migration-guide.md) - User-facing migration tools
## Roadmap
See [project.task.yaml](project.task.yaml) for current priorities.
@@ -45,94 +19,18 @@ npm install
npm run dev
```
See [BUILDING.md](BUILDING.md) for comprehensive build instructions for all platforms (Web, Electron, iOS, Android, Docker).
See [BUILDING.md](BUILDING.md) for more details.
## Development Database Clearing
TimeSafari provides a simple script-based approach to clear the database for development purposes.
### Quick Usage
```bash
# Run the database clearing script
./scripts/clear-database.sh
# Then restart your development server
npm run build:electron:dev # For Electron
npm run build:web:dev # For Web
```
### What It Does
#### **Electron (Desktop App)**
- Automatically finds and clears the SQLite database files
- Works on Linux, macOS, and Windows
- Clears all data and forces fresh migrations on next startup
#### **Web Browser**
- Provides instructions for using custom browser data directories
- Shows manual clearing via browser DevTools
- Ensures reliable database clearing without browser complications
### Safety Features
-**Interactive Script**: Guides you through the process
-**Platform Detection**: Automatically detects your OS
-**Clear Instructions**: Step-by-step guidance for each platform
-**Safe Paths**: Only clears TimeSafari-specific data
### Manual Commands (if needed)
#### **Electron Database Location**
```bash
# Linux
rm -rf ~/.config/TimeSafari/*
# macOS
rm -rf ~/Library/Application\ Support/TimeSafari/*
# Windows
rmdir /s /q %APPDATA%\TimeSafari
```
#### **Web Browser (Custom Data Directory)**
```bash
# Create isolated browser profile
mkdir ~/timesafari-dev-data
```
## Domain Configuration
TimeSafari uses a centralized domain configuration system to ensure consistent
URL generation across all environments. This prevents localhost URLs from
appearing in shared links during development.
### Key Features
-**Production URLs for Sharing**: All copy link buttons use production domain
-**Environment-Specific Internal URLs**: Internal operations use appropriate
environment URLs
-**Single Point of Control**: Change domain in one place for entire app
-**Type-Safe Configuration**: Full TypeScript support
### Quick Reference
```typescript
// For sharing functionality (environment-specific)
import { APP_SERVER } from "@/constants/app";
const shareLink = `${APP_SERVER}/deep-link/claim/123`;
// For internal operations (environment-specific)
import { APP_SERVER } from "@/constants/app";
const apiUrl = `${APP_SERVER}/api/claim/123`;
```
### Documentation
- [Domain Configuration System](docs/domain-configuration.md) - Complete guide
- [Constants and Configuration](src/constants/app.ts) - Core constants
## Tests
See [TESTING.md](test-playwright/TESTING.md) for detailed test instructions.
## Icons
Application icons are in the `assets` directory, processed by the `capacitor-assets` command.
@@ -168,25 +66,6 @@ Key principles:
- Common interfaces are shared through `common.ts`
- Type definitions are generated from Zod schemas where possible
### Database Architecture
The application uses a platform-agnostic database layer with Vue mixins for service access:
* `src/services/PlatformService.ts` - Database interface definition
* `src/services/PlatformServiceFactory.ts` - Platform-specific service factory
* `src/services/AbsurdSqlDatabaseService.ts` - SQLite implementation
* `src/utils/PlatformServiceMixin.ts` - Vue mixin for database access with caching
* `src/db/` - Legacy Dexie database (migration in progress)
**Development Guidelines**:
- Always use `PlatformServiceMixin` for database operations in components
- Test with PlatformServiceMixin for new features
- Use migration tools for data transfer between systems
- Leverage mixin's ultra-concise methods: `$db()`, `$exec()`, `$one()`, `$contacts()`, `$settings()`
**Architecture Decision**: The project uses Vue mixins over Composition API composables for platform service access. See [Architecture Decisions](doc/architecture-decisions.md) for detailed rationale.
### Kudos
Gifts make the world go 'round!

7
android/.gitignore vendored
View File

@@ -84,6 +84,13 @@ freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
# Version control
vcs.xml

View File

@@ -31,8 +31,8 @@ android {
applicationId "app.timesafari.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 35
versionName "1.0.2"
versionCode 18
versionName "0.4.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
@@ -64,14 +64,6 @@ android {
}
}
}
packagingOptions {
jniLibs {
pickFirsts += ['**/lib/x86_64/libbarhopper_v3.so', '**/lib/x86_64/libimage_processing_util_jni.so', '**/lib/x86_64/libsqlcipher.so']
}
}
// Configure for 16 KB page size compatibility
// Enable bundle builds (without which it doesn't work right for bundleDebug vs bundleRelease)
bundle {

View File

@@ -13,7 +13,6 @@
android:exported="true"
android:label="@string/title_activity_main"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBarLaunch">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@@ -2,6 +2,7 @@
"appId": "app.timesafari",
"appName": "TimeSafari",
"webDir": "dist",
"bundledWebRuntime": false,
"server": {
"cleartext": true
},
@@ -16,36 +17,22 @@
]
}
},
"SplashScreen": {
"launchShowDuration": 3000,
"launchAutoHide": true,
"backgroundColor": "#ffffff",
"androidSplashResourceName": "splash",
"androidScaleType": "CENTER_CROP",
"showSpinner": false,
"androidSpinnerStyle": "large",
"iosSpinnerStyle": "small",
"spinnerColor": "#999999",
"splashFullScreen": true,
"splashImmersive": true
},
"CapacitorSQLite": {
"SQLite": {
"iosDatabaseLocation": "Library/CapacitorDatabase",
"iosIsEncryption": false,
"iosIsEncryption": true,
"iosBiometric": {
"biometricAuth": false,
"biometricAuth": true,
"biometricTitle": "Biometric login for TimeSafari"
},
"androidIsEncryption": false,
"androidIsEncryption": true,
"androidBiometric": {
"biometricAuth": false,
"biometricAuth": true,
"biometricTitle": "Biometric login for TimeSafari"
},
"electronIsEncryption": false
}
}
},
"ios": {
"contentInset": "never",
"contentInset": "always",
"allowsLinkPreview": true,
"scrollEnabled": true,
"limitsNavigationsToAppBoundDomains": true,
@@ -57,65 +44,13 @@
]
},
"android": {
"allowMixedContent": true,
"allowMixedContent": false,
"captureInput": true,
"webContentsDebuggingEnabled": false,
"allowNavigation": [
"*.timesafari.app",
"*.jsdelivr.net",
"api.endorser.ch",
"10.0.2.2:3000"
"api.endorser.ch"
]
},
"electron": {
"deepLinking": {
"schemes": [
"timesafari"
]
},
"buildOptions": {
"appId": "app.timesafari",
"productName": "TimeSafari",
"directories": {
"output": "dist-electron-packages"
},
"files": [
"dist/**/*",
"electron/**/*"
],
"mac": {
"category": "public.app-category.productivity",
"target": [
{
"target": "dmg",
"arch": [
"x64",
"arm64"
]
}
]
},
"win": {
"target": [
{
"target": "nsis",
"arch": [
"x64"
]
}
]
},
"linux": {
"target": [
{
"target": "AppImage",
"arch": [
"x64"
]
}
],
"category": "Utility"
}
}
}
}

View File

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2480 4005 c-25 -7 -58 -20 -75 -29 -16 -9 -40 -16 -52 -16 -17 0
-24 -7 -28 -27 -3 -16 -14 -45 -24 -65 -21 -41 -13 -55 18 -38 25 13 67 13 92
-1 15 -8 35 -4 87 17 99 39 130 41 197 10 64 -29 77 -31 107 -15 20 11 20 11
-3 35 -12 13 -30 24 -38 24 -24 1 -132 38 -148 51 -8 7 -11 20 -7 32 12 37
-40 47 -126 22z"/>
<path d="M1450 3775 c-7 -8 -18 -15 -24 -15 -7 0 -31 -14 -54 -32 -29 -22 -38
-34 -29 -40 17 -11 77 -10 77 1 0 5 16 16 35 25 60 29 220 19 290 -18 17 -9
33 -16 37 -16 4 0 31 -15 60 -34 108 -70 224 -215 282 -353 30 -71 53 -190 42
-218 -10 -27 -23 -8 -52 75 -30 90 -88 188 -120 202 -13 6 -26 9 -29 6 -3 -2
11 -51 30 -108 28 -83 35 -119 35 -179 0 -120 -22 -127 -54 -17 -11 37 -13 21
-18 -154 -5 -180 -8 -200 -32 -264 -51 -132 -129 -245 -199 -288 -21 -12 -79
-49 -129 -80 -161 -102 -294 -141 -473 -141 -228 0 -384 76 -535 259 -81 99
-118 174 -154 312 -31 121 -35 273 -11 437 19 127 19 125 -4 125 -23 0 -51
-34 -87 -104 -14 -28 -33 -64 -41 -81 -19 -34 -22 -253 -7 -445 9 -106 12
-119 44 -170 19 -30 42 -67 50 -81 64 -113 85 -140 130 -169 28 -18 53 -44 61
-62 8 -20 36 -45 83 -76 62 -39 80 -46 151 -54 44 -5 96 -13 115 -18 78 -20
238 -31 282 -19 24 6 66 8 95 5 76 -9 169 24 319 114 32 19 80 56 106 82 27
26 52 48 58 48 5 0 27 26 50 58 48 66 56 70 132 71 62 1 165 29 238 64 112 55
177 121 239 245 37 76 39 113 10 267 -12 61 -23 131 -26 156 -5 46 -5 47 46
87 92 73 182 70 263 -8 l51 -49 -6 -61 c-4 -34 -13 -85 -21 -113 -28 -103 -30
-161 -4 -228 16 -44 32 -67 55 -83 18 -11 39 -37 47 -58 10 -23 37 -53 73 -81
32 -25 69 -57 82 -71 14 -14 34 -26 47 -26 12 0 37 -7 56 -15 20 -8 66 -17
104 -20 107 -10 110 -11 150 -71 50 -75 157 -177 197 -187 18 -5 53 -24 78
-42 71 -51 176 -82 304 -89 61 -4 127 -12 147 -18 29 -9 45 -8 77 6 23 9 50
16 60 16 31 0 163 46 216 76 28 15 75 46 105 69 30 23 69 49 85 58 17 8 46 31
64 51 19 20 40 36 47 36 18 0 77 70 100 120 32 66 45 108 55 173 5 32 16 71
24 87 43 84 43 376 0 549 -27 105 -43 127 -135 188 -30 21 -65 46 -77 57 -13
11 -23 17 -23 14 0 -3 21 -46 47 -94 79 -151 85 -166 115 -263 25 -83 28 -110
28 -226 0 -144 -17 -221 -75 -335 -39 -77 -208 -244 -304 -299 -451 -263 -975
-67 -1138 426 -23 70 -26 95 -28 254 -1 108 -7 183 -14 196 -6 12 -11 31 -11
43 0 32 31 122 52 149 10 13 18 28 18 34 0 5 25 40 56 78 60 73 172 170 219
190 30 12 30 13 6 17 -15 2 -29 -2 -37 -12 -6 -9 -16 -16 -22 -16 -6 0 -23
-11 -39 -24 -15 -12 -33 -25 -40 -27 -17 -6 -82 -60 -117 -97 -65 -70 -75 -82
-107 -133 -23 -34 -35 -46 -37 -35 -3 16 20 87 44 134 6 12 9 34 6 48 -4 22
-8 25 -31 19 -14 -3 -38 -15 -53 -26 -34 -24 -34 -21 -6 28 65 112 184 206
291 227 15 3 39 9 55 12 l27 6 -24 9 c-90 35 -304 -66 -478 -225 -39 -36 -74
-66 -77 -66 -22 0 18 82 72 148 19 23 32 46 28 49 -4 4 -26 13 -49 19 -73 21
-161 54 -171 64 -6 6 -20 10 -32 10 -21 0 -21 -1 -8 -40 45 -130 8 -247 -93
-299 -25 -13 -31 0 -14 29 15 22 1 33 -22 17 -56 -36 -117 -22 -117 28 0 13
-16 47 -35 76 -22 34 -33 60 -29 73 4 16 -3 26 -26 39 -16 10 -30 21 -30 25 1
18 54 64 87 76 l38 13 -33 5 c-30 4 -115 -18 -154 -42 -13 -7 -20 -5 -27 8 -9
16 -12 16 -53 1 -160 -61 -258 -104 -258 -114 0 -7 10 -20 21 -31 103 -91 217
-297 249 -449 28 -135 41 -237 35 -276 -14 -91 -48 -170 -97 -220 -44 -47 -68
-60 -68 -40 0 6 4 12 8 15 5 3 24 35 42 72 l33 67 -6 141 c-4 103 -11 158 -26
205 -12 35 -21 70 -21 77 0 7 -20 56 -45 108 -82 173 -227 322 -392 401 -67
33 -90 39 -163 42 -108 5 -130 10 -130 28 0 20 -63 20 -80 0z"/>
<path d="M3710 3765 c0 -20 8 -28 39 -41 22 -8 42 -22 45 -30 5 -14 42 -19 70
-8 10 4 -7 21 -58 55 -41 27 -79 49 -85 49 -6 0 -11 -11 -11 -25z"/>
<path d="M3173 3734 c-9 -25 10 -36 35 -18 12 8 22 19 22 25 0 16 -50 10 -57
-7z"/>
<path d="M1982 3728 c6 -16 36 -34 44 -26 3 4 4 14 1 23 -7 17 -51 21 -45 3z"/>
<path d="M1540 3620 c0 -5 7 -10 16 -10 8 0 12 5 9 10 -3 6 -10 10 -16 10 -5
0 -9 -4 -9 -10z"/>
<path d="M4467 3624 c-4 -4 23 -27 60 -50 84 -56 99 -58 67 -9 -28 43 -107 79
-127 59z"/>
<path d="M655 3552 c-11 -2 -26 -9 -33 -14 -7 -6 -27 -18 -45 -27 -36 -18 -58
-64 -39 -83 9 -9 25 1 70 43 53 48 78 78 70 84 -2 1 -12 -1 -23 -3z"/>
<path d="M1015 3460 c-112 -24 -247 -98 -303 -165 -53 -65 -118 -214 -136
-311 -20 -113 -20 -145 -1 -231 20 -88 49 -153 102 -230 79 -113 186 -182 331
-214 108 -24 141 -24 247 1 130 30 202 72 316 181 102 100 153 227 152 384 0
142 -58 293 -150 395 -60 67 -180 145 -261 171 -75 23 -232 34 -297 19z m340
-214 c91 -43 174 -154 175 -234 0 -18 -9 -51 -21 -73 -19 -37 -19 -42 -5 -64
35 -54 12 -121 -48 -142 -22 -7 -47 -19 -55 -27 -9 -8 -41 -27 -71 -42 -50
-26 -64 -29 -155 -29 -111 0 -152 14 -206 68 -49 49 -63 85 -64 162 0 59 4 78
28 118 31 52 96 105 141 114 23 5 33 17 56 68 46 103 121 130 225 81z"/>
<path d="M3985 3464 c-44 -7 -154 -44 -200 -67 -55 -28 -138 -96 -162 -132
-10 -16 -39 -75 -64 -130 l-44 -100 0 -160 0 -160 45 -90 c53 -108 152 -214
245 -264 59 -31 215 -71 281 -71 53 0 206 40 255 67 98 53 203 161 247 253 53
113 74 193 74 280 -1 304 -253 564 -557 575 -49 2 -103 1 -120 -1z m311 -220
c129 -68 202 -209 160 -309 -15 -35 -15 -42 -1 -72 26 -55 -3 -118 -59 -129
-19 -3 -43 -15 -53 -26 -26 -29 -99 -64 -165 -78 -45 -10 -69 -10 -120 -1 -74
15 -113 37 -161 91 -110 120 -50 331 109 385 24 8 44 23 52 39 6 14 18 38 25
53 33 72 127 93 213 47z"/>
<path d="M487 3394 c-21 -12 -27 -21 -25 -40 2 -14 7 -26 12 -27 14 -3 48 48
44 66 -3 14 -6 14 -31 1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 KiB

View File

@@ -0,0 +1,11 @@
Model Information:
* title: Lupine Plant
* source: https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439
* author: rufusrockwell (https://sketchfab.com/rufusrockwell)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "Lupine Plant" (https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439) by rufusrockwell (https://sketchfab.com/rufusrockwell) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

View File

@@ -0,0 +1,229 @@
{
"accessors": [
{
"bufferView": 2,
"componentType": 5126,
"count": 2759,
"max": [
41.3074951171875,
40.37548828125,
87.85917663574219
],
"min": [
-35.245540618896484,
-36.895416259765625,
-0.9094290137290955
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 33108,
"componentType": 5126,
"count": 2759,
"max": [
0.9999382495880127,
0.9986748695373535,
0.9985831379890442
],
"min": [
-0.9998949766159058,
-0.9975876212120056,
-0.411094069480896
],
"type": "VEC3"
},
{
"bufferView": 3,
"componentType": 5126,
"count": 2759,
"max": [
0.9987699389457703,
0.9998998045921326,
0.9577858448028564,
1.0
],
"min": [
-0.9987726807594299,
-0.9990445971488953,
-0.999801516532898,
1.0
],
"type": "VEC4"
},
{
"bufferView": 1,
"componentType": 5126,
"count": 2759,
"max": [
1.0061479806900024,
0.9993550181388855
],
"min": [
0.00279300007969141,
0.0011620000004768372
],
"type": "VEC2"
},
{
"bufferView": 0,
"componentType": 5125,
"count": 6378,
"type": "SCALAR"
}
],
"asset": {
"extras": {
"author": "rufusrockwell (https://sketchfab.com/rufusrockwell)",
"license": "CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)",
"source": "https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439",
"title": "Lupine Plant"
},
"generator": "Sketchfab-12.68.0",
"version": "2.0"
},
"bufferViews": [
{
"buffer": 0,
"byteLength": 25512,
"name": "floatBufferViews",
"target": 34963
},
{
"buffer": 0,
"byteLength": 22072,
"byteOffset": 25512,
"byteStride": 8,
"name": "floatBufferViews",
"target": 34962
},
{
"buffer": 0,
"byteLength": 66216,
"byteOffset": 47584,
"byteStride": 12,
"name": "floatBufferViews",
"target": 34962
},
{
"buffer": 0,
"byteLength": 44144,
"byteOffset": 113800,
"byteStride": 16,
"name": "floatBufferViews",
"target": 34962
}
],
"buffers": [
{
"byteLength": 157944,
"uri": "scene.bin"
}
],
"images": [
{
"uri": "textures/lambert2SG_baseColor.png"
},
{
"uri": "textures/lambert2SG_normal.png"
}
],
"materials": [
{
"alphaCutoff": 0.2,
"alphaMode": "MASK",
"doubleSided": true,
"name": "lambert2SG",
"normalTexture": {
"index": 1
},
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
},
"metallicFactor": 0.0
}
}
],
"meshes": [
{
"name": "Object_0",
"primitives": [
{
"attributes": {
"NORMAL": 1,
"POSITION": 0,
"TANGENT": 2,
"TEXCOORD_0": 3
},
"indices": 4,
"material": 0,
"mode": 4
}
]
}
],
"nodes": [
{
"children": [
1
],
"matrix": [
1.0,
0.0,
0.0,
0.0,
0.0,
2.220446049250313e-16,
-1.0,
0.0,
0.0,
1.0,
2.220446049250313e-16,
0.0,
0.0,
0.0,
0.0,
1.0
],
"name": "Sketchfab_model"
},
{
"children": [
2
],
"name": "LupineSF.obj.cleaner.materialmerger.gles"
},
{
"mesh": 0,
"name": "Object_2"
}
],
"samplers": [
{
"magFilter": 9729,
"minFilter": 9987,
"wrapS": 10497,
"wrapT": 10497
}
],
"scene": 0,
"scenes": [
{
"name": "Sketchfab_Scene",
"nodes": [
0
]
}
],
"textures": [
{
"sampler": 0,
"source": 0
},
{
"sampler": 0,
"source": 1
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow:

View File

@@ -2,7 +2,7 @@ package app.timesafari;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;
//import com.getcapacitor.community.sqlite.SQLite;
import com.getcapacitor.community.sqlite.SQLite;
public class MainActivity extends BridgeActivity {
@Override
@@ -10,6 +10,6 @@ public class MainActivity extends BridgeActivity {
super.onCreate(savedInstanceState);
// Initialize SQLite
//registerPlugin(SQLite.class);
registerPlugin(SQLite.class);
}
}

View File

@@ -0,0 +1,5 @@
package timesafari.app;
import com.getcapacitor.BridgeActivity;
public class MainActivity extends BridgeActivity {}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FFFFFF</color>
</resources>

View File

@@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.12.0'
classpath 'com.android.tools.build:gradle:8.9.1'
classpath 'com.google.gms:google-services:4.4.0'
// NOTE: Do not place your application dependencies here; they belong

View File

@@ -20,4 +20,4 @@ org.gradle.jvmargs=-Xmx1536m
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
android.suppressUnsupportedCompileSdk=36
android.suppressUnsupportedCompileSdk=34

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,7 +1,7 @@
ext {
minSdkVersion = 22
compileSdkVersion = 36
targetSdkVersion = 36
compileSdkVersion = 34
targetSdkVersion = 34
androidxActivityVersion = '1.8.0'
androidxAppCompatVersion = '1.6.1'
androidxCoordinatorLayoutVersion = '1.2.0'

BIN
assets/icon-only.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

View File

@@ -1,36 +0,0 @@
{
"icon": {
"ios": {
"source": "resources/ios/icon/icon.png",
"target": "ios/App/App/Assets.xcassets/AppIcon.appiconset"
},
"android": {
"source": "resources/android/icon/icon.png",
"target": "android/app/src/main/res"
},
"web": {
"source": "resources/web/icon/icon.png",
"target": "public/img/icons"
}
},
"splash": {
"ios": {
"source": "resources/ios/splash/splash.png",
"target": "ios/App/App/Assets.xcassets/Splash.imageset"
},
"android": {
"source": "resources/android/splash/splash.png",
"target": "android/app/src/main/res"
}
},
"splashDark": {
"ios": {
"source": "resources/ios/splash/splash_dark.png",
"target": "ios/App/App/Assets.xcassets/SplashDark.imageset"
},
"android": {
"source": "resources/android/splash/splash_dark.png",
"target": "android/app/src/main/res"
}
}
}

View File

@@ -1,9 +1,11 @@
{
"appId": "app.timesafari",
"appId": "com.timesafari.app",
"appName": "TimeSafari",
"webDir": "dist",
"bundledWebRuntime": false,
"server": {
"cleartext": true
"cleartext": true,
"androidScheme": "https"
},
"plugins": {
"App": {
@@ -16,36 +18,28 @@
]
}
},
"SplashScreen": {
"launchShowDuration": 3000,
"launchAutoHide": true,
"backgroundColor": "#ffffff",
"androidSplashResourceName": "splash",
"androidScaleType": "CENTER_CROP",
"showSpinner": false,
"androidSpinnerStyle": "large",
"iosSpinnerStyle": "small",
"spinnerColor": "#999999",
"splashFullScreen": true,
"splashImmersive": true
"SQLite": {
"iosDatabaseLocation": "Library/CapacitorDatabase",
"iosIsEncryption": true,
"iosBiometric": {
"biometricAuth": true,
"biometricTitle": "Biometric login for TimeSafari"
},
"androidIsEncryption": true,
"androidBiometric": {
"biometricAuth": true,
"biometricTitle": "Biometric login for TimeSafari"
}
},
"CapacitorSQLite": {
"iosDatabaseLocation": "Library/CapacitorDatabase",
"iosIsEncryption": false,
"iosBiometric": {
"biometricAuth": false,
"biometricTitle": "Biometric login for TimeSafari"
},
"androidIsEncryption": false,
"androidBiometric": {
"biometricAuth": false,
"biometricTitle": "Biometric login for TimeSafari"
},
"electronIsEncryption": false
"electronIsEncryption": false,
"electronMacLocation": "~/Library/Application Support/TimeSafari",
"electronWindowsLocation": "C:\\ProgramData\\TimeSafari",
"electronLinuxLocation": "~/.local/share/TimeSafari"
}
},
"ios": {
"contentInset": "never",
"contentInset": "always",
"allowsLinkPreview": true,
"scrollEnabled": true,
"limitsNavigationsToAppBoundDomains": true,
@@ -57,56 +51,13 @@
]
},
"android": {
"allowMixedContent": true,
"allowMixedContent": false,
"captureInput": true,
"webContentsDebuggingEnabled": false,
"allowNavigation": [
"*.timesafari.app",
"*.jsdelivr.net",
"api.endorser.ch",
"10.0.2.2:3000"
"api.endorser.ch"
]
},
"electron": {
"deepLinking": {
"schemes": ["timesafari"]
},
"buildOptions": {
"appId": "app.timesafari",
"productName": "TimeSafari",
"directories": {
"output": "dist-electron-packages"
},
"files": [
"dist/**/*",
"electron/**/*"
],
"mac": {
"category": "public.app-category.productivity",
"target": [
{
"target": "dmg",
"arch": ["x64", "arm64"]
}
]
},
"win": {
"target": [
{
"target": "nsis",
"arch": ["x64"]
}
]
},
"linux": {
"target": [
{
"target": "AppImage",
"arch": ["x64"]
}
],
"category": "Utility"
}
}
}
}

View File

@@ -100,7 +100,6 @@ try {
- `src/interfaces/deepLinks.ts`: Type definitions and validation schemas
- `src/services/deepLinks.ts`: Deep link processing service
- `src/main.capacitor.ts`: Capacitor integration
- `src/views/DeepLinkRedirectView.vue`: Page to handle links to both mobile and web
## Type Safety Examples

View File

@@ -1,381 +0,0 @@
# Worker-Only Database Implementation for Web Platform
## Overview
This implementation fixes the double migration issue in the TimeSafari web platform by implementing worker-only database access, similar to the Capacitor platform architecture.
## Problem Solved
**Before:** Web platform had dual database contexts:
- Worker thread: `registerSQLWorker.js``AbsurdSqlDatabaseService.initialize()` → migrations run
- Main thread: `WebPlatformService.dbQuery()``databaseService.query()` → migrations run **AGAIN**
**After:** Single database context:
- Worker thread: Handles ALL database operations and initializes once
- Main thread: Sends messages to worker, no direct database access
## Architecture Changes
### 1. Message-Based Communication
```typescript
// Main Thread (WebPlatformService)
await this.sendWorkerMessage<QueryResult>({
type: "query",
sql: "SELECT * FROM users",
params: []
});
// Worker Thread (registerSQLWorker.js)
onmessage = async (event) => {
const { id, type, sql, params } = event.data;
if (type === "query") {
const result = await databaseService.query(sql, params);
postMessage({ id, type: "success", data: { result } });
}
};
```
### 2. Type-Safe Worker Messages
```typescript
// src/interfaces/worker-messages.ts
export interface QueryRequest extends BaseWorkerMessage {
type: "query";
sql: string;
params?: unknown[];
}
export type WorkerRequest =
| QueryRequest
| ExecRequest
| GetOneRowRequest
| InitRequest
| PingRequest;
```
### 3. Circular Dependency Resolution
#### 🔥 Critical Fix: Stack Overflow Prevention
**Problem**: Circular module dependency caused infinite recursion:
- `WebPlatformService` constructor → creates Worker
- Worker loads `registerSQLWorker.js` → imports `databaseService`
- Module resolution creates circular dependency → Stack Overflow
**Solution**: Lazy Loading in Worker
```javascript
// Before (caused stack overflow)
import databaseService from "./services/AbsurdSqlDatabaseService";
// After (fixed)
let databaseService = null;
async function getDatabaseService() {
if (!databaseService) {
// Dynamic import prevents circular dependency
const { default: service } = await import("./services/AbsurdSqlDatabaseService");
databaseService = service;
}
return databaseService;
}
```
**Key Changes for Stack Overflow Fix:**
- ✅ Removed top-level import of database service
- ✅ Added lazy loading with dynamic import
- ✅ Updated all handlers to use `await getDatabaseService()`
- ✅ Removed auto-initialization that triggered immediate loading
- ✅ Database service only loads when first database operation occurs
## Implementation Details
### 1. WebPlatformService Changes
- Removed direct database imports
- Added worker message handling
- Implemented timeout and error handling
- All database methods now proxy to worker
### 2. Worker Thread Changes
- Added message-based operation handling
- Implemented lazy loading for database service
- Added proper error handling and response formatting
- Fixed circular dependency with dynamic imports
### 3. Main Thread Changes
- Removed duplicate worker creation in `main.web.ts`
- WebPlatformService now manages single worker instance
- Added Safari compatibility with `initBackend()`
## Files Modified
1. **src/interfaces/worker-messages.ts** *(NEW)*
- Type definitions for worker communication
- Request and response message interfaces
2. **src/registerSQLWorker.js** *(MAJOR REWRITE)*
- Message-based operation handling
- **Fixed circular dependency with lazy loading**
- Proper error handling and response formatting
3. **src/services/platforms/WebPlatformService.ts** *(MAJOR REWRITE)*
- Worker-only database access
- Message sending and response handling
- Timeout and error management
4. **src/main.web.ts** *(SIMPLIFIED)*
- Removed duplicate worker creation
- Simplified initialization flow
5. **WORKER_ONLY_DATABASE_IMPLEMENTATION.md** *(NEW)*
- Complete documentation of changes
## Benefits
### ✅ Fixes Double Migration Issue
- Database migrations now run only once in worker thread
- No duplicate initialization between main thread and worker
### ✅ Prevents Stack Overflow
- Circular dependency resolved with lazy loading
- Worker loads immediately without triggering database import
- Database service loads on-demand when first operation occurs
### ✅ Improved Performance
- Single database connection
- No redundant operations
- Better resource utilization
### ✅ Better Error Handling
- Centralized error handling in worker
- Type-safe message communication
- Proper timeout handling
### ✅ Consistent Architecture
- Matches Capacitor platform pattern
- Single-threaded database access
- Clear separation of concerns
## Testing Verification
After implementation, you should see:
1. **Worker Loading**:
```text
[SQLWorker] Worker loaded, ready to receive messages
```
2. **Database Initialization** (only on first operation):
```text
[SQLWorker] Starting database initialization...
[SQLWorker] Database initialization completed successfully
```
3. **No Stack Overflow**: Application starts without infinite recursion
4. **Single Migration Run**: Database migrations execute only once
5. **Functional Database**: All queries, inserts, and updates work correctly
## Migration from Previous Implementation
If upgrading from the dual-context implementation:
1. **Remove Direct Database Imports**: No more `import databaseService` in main thread
2. **Update Database Calls**: Use platform service methods instead of direct database calls
3. **Handle Async Operations**: All database operations are now async message-based
4. **Error Handling**: Update error handling to work with worker responses
## Security Considerations
- Worker thread isolates database operations
- Message validation prevents malformed requests
- Timeout handling prevents hanging operations
- Type safety reduces runtime errors
## Performance Notes
- Initial worker creation has minimal overhead
- Database operations have message passing overhead (negligible)
- Single database connection is more efficient than dual connections
- Lazy loading reduces startup time
## Migration Execution Flow
### Before (Problematic)
```chart
┌────────────── ───┐ ┌─────────────────┐
│ Main Thread │ │ Worker Thread │
│ │ │ │
│ WebPlatformService│ │registerSQLWorker│
│ ↓ │ │ ↓ │
│ databaseService │ │ databaseService │
│ (Instance A) │ │ (Instance B) │
│ ↓ │ │ ↓ │
│ [Run Migrations] │ │[Run Migrations] │ ← DUPLICATE!
└─────────────── ──┘ └─────────────────┘
```
### After (Fixed)
```text
┌─────────────── ──┐ ┌─────────────────┐
│ Main Thread │ │ Worker Thread │
│ │ │ │
│ WebPlatformService │───→│registerSQLWorker│
│ │ │ ↓ │
│ [Send Messages] │ │ databaseService │
│ │ │(Single Instance)│
│ │ │ ↓ │
│ │ │[Run Migrations] │ ← ONCE ONLY!
└─────────────── ──┘ └─────────────────┘
```
## New Security Considerations
### 1. **Message Validation**
- All worker messages validated for required fields
- Unknown message types rejected with errors
- Proper error responses prevent information leakage
### 2. **Timeout Protection**
- 30-second timeout prevents hung operations
- Automatic cleanup of pending messages
- Worker health checks via ping/pong
### 3. **Error Sanitization**
- Error messages logged but not exposed raw to main thread
- Stack traces included only in development
- Graceful handling of worker failures
## Testing Considerations
### 1. **Unit Tests Needed**
- Worker message handling
- WebPlatformService worker communication
- Error handling and timeouts
- Migration execution (should run once only)
### 2. **Integration Tests**
- End-to-end database operations
- Worker lifecycle management
- Cross-browser compatibility (especially Safari)
### 3. **Performance Tests**
- Message passing overhead
- Database operation throughput
- Memory usage with worker communication
## Browser Compatibility
### 1. **Modern Browsers**
- Chrome/Edge: Full SharedArrayBuffer support
- Firefox: Full SharedArrayBuffer support (with headers)
- Safari: Uses IndexedDB fallback via `initBackend()`
### 2. **Required Headers**
```text
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```
## Deployment Notes
### 1. **Development**
- Enhanced logging shows worker message flow
- Clear separation between worker and main thread logs
- Easy debugging via browser DevTools
### 2. **Production**
- Reduced logging overhead
- Optimized message passing
- Proper error reporting without sensitive data
## Future Enhancements
### 1. **Potential Optimizations**
- Message batching for bulk operations
- Connection pooling simulation
- Persistent worker state management
### 2. **Additional Features**
- Database backup/restore via worker
- Schema introspection commands
- Performance monitoring hooks
## Rollback Plan
If issues arise, rollback involves:
1. Restore original `WebPlatformService.ts`
2. Restore original `registerSQLWorker.js`
3. Restore original `main.web.ts`
4. Remove `worker-messages.ts` interface
## Commit Messages
```bash
git add src/interfaces/worker-messages.ts
git commit -m "Add worker message interface for type-safe database communication
- Define TypeScript interfaces for worker request/response messages
- Include query, exec, getOneRow, init, and ping message types
- Provide type safety for web platform worker messaging"
git add src/registerSQLWorker.js
git commit -m "Implement message-based worker for single-point database access
- Replace simple auto-init with comprehensive message handler
- Add support for query, exec, getOneRow, init, ping operations
- Implement proper error handling and response management
- Ensure single database initialization point to prevent double migrations"
git add src/services/platforms/WebPlatformService.ts
git commit -m "Migrate WebPlatformService to worker-only database access
- Remove direct databaseService import to prevent dual context issue
- Implement worker-based messaging for all database operations
- Add worker lifecycle management with initialization tracking
- Include message timeout and error handling for reliability
- Add Safari compatibility with initBackend call"
git add src/main.web.ts
git commit -m "Remove duplicate worker creation from main.web.ts
- Worker initialization now handled by WebPlatformService
- Prevents duplicate worker creation and database contexts
- Simplifies main thread initialization"
git add WORKER_ONLY_DATABASE_IMPLEMENTATION.md
git commit -m "Document worker-only database implementation
- Comprehensive documentation of architecture changes
- Explain problem solved and benefits achieved
- Include security considerations and testing requirements"
```

Some files were not shown because too many files have changed in this diff Show More