From 016e849d3ed2be8edf8ecfa11dab7593bf6e6722 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Mon, 18 Aug 2025 19:26:59 -0600 Subject: [PATCH 01/35] fix: Fix onboard-meeting-members deep link with groupId. --- package.json | 1 + src/interfaces/deepLinks.ts | 28 +++++++++++++++++-------- src/services/deepLinks.ts | 28 +++++++++++++++++-------- src/views/DeepLinkErrorView.vue | 4 ++-- src/views/OnboardMeetingMembersView.vue | 2 +- 5 files changed, 42 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index eb68f859..bdb48dd0 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "type-check": "tsc --noEmit", "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js", "test:prerequisites": "node scripts/check-prerequisites.js", + "test:all": "npm run lint && tsc && npm run test:web && npm run test:mobile && ./scripts/test-safety-check.sh && echo '\n\n\nGotta add the performance tests'", "test:web": "npx playwright test -c playwright.config-local.ts --trace on", "test:mobile": "./scripts/test-mobile.sh", "test:android": "node scripts/test-android.js", diff --git a/src/interfaces/deepLinks.ts b/src/interfaces/deepLinks.ts index d5266c7a..0fe5c68d 100644 --- a/src/interfaces/deepLinks.ts +++ b/src/interfaces/deepLinks.ts @@ -28,7 +28,7 @@ import { z } from "zod"; // Parameter validation schemas for each route type -export const deepLinkSchemas = { +export const deepLinkPathSchemas = { claim: z.object({ id: z.string(), }), @@ -60,7 +60,7 @@ export const deepLinkSchemas = { jwt: z.string().optional(), }), "onboard-meeting-members": z.object({ - id: z.string(), + groupId: z.string(), }), project: z.object({ id: z.string(), @@ -70,6 +70,17 @@ export const deepLinkSchemas = { }), }; +export const deepLinkQuerySchemas = { + "onboard-meeting-members": z.object({ + password: z.string(), + }), +}; + +// Add a union type of all valid route paths +export const VALID_DEEP_LINK_ROUTES = Object.keys( + deepLinkPathSchemas, +) as readonly (keyof typeof deepLinkPathSchemas)[]; + // Create a type from the array export type DeepLinkRoute = (typeof VALID_DEEP_LINK_ROUTES)[number]; @@ -80,14 +91,13 @@ export const baseUrlSchema = z.object({ queryParams: z.record(z.string()).optional(), }); -// Add a union type of all valid route paths -export const VALID_DEEP_LINK_ROUTES = Object.keys( - deepLinkSchemas, -) as readonly (keyof typeof deepLinkSchemas)[]; +// export type DeepLinkPathParams = { +// [K in keyof typeof deepLinkPathSchemas]: z.infer<(typeof deepLinkPathSchemas)[K]>; +// }; -export type DeepLinkParams = { - [K in keyof typeof deepLinkSchemas]: z.infer<(typeof deepLinkSchemas)[K]>; -}; +// export type DeepLinkQueryParams = { +// [K in keyof typeof deepLinkQuerySchemas]: z.infer<(typeof deepLinkQuerySchemas)[K]>; +// }; export interface DeepLinkError extends Error { code: string; diff --git a/src/services/deepLinks.ts b/src/services/deepLinks.ts index d8445607..8d94185d 100644 --- a/src/services/deepLinks.ts +++ b/src/services/deepLinks.ts @@ -47,10 +47,11 @@ import { Router } from "vue-router"; import { z } from "zod"; import { - deepLinkSchemas, + deepLinkPathSchemas, baseUrlSchema, routeSchema, DeepLinkRoute, + deepLinkQuerySchemas, } from "../interfaces/deepLinks"; import type { DeepLinkError } from "../interfaces/deepLinks"; import { logger } from "../utils/logger"; @@ -74,7 +75,7 @@ function getFirstKeyFromZodObject( * because "router.replace" expects the right parameter name for the route. */ export const ROUTE_MAP: Record = - Object.entries(deepLinkSchemas).reduce( + Object.entries(deepLinkPathSchemas).reduce( (acc, [routeName, schema]) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const paramKey = getFirstKeyFromZodObject(schema as z.ZodObject); @@ -198,15 +199,22 @@ export class DeepLinkHandler { } // Continue with parameter validation as before... - const schema = deepLinkSchemas[path as keyof typeof deepLinkSchemas]; + const pathSchema = deepLinkPathSchemas[path as keyof typeof deepLinkPathSchemas]; + const querySchema = deepLinkQuerySchemas[path as keyof typeof deepLinkQuerySchemas]; - let validatedParams; + let validatedPathParams: Record = {}; + let validatedQueryParams: Record = {}; try { - validatedParams = await schema.parseAsync(params); + if (pathSchema) { + validatedPathParams = await pathSchema.parseAsync(params); + } + if (querySchema) { + validatedQueryParams = await querySchema.parseAsync(query); + } } catch (error) { // For parameter validation errors, provide specific error feedback logger.error( - `[DeepLink] Invalid parameters for route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with params: ${JSON.stringify(params)} ... and query: ${JSON.stringify(query)}`, + `[DeepLink] Invalid parameters for route name ${routeName} for path: ${path} ... with error: ${JSON.stringify(error)} ... with params: ${JSON.stringify(params)} ... and query: ${JSON.stringify(query)}`, ); await this.router.replace({ name: "deep-link-error", @@ -226,20 +234,22 @@ export class DeepLinkHandler { try { await this.router.replace({ name: routeName, - params: validatedParams, + params: validatedPathParams, + query: validatedQueryParams }); } catch (error) { logger.error( - `[DeepLink] Error routing to route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with validated params: ${JSON.stringify(validatedParams)}`, + `[DeepLink] Error routing to route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with validated params: ${JSON.stringify(validatedPathParams)} ... and query: ${JSON.stringify(validatedQueryParams)}`, ); // For parameter validation errors, provide specific error feedback await this.router.replace({ name: "deep-link-error", - params: validatedParams, + params: validatedPathParams, query: { originalPath: path, errorCode: "ROUTING_ERROR", errorMessage: `Error routing to ${routeName}: ${JSON.stringify(error)}`, + ...validatedQueryParams, }, }); } diff --git a/src/views/DeepLinkErrorView.vue b/src/views/DeepLinkErrorView.vue index 6decd859..a3b53b09 100644 --- a/src/views/DeepLinkErrorView.vue +++ b/src/views/DeepLinkErrorView.vue @@ -47,7 +47,7 @@ import { computed, onMounted } from "vue"; import { useRoute, useRouter } from "vue-router"; import { VALID_DEEP_LINK_ROUTES, - deepLinkSchemas, + deepLinkPathSchemas, } from "../interfaces/deepLinks"; import { logConsoleAndDb } from "../db/databaseUtil"; import { logger } from "../utils/logger"; @@ -56,7 +56,7 @@ const route = useRoute(); const router = useRouter(); // an object with the route as the key and the first param name as the value const deepLinkSchemaKeys = Object.fromEntries( - Object.entries(deepLinkSchemas).map(([route, schema]) => { + Object.entries(deepLinkPathSchemas).map(([route, schema]) => { const param = Object.keys(schema.shape)[0]; return [route, param]; }), diff --git a/src/views/OnboardMeetingMembersView.vue b/src/views/OnboardMeetingMembersView.vue index a1280011..7e42718b 100644 --- a/src/views/OnboardMeetingMembersView.vue +++ b/src/views/OnboardMeetingMembersView.vue @@ -113,7 +113,7 @@ export default class OnboardMeetingMembersView extends Vue { try { // Identity creation should be handled by router guard, but keep as fallback for meeting setup if (!this.activeDid) { - logger.info( + this.$logAndConsole( "[OnboardMeetingMembersView] No active DID found, creating identity as fallback for meeting setup", ); this.activeDid = await generateSaveAndActivateIdentity(); From b43ff58b71fc3aff4813354ec2b65da34aa7920d Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Mon, 18 Aug 2025 19:38:43 -0600 Subject: [PATCH 02/35] fix: Fix logging methods for iOS build. --- scripts/build-ios.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/build-ios.sh b/scripts/build-ios.sh index e9009715..511358d5 100755 --- a/scripts/build-ios.sh +++ b/scripts/build-ios.sh @@ -173,20 +173,20 @@ check_ios_resources() { # Check for required assets if [ ! -f "assets/icon.png" ]; then - log_warning "App icon not found at assets/icon.png" + log_warn "App icon not found at assets/icon.png" fi if [ ! -f "assets/splash.png" ]; then - log_warning "Splash screen not found at assets/splash.png" + log_warn "Splash screen not found at assets/splash.png" fi # Check for iOS-specific files if [ ! -f "ios/App/App/Info.plist" ]; then - log_warning "Info.plist not found" + log_warn "Info.plist not found" fi if [ ! -f "ios/App/App/AppDelegate.swift" ]; then - log_warning "AppDelegate.swift not found" + log_warn "AppDelegate.swift not found" fi log_success "iOS resource check completed" From 01b2f9e8c13303267f3bb2e95574d49894c0ab4c Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Mon, 18 Aug 2025 20:19:55 -0600 Subject: [PATCH 03/35] chore: Bump to version 1.0.7 build 40. --- BUILDING.md | 71 +++++++++------------------ CHANGELOG.md | 2 +- android/app/build.gradle | 4 +- ios/App/App.xcodeproj/project.pbxproj | 8 +-- package-lock.json | 4 +- package.json | 2 +- 6 files changed, 32 insertions(+), 59 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index e1e94fcd..571fd6c2 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1017,47 +1017,27 @@ If you need to build manually or want to understand the individual steps: export GEM_PATH=$shortened_path ``` -1. Build the web assets & update ios: +1. Bump the version in package.json, then here. - ```bash - rm -rf dist - npm run build:web - npm run build:capacitor - npx cap sync ios - ``` - - - If that fails with "Could not find..." then look at the "gem_path" instructions above. - -3. Copy the assets: - - ```bash - # It makes no sense why capacitor-assets will not run without these but it actually changes the contents. - mkdir -p ios/App/App/Assets.xcassets/AppIcon.appiconset - echo '{"images":[]}' > ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json - mkdir -p ios/App/App/Assets.xcassets/Splash.imageset - echo '{"images":[]}' > ios/App/App/Assets.xcassets/Splash.imageset/Contents.json - npx capacitor-assets generate --ios ``` - -4. Bump the version to match Android & package.json: - - ``` - cd ios/App && xcrun agvtool new-version 39 && perl -p -i -e "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 1.0.6;/g" App.xcodeproj/project.pbxproj && cd - + cd ios/App && xcrun agvtool new-version 40 && perl -p -i -e "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 1.0.7;/g" App.xcodeproj/project.pbxproj && cd - # Unfortunately this edits Info.plist directly. #xcrun agvtool new-marketing-version 0.4.5 ``` -5. Open the project in Xcode: +2. Build. - ```bash - npx cap open ios - ``` + Here's prod. Also available: test, dev + + ```bash + npm run build:ios:prod + ``` -6. Use Xcode to build and run on simulator or device. +3.1. Use Xcode to build and run on simulator or device. * Select Product -> Destination with some Simulator version. Then click the run arrow. -7. Release +3.2. Use Xcode to release. * Someday: Under "General" we want to rename a bunch of things to "Time Safari" * Choose Product -> Destination -> Any iOS Device @@ -1125,35 +1105,28 @@ The recommended way to build for Android is using the automated build script: #### Manual Build Process -1. Build the web assets: - - ```bash - rm -rf dist - npm run build:web - npm run build:capacitor - ``` - -2. Update Android project with latest build: +1. Bump the version in package.json, then here: android/app/build.gradle - ```bash - npx cap sync android - ``` + ```bash + perl -p -i -e 's/versionCode .*/versionCode 40/g' android/app/build.gradle + perl -p -i -e 's/versionName .*/versionName "1.0.7"/g' android/app/build.gradle + ``` -3. Copy the assets +2. Build. - ```bash - npx capacitor-assets generate --android - ``` + Here's prod. Also available: test, dev -4. Bump version to match iOS & package.json: android/app/build.gradle + ```bash + npm run build:android:prod + ``` -5. Open the project in Android Studio: +3. Open the project in Android Studio: ```bash npx cap open android ``` -6. Use Android Studio to build and run on emulator or device. +4. Use Android Studio to build and run on emulator or device. ## Android Build from the console diff --git a/CHANGELOG.md b/CHANGELOG.md index cf28e788..b16ef146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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 +## [1.0.7] - 2025.08.18 ### Changed - Photo is pinned to profile mode ### Fixed diff --git a/android/app/build.gradle b/android/app/build.gradle index a92af2db..57c34006 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -31,8 +31,8 @@ android { applicationId "app.timesafari.app" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 39 - versionName "1.0.6" + versionCode 40 + versionName "1.0.7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 381f4bab..5b57160c 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -403,7 +403,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 39; + CURRENT_PROJECT_VERSION = 40; DEVELOPMENT_TEAM = GM3FS5JQPH; ENABLE_APP_SANDBOX = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO; @@ -413,7 +413,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.6; + MARKETING_VERSION = 1.0.7; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = app.timesafari; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -430,7 +430,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 39; + CURRENT_PROJECT_VERSION = 40; DEVELOPMENT_TEAM = GM3FS5JQPH; ENABLE_APP_SANDBOX = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO; @@ -440,7 +440,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.6; + MARKETING_VERSION = 1.0.7; PRODUCT_BUNDLE_IDENTIFIER = app.timesafari; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; diff --git a/package-lock.json b/package-lock.json index d6914554..b152486e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "timesafari", - "version": "1.0.7-beta", + "version": "1.0.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "timesafari", - "version": "1.0.7-beta", + "version": "1.0.7", "dependencies": { "@capacitor-community/electron": "^5.0.1", "@capacitor-community/sqlite": "6.0.2", diff --git a/package.json b/package.json index bdb48dd0..c493198a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "timesafari", - "version": "1.0.7-beta", + "version": "1.0.7", "description": "Time Safari Application", "author": { "name": "Time Safari Team" From e6ce71362a3cd2a478bcfa04a8e059826ca0fd48 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Mon, 18 Aug 2025 20:26:05 -0600 Subject: [PATCH 04/35] chore: bump version and add "-beta" --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b152486e..f8c11390 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "timesafari", - "version": "1.0.7", + "version": "1.0.8-beta", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "timesafari", - "version": "1.0.7", + "version": "1.0.8-beta", "dependencies": { "@capacitor-community/electron": "^5.0.1", "@capacitor-community/sqlite": "6.0.2", diff --git a/package.json b/package.json index c493198a..1c685c2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "timesafari", - "version": "1.0.7", + "version": "1.0.8-beta", "description": "Time Safari Application", "author": { "name": "Time Safari Team" From b138f5cdaf0ab85896e20b366baffd4df1cbc74f Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Mon, 18 Aug 2025 20:37:15 -0600 Subject: [PATCH 05/35] doc: Fix BUILDING & CHANGELOG. --- BUILDING.md | 4 ++-- CHANGELOG.md | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 571fd6c2..e5abf069 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1159,9 +1159,9 @@ cd - At play.google.com/console: -- Go to the Testing Track (eg. Closed). +- Go to Production or the Closed Testing and either Create Track or Manage Track. - Click "Create new release". -- Upload the `aab` file. +- Upload the `aab` file from: app/build/outputs/bundle/release/app-release.aab - Hit "Next". - Save, go to "Publishing Overview" as prompted, and click "Send changes for review". diff --git a/CHANGELOG.md b/CHANGELOG.md index b16ef146..19209fb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,9 @@ 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.7] - 2025.08.18 -### Changed -- Photo is pinned to profile mode ### Fixed -- Deep link URLs (and other prod settings) -- Error in BVC begin view +- Deep link for onboard-meeting-members + ## [1.0.6] - 2025.08.09 ### Fixed From d39e21394c044b058f1c2ed5d2753b153b816540 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 19 Aug 2025 03:36:22 +0000 Subject: [PATCH 06/35] refactor(rules): consolidate type safety content and clean software development ruleset - Remove duplicate content and restore file integrity in software_development.mdc - Add comprehensive Type Safety Enforcement section to type_safety_guide.mdc - Clean up file structure and eliminate corruption from duplicate sections - Move type safety patterns and guidelines to appropriate specialized guide --- .../rules/development/type_safety_guide.mdc | 17 +++ .cursor/rules/software_development.mdc | 118 +++++++----------- 2 files changed, 59 insertions(+), 76 deletions(-) diff --git a/.cursor/rules/development/type_safety_guide.mdc b/.cursor/rules/development/type_safety_guide.mdc index 507e3f23..6dba1416 100644 --- a/.cursor/rules/development/type_safety_guide.mdc +++ b/.cursor/rules/development/type_safety_guide.mdc @@ -40,6 +40,23 @@ Practical rules to keep TypeScript strict and predictable. Minimize exceptions. - Avoid `(obj as any)[k]`. +## Type Safety Enforcement + +### Core Type Safety Rules +- **No `any` Types**: Use explicit types or `unknown` with proper type guards +- **Error Handling Uses Guards**: Implement and reuse type guards from `src/interfaces/**` +- **Dynamic Property Access**: Use `keyof` + `in` checks for type-safe property access + +### Type Guard Patterns +- **API Errors**: Use `isApiError(error)` guards for API error handling +- **Database Errors**: Use `isDatabaseError(error)` guards for database operations +- **Axios Errors**: Implement `isAxiosError(error)` guards for HTTP error handling + +### Implementation Guidelines +- **Avoid Type Assertions**: Replace `as any` with proper type guards and interfaces +- **Narrow Types Properly**: Use type guards to narrow `unknown` types safely +- **Document Type Decisions**: Explain complex type structures and their purpose + ## Minimal Special Cases (document in PR when used) - **Vue refs / instances**: Use `ComponentPublicInstance` or specific component diff --git a/.cursor/rules/software_development.mdc b/.cursor/rules/software_development.mdc index f84bd5a2..745317cd 100644 --- a/.cursor/rules/software_development.mdc +++ b/.cursor/rules/software_development.mdc @@ -1,6 +1,3 @@ ---- -alwaysApply: true ---- # Software Development Ruleset @@ -89,90 +86,59 @@ Specialized guidelines for software development tasks including code review, deb - [ ] Solution complexity justified by evidence - [ ] Simpler alternatives considered and documented - [ ] Impact on existing systems assessed -# Software Development Ruleset +- [ ] Dependencies validated and accessible +- [ ] Environment impact assessed for team members +- [ ] Pre-build validation implemented where appropriate -## Purpose -Specialized guidelines for software development tasks including code review, debugging, architecture decisions, and testing. +## Additional Core Principles -## Core Principles +### 4. Dependency Management & Environment Validation +- **Pre-build Validation**: Always validate critical dependencies before executing build scripts +- **Environment Consistency**: Ensure team members have identical development environments +- **Dependency Verification**: Check that required packages are installed and accessible +- **Path Resolution**: Use `npx` for local dependencies to avoid PATH issues -### 1. Evidence-First Development -- **Code Citations Required**: Always cite specific file:line references when making claims -- **Execution Path Tracing**: Trace actual code execution before proposing architectural changes -- **Assumption Validation**: Flag assumptions as "assumed" vs "evidence-based" +## Additional Required Workflows -### 2. Code Review Standards -- **Trace Before Proposing**: Always trace execution paths before suggesting changes -- **Evidence Over Inference**: Prefer code citations over logical deductions -- **Scope Validation**: Confirm the actual scope of problems before proposing solutions +### Dependency Validation (Before Proposing Changes) +- [ ] **Dependency Validation**: Verify all required dependencies are available and accessible -### 3. Problem-Solution Validation -- **Problem Scope**: Does the solution address the actual problem? -- **Evidence Alignment**: Does the solution match the evidence? -- **Complexity Justification**: Is added complexity justified by real needs? -- **Alternative Analysis**: What simpler solutions were considered? +### Environment Impact Assessment (During Solution Design) +- [ ] **Environment Impact**: Assess how changes affect team member setups -## Required Workflows +## Additional Competence Hooks -### Before Proposing Changes -- [ ] **Code Path Tracing**: Map execution flow from entry to exit -- [ ] **Evidence Collection**: Gather specific code citations and logs -- [ ] **Assumption Surfacing**: Identify what's proven vs. inferred -- [ ] **Scope Validation**: Confirm the actual extent of the problem +### Dependency & Environment Management +- **"What dependencies does this feature require and are they properly declared?"** +- **"How will this change affect team member development environments?"** +- **"What validation can we add to catch dependency issues early?"** -### During Solution Design -- [ ] **Evidence Alignment**: Ensure solution addresses proven problems -- [ ] **Complexity Assessment**: Justify any added complexity -- [ ] **Alternative Evaluation**: Consider simpler approaches first -- [ ] **Impact Analysis**: Assess effects on existing systems +## Dependency Management Best Practices -## Software-Specific Competence Hooks +### Pre-build Validation +- **Check Critical Dependencies**: Validate essential tools before executing build scripts +- **Use npx for Local Dependencies**: Prefer `npx tsx` over direct `tsx` to avoid PATH issues +- **Environment Consistency**: Ensure all team members have identical dependency versions -### Evidence Validation -- **"What code path proves this claim?"** -- **"How does data actually flow through the system?"** -- **"What am I assuming vs. what can I prove?"** +### Common Pitfalls +- **Missing npm install**: Team members cloning without running `npm install` +- **PATH Issues**: Direct command execution vs. npm script execution differences +- **Version Mismatches**: Different Node.js/npm versions across team members -### Code Tracing -- **"What's the execution path from user action to system response?"** -- **"Which components actually interact in this scenario?"** -- **"Where does the data originate and where does it end up?"** +### Validation Strategies +- **Dependency Check Scripts**: Implement pre-build validation for critical dependencies +- **Environment Requirements**: Document and enforce minimum Node.js/npm versions +- **Onboarding Checklist**: Standardize team member setup procedures -### Architecture Decisions -- **"What evidence shows this change is necessary?"** -- **"What simpler solution could achieve the same goal?"** -- **"How does this change affect the existing system architecture?"** - -## Integration with Other Rulesets - -### With base_context.mdc -- Inherits generic competence principles -- Adds software-specific evidence requirements -- Maintains collaboration and learning focus - -### With research_diagnostic.mdc -- Enhances investigation with code path tracing -- Adds evidence validation to diagnostic workflow -- Strengthens problem identification accuracy - -## Usage Guidelines +### Error Messages and Guidance +- **Specific Error Context**: Provide clear guidance when dependency issues occur +- **Actionable Solutions**: Direct users to specific commands (`npm install`, `npm run check:dependencies`) +- **Environment Diagnostics**: Implement comprehensive environment validation tools -### When to Use This Ruleset -- Code reviews and architectural decisions -- Bug investigation and debugging -- Performance optimization -- Feature implementation planning -- Testing strategy development - -### When to Combine with Others -- **base_context + software_development**: General development tasks -- **research_diagnostic + software_development**: Technical investigations -- **All three**: Complex architectural decisions or major refactoring +### Build Script Enhancements +- **Early Validation**: Check dependencies before starting build processes +- **Graceful Degradation**: Continue builds when possible but warn about issues +- **Helpful Tips**: Remind users about dependency management best practices -## Self-Check (model, before responding) -- [ ] Code path traced and documented -- [ ] Evidence cited with specific file:line references -- [ ] Assumptions clearly flagged as proven vs. inferred -- [ ] Solution complexity justified by evidence -- [ ] Simpler alternatives considered and documented -- [ ] Impact on existing systems assessed +- **Narrow Types Properly**: Use type guards to narrow `unknown` types safely +- **Document Type Decisions**: Explain complex type structures and their purpose From bc1214e9db26d78aeae9b3a2de8ce55c1ad7691b Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 19 Aug 2025 03:36:57 +0000 Subject: [PATCH 07/35] feat(dev): enhance development environment and dependency management - Add comprehensive environment setup documentation to README.md - Add check:dependencies npm script for environment validation - Update build scripts to use npx for local dependencies - Enhance Android build script with dependency validation - Add new check-dependencies.sh script for environment diagnostics --- README.md | 27 +++++++++ package.json | 5 +- scripts/build-android.sh | 34 +++++++++++ scripts/check-dependencies.sh | 110 ++++++++++++++++++++++++++++++++++ 4 files changed, 174 insertions(+), 2 deletions(-) create mode 100755 scripts/check-dependencies.sh diff --git a/README.md b/README.md index efc9b1ad..fc954fd5 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,33 @@ npm run assets:clean npm run build:native ``` +### Environment Setup & Dependencies + +Before building the application, ensure your development environment is properly +configured: + +```bash +# Install all dependencies (required first time and after updates) +npm install + +# Validate your development environment +npm run check:dependencies + +# Check prerequisites for testing +npm run test:prerequisites +``` + +**Common Issues & Solutions**: + +- **"tsx: command not found"**: Run `npm install` to install devDependencies +- **"capacitor-assets: command not found"**: Ensure `@capacitor/assets` is installed +- **Build failures**: Run `npm run check:dependencies` to diagnose environment issues + +**Required Versions**: +- Node.js: 18+ (LTS recommended) +- npm: 8+ (comes with Node.js) +- Platform-specific tools: Android Studio, Xcode (for mobile builds) + ### Platform Support - **Android**: Adaptive icons with foreground/background, monochrome support diff --git a/package.json b/package.json index 1c685c2b..e0548c68 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "type-check": "tsc --noEmit", "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js", "test:prerequisites": "node scripts/check-prerequisites.js", + "check:dependencies": "./scripts/check-dependencies.sh", "test:all": "npm run lint && tsc && npm run test:web && npm run test:mobile && ./scripts/test-safety-check.sh && echo '\n\n\nGotta add the performance tests'", "test:web": "npx playwright test -c playwright.config-local.ts --trace on", "test:mobile": "./scripts/test-mobile.sh", @@ -28,8 +29,8 @@ "build:capacitor": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode capacitor --config vite.config.capacitor.mts", "build:capacitor:sync": "npm run build:capacitor && npx cap sync", "build:native": "vite build && npx cap sync && npx capacitor-assets generate", - "assets:config": "tsx scripts/assets-config.ts", - "assets:validate": "tsx scripts/assets-validator.ts", + "assets:config": "npx tsx scripts/assets-config.ts", + "assets:validate": "npx tsx scripts/assets-validator.ts", "assets:clean": "rimraf android/app/src/main/res/mipmap-* ios/App/App/Assets.xcassets/**/AppIcon*.png ios/App/App/Assets.xcassets/**/Splash*.png || true", "build:ios": "./scripts/build-ios.sh", "build:ios:dev": "./scripts/build-ios.sh --dev", diff --git a/scripts/build-android.sh b/scripts/build-android.sh index c6c8ae88..c795a4b0 100755 --- a/scripts/build-android.sh +++ b/scripts/build-android.sh @@ -49,6 +49,31 @@ set -e # Source common utilities source "$(dirname "$0")/common.sh" +# Function to validate critical dependencies +validate_dependencies() { + log_info "Validating critical dependencies..." + + # Check if node_modules exists + if [ ! -d "node_modules" ]; then + log_error "node_modules directory not found. Please run 'npm install' first." + exit 1 + fi + + # Check if tsx is available + if [ ! -f "node_modules/.bin/tsx" ]; then + log_error "tsx dependency not found. Please run 'npm install' first." + exit 1 + fi + + # Check if capacitor-assets is available + if [ ! -f "node_modules/.bin/capacitor-assets" ]; then + log_error "capacitor-assets dependency not found. Please run 'npm install' first." + exit 1 + fi + + log_success "All critical dependencies validated successfully" +} + # Default values BUILD_MODE="development" BUILD_TYPE="debug" @@ -179,6 +204,11 @@ parse_android_args "$@" # Print build header print_header "TimeSafari Android Build Process" + +# Validate dependencies before proceeding +validate_dependencies + +# Log build start log_info "Starting Android build process at $(date)" log_info "Build mode: $BUILD_MODE" log_info "Build type: $BUILD_TYPE" @@ -257,6 +287,7 @@ fi # Step 1: Validate asset configuration safe_execute "Validating asset configuration" "npm run assets:validate" || { log_warn "Asset validation found issues, but continuing with build..." + log_info "If you encounter build failures, please run 'npm install' first to ensure all dependencies are available." } # Step 2: Clean Android app @@ -337,6 +368,9 @@ if [ "$OPEN_STUDIO" = true ]; then log_info "Android Studio: opened" fi +# Reminder about dependency management +log_info "💡 Tip: If you encounter dependency issues, run 'npm install' to ensure all packages are up to date." + print_footer "Android Build" # Exit with success diff --git a/scripts/check-dependencies.sh b/scripts/check-dependencies.sh new file mode 100755 index 00000000..c8e14e8b --- /dev/null +++ b/scripts/check-dependencies.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# check-dependencies.sh +# Author: Matthew Raymer +# Date: 2025-08-19 +# Description: Dependency validation script for TimeSafari development environment +# This script checks for critical dependencies required for building the application. + +# Exit on any error +set -e + +# Source common utilities +source "$(dirname "$0")/common.sh" + +print_header "TimeSafari Dependency Validation" + +log_info "Checking development environment dependencies..." + +# Check Node.js version +if command -v node &> /dev/null; then + NODE_VERSION=$(node --version) + log_info "Node.js version: $NODE_VERSION" + + # Extract major version number + MAJOR_VERSION=$(echo $NODE_VERSION | sed 's/v\([0-9]*\)\..*/\1/') + if [ "$MAJOR_VERSION" -lt 18 ]; then + log_error "Node.js version $NODE_VERSION is too old. Please upgrade to Node.js 18 or later." + exit 1 + fi +else + log_error "Node.js is not installed. Please install Node.js 18 or later." + exit 1 +fi + +# Check npm version +if command -v npm &> /dev/null; then + NPM_VERSION=$(npm --version) + log_info "npm version: $NPM_VERSION" +else + log_error "npm is not installed. Please install npm." + exit 1 +fi + +# Check if node_modules exists +if [ ! -d "node_modules" ]; then + log_error "node_modules directory not found." + log_info "Please run: npm install" + exit 1 +fi + +# Check critical dependencies +log_info "Validating critical packages..." + +CRITICAL_DEPS=("tsx" "capacitor-assets" "vite") + +for dep in "${CRITICAL_DEPS[@]}"; do + if [ -f "node_modules/.bin/$dep" ]; then + log_success "✓ $dep found" + else + log_error "✗ $dep not found in node_modules/.bin" + log_info "This usually means the package wasn't installed properly." + log_info "Try running: npm install" + exit 1 + fi +done + +# Check TypeScript via npx +if npx tsc --version &> /dev/null; then + TSC_VERSION=$(npx tsc --version) + log_success "✓ TypeScript found: $TSC_VERSION" +else + log_error "✗ TypeScript not accessible via npx" + log_info "Try running: npm install" + exit 1 +fi + +# Check Capacitor CLI +if command -v npx &> /dev/null; then + if npx cap --version &> /dev/null; then + CAP_VERSION=$(npx cap --version) + log_success "✓ Capacitor CLI version: $CAP_VERSION" + else + log_error "✗ Capacitor CLI not accessible via npx" + log_info "Try running: npm install @capacitor/cli" + exit 1 + fi +else + log_error "npx is not available. Please ensure npm is properly installed." + exit 1 +fi + +# Check Android development tools +if command -v adb &> /dev/null; then + log_success "✓ Android Debug Bridge (adb) found" +else + log_warn "⚠ Android Debug Bridge (adb) not found" + log_info "This is only needed for Android development and testing." +fi + +if command -v gradle &> /dev/null; then + GRADLE_VERSION=$(gradle --version | head -n 1) + log_success "✓ Gradle found: $GRADLE_VERSION" +else + log_warn "⚠ Gradle not found in PATH" + log_info "This is only needed if building outside of Android Studio." +fi + +log_success "Dependency validation completed successfully!" +log_info "Your development environment is ready for TimeSafari development." + +print_footer "Dependency Validation" From 9384f0083a16e726e749a214cf50e06f58f35a9a Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 19 Aug 2025 03:37:20 +0000 Subject: [PATCH 08/35] refactor(types): improve type safety and eliminate type assertions - Replace type assertions with proper type guards in ProfileService - Add isAxiosError type guard and improve error handling - Clean up formatting and improve type safety in deepLinks service - Remove type assertions in AccountViewView Vue component - Improve code formatting and consistency across services --- src/services/ProfileService.ts | 51 +++++++++++++++++++------- src/services/deepLinks.ts | 8 +++-- src/views/AccountViewView.vue | 66 ++++++++++++++++++++-------------- 3 files changed, 84 insertions(+), 41 deletions(-) diff --git a/src/services/ProfileService.ts b/src/services/ProfileService.ts index bdb27f46..c1779c71 100644 --- a/src/services/ProfileService.ts +++ b/src/services/ProfileService.ts @@ -127,10 +127,10 @@ export class ProfileService { logger.debug("Attempting to delete profile for DID:", activeDid); logger.debug("Using partner API server:", this.partnerApiServer); logger.debug("Request headers:", headers); - + const url = `${this.partnerApiServer}/api/partner/userProfile`; logger.debug("DELETE request URL:", url); - + const response = await this.axios.delete(url, { headers }); if (response.status === 200 || response.status === 204) { @@ -140,20 +140,22 @@ export class ProfileService { logger.error("Unexpected response status when deleting profile:", { status: response.status, statusText: response.statusText, - data: response.data + data: response.data, }); - throw new Error(`Profile not deleted - HTTP ${response.status}: ${response.statusText}`); + throw new Error( + `Profile not deleted - HTTP ${response.status}: ${response.statusText}`, + ); } } catch (error) { if (this.isApiError(error) && error.response) { - const response = error.response as any; // Type assertion for error response + const response = error.response; logger.error("API error deleting profile:", { status: response.status, statusText: response.statusText, data: response.data, - url: (error as any).config?.url + url: this.getErrorUrl(error), }); - + // Handle specific HTTP status codes if (response.status === 204) { logger.debug("Profile deleted successfully (204 No Content)"); @@ -163,7 +165,11 @@ export class ProfileService { return true; // Consider this a success if profile doesn't exist } else if (response.status === 400) { logger.error("Bad request when deleting profile:", response.data); - throw new Error(`Profile deletion failed: ${response.data?.message || 'Bad request'}`); + const errorMessage = + typeof response.data === "string" + ? response.data + : response.data?.message || "Bad request"; + throw new Error(`Profile deletion failed: ${errorMessage}`); } else if (response.status === 401) { logger.error("Unauthorized to delete profile"); throw new Error("You are not authorized to delete this profile"); @@ -172,7 +178,7 @@ export class ProfileService { throw new Error("You are not allowed to delete this profile"); } } - + logger.error("Error deleting profile:", errorStringForLog(error)); handleApiError(error as AxiosError, "/api/partner/userProfile"); return false; @@ -244,11 +250,32 @@ export class ProfileService { /** * Type guard for API errors */ - private isApiError( - error: unknown, - ): error is { response?: { status?: number } } { + private isApiError(error: unknown): error is { + response?: { + status?: number; + statusText?: string; + data?: { message?: string } | string; + }; + } { return typeof error === "object" && error !== null && "response" in error; } + + /** + * Extract URL from AxiosError without type casting + */ + private getErrorUrl(error: unknown): string | undefined { + if (this.isAxiosError(error)) { + return error.config?.url; + } + return undefined; + } + + /** + * Type guard for AxiosError + */ + private isAxiosError(error: unknown): error is AxiosError { + return error instanceof AxiosError; + } } /** diff --git a/src/services/deepLinks.ts b/src/services/deepLinks.ts index 8d94185d..ee6095bb 100644 --- a/src/services/deepLinks.ts +++ b/src/services/deepLinks.ts @@ -199,8 +199,10 @@ export class DeepLinkHandler { } // Continue with parameter validation as before... - const pathSchema = deepLinkPathSchemas[path as keyof typeof deepLinkPathSchemas]; - const querySchema = deepLinkQuerySchemas[path as keyof typeof deepLinkQuerySchemas]; + const pathSchema = + deepLinkPathSchemas[path as keyof typeof deepLinkPathSchemas]; + const querySchema = + deepLinkQuerySchemas[path as keyof typeof deepLinkQuerySchemas]; let validatedPathParams: Record = {}; let validatedQueryParams: Record = {}; @@ -235,7 +237,7 @@ export class DeepLinkHandler { await this.router.replace({ name: routeName, params: validatedPathParams, - query: validatedQueryParams + query: validatedQueryParams, }); } catch (error) { logger.error( diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index 1c38a8bb..f309fc6e 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -174,16 +174,18 @@ :aria-busy="loadingProfile || savingProfile" > -
- - - (Debug: {{ isMapReady ? 'Map Ready' : 'Map Loading' }}) -
+
+ + + (Debug: {{ isMapReady ? "Map Ready" : "Map Loading" }}) +

The location you choose will be shared with the world until you remove @@ -918,15 +920,18 @@ export default class AccountViewView extends Vue { created() { this.notify = createNotifyHelpers(this.$notify); - + // Fix Leaflet icon issues in modern bundlers // This prevents the "Cannot read properties of undefined (reading 'Default')" error if (L.Icon.Default) { - delete (L.Icon.Default.prototype as any)._getIconUrl; + delete (L.Icon.Default.prototype as { _getIconUrl?: unknown }) + ._getIconUrl; L.Icon.Default.mergeOptions({ - iconRetinaUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon-2x.png', - iconUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png', - shadowUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-shadow.png', + iconRetinaUrl: + "https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon-2x.png", + iconUrl: "https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png", + shadowUrl: + "https://unpkg.com/leaflet@1.7.1/dist/images/marker-shadow.png", }); } } @@ -955,7 +960,7 @@ export default class AccountViewView extends Vue { this.userProfileLatitude = profile.latitude; this.userProfileLongitude = profile.longitude; this.includeUserProfileLocation = profile.includeLocation; - + // Initialize map ready state if location is included if (profile.includeLocation) { this.isMapReady = false; // Will be set to true when map is ready @@ -1543,12 +1548,18 @@ export default class AccountViewView extends Vue { try { logger.debug("Map ready event fired, map object:", map); // doing this here instead of on the l-map element avoids a recentering after a drag then zoom at startup - const zoom = this.userProfileLatitude && this.userProfileLongitude ? 12 : 2; + const zoom = + this.userProfileLatitude && this.userProfileLongitude ? 12 : 2; const lat = this.userProfileLatitude || 0; const lng = this.userProfileLongitude || 0; map.setView([lat, lng], zoom); this.isMapReady = true; - logger.debug("Map ready state set to true, coordinates:", [lat, lng], "zoom:", zoom); + logger.debug( + "Map ready state set to true, coordinates:", + [lat, lng], + "zoom:", + zoom, + ); } catch (error) { logger.error("Error in onMapReady:", error); this.isMapReady = true; // Set to true even on error to prevent infinite loading @@ -1560,7 +1571,7 @@ export default class AccountViewView extends Vue { // Check if map ref is available const mapRef = this.$refs.profileMap; logger.debug("Map ref:", mapRef); - + // Try to set map ready after component is mounted setTimeout(() => { this.isMapReady = true; @@ -1597,9 +1608,9 @@ export default class AccountViewView extends Vue { longitude: this.userProfileLongitude, includeLocation: this.includeUserProfileLocation, }; - + logger.debug("Saving profile data:", profileData); - + const success = await this.profileService.saveProfile( this.activeDid, profileData, @@ -1628,7 +1639,7 @@ export default class AccountViewView extends Vue { this.userProfileLatitude = updated.latitude; this.userProfileLongitude = updated.longitude; this.includeUserProfileLocation = updated.includeLocation; - + // Reset map ready state when toggling location if (!updated.includeLocation) { this.isMapReady = false; @@ -1679,7 +1690,7 @@ export default class AccountViewView extends Vue { } } catch (error) { logger.error("Error in deleteProfile component method:", error); - + // Show more specific error message if available if (error instanceof Error) { this.notify.error(error.message); @@ -1710,7 +1721,10 @@ export default class AccountViewView extends Vue { onLocationCheckboxChange(): void { try { - logger.debug("Location checkbox changed, new value:", this.includeUserProfileLocation); + logger.debug( + "Location checkbox changed, new value:", + this.includeUserProfileLocation, + ); if (!this.includeUserProfileLocation) { // Location checkbox was unchecked, clean up map state this.isMapReady = false; @@ -1721,7 +1735,7 @@ export default class AccountViewView extends Vue { // Location checkbox was checked, start map initialization timeout this.isMapReady = false; logger.debug("Location checked, starting map initialization timeout"); - + // Try to set map ready after a short delay to allow Vue to render setTimeout(() => { if (!this.isMapReady) { @@ -1729,7 +1743,7 @@ export default class AccountViewView extends Vue { this.isMapReady = true; } }, 1000); // 1 second delay - + this.handleMapInitFailure(); } } catch (error) { From 8724f8bbe0161ee86339177e46d8d3db7aaa77f3 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 19 Aug 2025 03:41:30 +0000 Subject: [PATCH 09/35] fix: resolve CHANGELOG version mismatch and Android clean hanging issue - Fix CHANGELOG.md version from [1.0.7] to [1.0.8-beta] to match package.json - Replace problematic clean:android npm script with robust clean-android.sh script - Add timeout protection (30s) to prevent adb commands from hanging indefinitely - Include cross-platform timeout fallback using perl for macOS compatibility - Improve logging and error handling for Android cleanup process Fixes team member reported issues: - CHANGELOG version inconsistency - clean:android getting stuck during execution --- CHANGELOG.md | 2 +- package.json | 2 +- scripts/clean-android.sh | 62 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100755 scripts/clean-android.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 19209fb6..3c8febc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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.7] - 2025.08.18 +## [1.0.8-beta] - 2025.08.18 ### Fixed - Deep link for onboard-meeting-members diff --git a/package.json b/package.json index e0548c68..cfe759b1 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "build:electron:dmg:dev": "./scripts/build-electron.sh --dev --dmg", "build:electron:dmg:test": "./scripts/build-electron.sh --test --dmg", "build:electron:dmg:prod": "./scripts/build-electron.sh --prod --dmg", - "clean:android": "adb uninstall app.timesafari.app || true", + "clean:android": "./scripts/clean-android.sh", "clean:ios": "rm -rf ios/App/build ios/App/Pods ios/App/output ios/App/App/public ios/DerivedData ios/capacitor-cordova-ios-plugins ios/App/App/capacitor.config.json ios/App/App/config.xml || true", "clean:electron": "./scripts/build-electron.sh --clean", "clean:all": "npm run clean:ios && npm run clean:android && npm run clean:electron", diff --git a/scripts/clean-android.sh b/scripts/clean-android.sh new file mode 100755 index 00000000..4fa354af --- /dev/null +++ b/scripts/clean-android.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# clean-android.sh +# Author: Matthew Raymer +# Date: 2025-08-19 +# Description: Clean Android app with timeout protection to prevent hanging +# This script safely uninstalls the TimeSafari app from connected Android devices +# with a 30-second timeout to prevent indefinite hanging. + +# Exit on any error +set -e + +# Source common utilities +source "$(dirname "$0")/common.sh" + +# Function to implement timeout for systems without timeout command +timeout_command() { + local timeout_seconds="$1" + shift + + # Check if timeout command exists + if command -v timeout &> /dev/null; then + timeout "$timeout_seconds" "$@" + else + # Fallback for systems without timeout (like macOS) + # Use perl to implement timeout + perl -e ' + eval { + local $SIG{ALRM} = sub { die "timeout" }; + alarm shift; + system @ARGV; + alarm 0; + }; + if ($@) { exit 1; } + ' "$timeout_seconds" "$@" + fi +} + +log_info "Starting Android cleanup process..." + +# Check if adb is available +if ! command -v adb &> /dev/null; then + log_error "adb command not found. Please install Android SDK Platform Tools." + exit 1 +fi + +# Check for connected devices +log_info "Checking for connected Android devices..." +if adb devices | grep -q 'device$'; then + log_info "Android device(s) found. Attempting to uninstall app..." + + # Try to uninstall with timeout + if timeout_command 30 adb uninstall app.timesafari.app; then + log_success "Successfully uninstalled TimeSafari app" + else + log_warn "Uninstall failed or timed out after 30 seconds" + log_info "This is normal if the app wasn't installed or device is unresponsive" + fi +else + log_info "No Android devices connected. Skipping uninstall." +fi + +log_success "Android cleanup process completed" From 1666e77aa5e73c449eae99f249f80a6d82a066cd Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 19 Aug 2025 13:14:25 +0000 Subject: [PATCH 10/35] docs(rules): apply markdown standards and streamline rulesets - Apply markdown.mdc formatting to all ruleset files (80-char line length, proper spacing) - Update timesafari.mdc to reflect completed migration (remove triple migration pattern references) - Clean up corrupted logging_standards.mdc and restore proper content - Streamline architectural_decision_record.mdc for better readability - Update all file dates to 2025-08-19 for consistency - Add proper document headers and metadata to all ruleset files - Remove duplicate content and improve file organization - Maintain alwaysApply settings and glob patterns appropriately Files affected: 15 ruleset files across app/, database/, development/, features/, workflow/ directories --- .cursor/rules/adr_template.mdc | 10 +- .../app/architectural_decision_record.mdc | 282 +++++++++--- .cursor/rules/app/timesafari.mdc | 413 ++++++------------ .cursor/rules/asset_configuration.mdc | 49 ++- .cursor/rules/base_context.mdc | 198 +++------ .cursor/rules/database/absurd-sql.mdc | 47 +- .cursor/rules/database/legacy_dexie.mdc | 5 +- .../rules/development/type_safety_guide.mdc | 53 ++- .../rules/features/camera-implementation.mdc | 8 +- .../rules/investigation_report_example.mdc | 81 +++- .cursor/rules/logging_standards.mdc | 13 +- .cursor/rules/research_diagnostic.mdc | 4 + .cursor/rules/software_development.mdc | 148 ++++--- .cursor/rules/time.mdc | 329 ++++++++++++++ .cursor/rules/workflow/version_control.mdc | 324 +++++++++++--- 15 files changed, 1313 insertions(+), 651 deletions(-) create mode 100644 .cursor/rules/time.mdc diff --git a/.cursor/rules/adr_template.mdc b/.cursor/rules/adr_template.mdc index 8faeaf1c..ce75d9ab 100644 --- a/.cursor/rules/adr_template.mdc +++ b/.cursor/rules/adr_template.mdc @@ -2,14 +2,16 @@ ## ADR-XXXX-YY-ZZ: [Short Title] -**Date:** YYYY-MM-DD -**Status:** [PROPOSED | ACCEPTED | REJECTED | DEPRECATED | SUPERSEDED] -**Deciders:** [List of decision makers] +**Date:** YYYY-MM-DD +**Status:** [PROPOSED | ACCEPTED | REJECTED | DEPRECATED | SUPERSEDED] +**Deciders:** [List of decision makers] **Technical Story:** [Link to issue/PR if applicable] ## Context -[Describe the forces at play, including technological, political, social, and project local. These forces are probably in tension, and should be called out as such. The language in this section is value-neutral. It is simply describing facts.] +[Describe the forces at play, including technological, political, social, and +project local. These forces are probably in tension, and should be called out as +such. The language in this section is value-neutral. It is simply describing facts.] ## Decision diff --git a/.cursor/rules/app/architectural_decision_record.mdc b/.cursor/rules/app/architectural_decision_record.mdc index 9772de1f..91cd8e8d 100644 --- a/.cursor/rules/app/architectural_decision_record.mdc +++ b/.cursor/rules/app/architectural_decision_record.mdc @@ -1,10 +1,13 @@ --- -description: -globs: -alwaysApply: true +description: when you need to understand the system architecture or make changes that impact the system architecture +alwaysApply: false --- # TimeSafari Cross-Platform Architecture Guide +**Author**: Matthew Raymer +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Architecture guidelines + ## 1. Platform Support Matrix | Feature | Web (PWA) | Capacitor (Mobile) | Electron (Desktop) | @@ -15,11 +18,10 @@ alwaysApply: true | Camera Access | MediaDevices API | Capacitor Camera | Not Implemented | | Platform Detection | Web APIs | Capacitor.isNativePlatform() | process.env checks | ---- - ## 2. Project Structure ### Core Directories + ``` src/ ├── components/ # Vue components @@ -38,14 +40,13 @@ src/ ``` ### Entry Points + - `main.ts` → Base entry - `main.common.ts` → Shared init - `main.capacitor.ts` → Mobile entry - `main.electron.ts` → Electron entry - `main.web.ts` → Web entry ---- - ## 3. Service Architecture ### Service Organization @@ -64,28 +65,30 @@ services/ ``` ### Factory Pattern -Use a **singleton factory** to select platform services via `process.env.VITE_PLATFORM`. ---- +Use a **singleton factory** to select platform services via +`process.env.VITE_PLATFORM`. ## 4. Feature Guidelines ### QR Code Scanning + - Define `QRScannerService` interface. -- Implement platform-specific classes (`WebInlineQRScanner`, Capacitor, etc). +- Implement platform-specific classes (`WebInlineQRScanner`, Capacitor, + etc). - Provide `addListener` and `onStream` hooks for composability. ### Deep Linking + - URL format: `timesafari://[/][?query=value]` -- Web: `router.beforeEach` → parse query +- Web: `router.beforeEach` → parse query - Capacitor: `App.addListener("appUrlOpen", …)` ---- - ## 5. Build Process -- `vite.config.common.mts` → shared config -- Platform configs: `vite.config.web.mts`, `.capacitor.mts`, `.electron.mts` +- `vite.config.common.mts` → shared config +- Platform configs: `vite.config.web.mts`, `.capacitor.mts`, + `.electron.mts` - Use `process.env.VITE_PLATFORM` for conditional loading. ```bash @@ -94,78 +97,255 @@ npm run build:capacitor npm run build:electron ``` ---- - ## 6. Testing Strategy - **Unit tests** for services. -- **Playwright** for Web + Capacitor: - - `playwright.config-local.ts` includes web + Pixel 5. -- **Electron tests**: add `spectron` or Playwright-Electron. +- **Playwright** for Web + Capacitor: + - `playwright.config-local.ts` includes web + Pixel 5. +- **Electron tests**: add `spectron` or Playwright-Electron. - Mark tests with platform tags: ```ts test.skip(!process.env.MOBILE_TEST, "Mobile-only test"); ``` -> 🔗 **Human Hook:** Before merging new tests, hold a short sync (≤15 min) with QA to align on coverage and flaky test risks. - ---- +> 🔗 **Human Hook:** Before merging new tests, hold a short sync (≤15 +> min) with QA to align on coverage and flaky test risks. ## 7. Error Handling -- Global Vue error handler → logs with component name. -- Platform-specific wrappers log API errors with platform prefix (`[Capacitor API Error]`, etc). +- Global Vue error handler → logs with component name. +- Platform-specific wrappers log API errors with platform prefix + (`[Capacitor API Error]`, etc). - Use structured logging (not `console.log`). ---- - ## 8. Best Practices -- Keep platform code **isolated** in `platforms/`. +- Keep platform code **isolated** in `platforms/`. - Always define a **shared interface** first. -- Use feature detection, not platform detection, when possible. -- Dependency injection for services → improves testability. -- Maintain **Competence Hooks** in PRs (2–3 prompts for dev discussion). - ---- +- Use feature detection, not platform detection, when possible. +- Dependency injection for services → improves testability. +- Maintain **Competence Hooks** in PRs (2–3 prompts for dev + discussion). ## 9. Dependency Management -- Key deps: `@capacitor/core`, `electron`, `vue`. -- Use conditional `import()` for platform-specific libs. - ---- +- Key deps: `@capacitor/core`, `electron`, `vue`. +- Use conditional `import()` for platform-specific libs. ## 10. Security Considerations -- **Permissions**: Always check + request gracefully. -- **Storage**: Secure storage for sensitive data; encrypt when possible. -- **Audits**: Schedule quarterly security reviews. - ---- +- **Permissions**: Always check + request gracefully. +- **Storage**: Secure storage for sensitive data; encrypt when possible. +- **Audits**: Schedule quarterly security reviews. ## 11. ADR Process -- All major architecture choices → log in `doc/adr/`. -- Use ADR template with Context, Decision, Consequences, Status. -- Link related ADRs in PR descriptions. +- All major architecture choices → log in `doc/adr/`. +- Use ADR template with Context, Decision, Consequences, Status. +- Link related ADRs in PR descriptions. + +> 🔗 **Human Hook:** When proposing a new ADR, schedule a 30-min +> design sync for discussion, not just async review. + +## 12. Collaboration Hooks + +- **QR features**: Sync with Security before merging → permissions & + privacy. +- **New platform builds**: Demo in team meeting → confirm UX + differences. +- **Critical ADRs**: Present in guild or architecture review. -> 🔗 **Human Hook:** When proposing a new ADR, schedule a 30-min design sync for discussion, not just async review. +## Self-Check + +- [ ] Does this feature implement a shared interface? +- [ ] Are fallbacks + errors handled gracefully? +- [ ] Have relevant ADRs been updated/linked? +- [ ] Did I add competence hooks or prompts for the team? +- [ ] Was human interaction (sync/review/demo) scheduled? --- +**Status**: Active architecture guidelines +**Priority**: High +**Estimated Effort**: Ongoing reference +**Dependencies**: Vue 3, Capacitor, Electron, Vite +**Stakeholders**: Development team, Architecture team + +- [ ] Are fallbacks + errors handled gracefully? +- [ ] Have relevant ADRs been updated/linked? +- [ ] Did I add competence hooks or prompts for the team? +- [ ] Was human interaction (sync/review/demo) scheduled? +# TimeSafari Cross-Platform Architecture Guide + +**Author**: Matthew Raymer +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Architecture guidelines + +## 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 | + +## 2. Project Structure + +### Core Directories + +``` +src/ +├── components/ # Vue components +├── services/ # Platform services and business logic +├── views/ # Page components +├── router/ # Vue router configuration +├── types/ # TypeScript type definitions +├── utils/ # Utility functions +├── lib/ # Core libraries +├── platforms/ # Platform-specific implementations +├── electron/ # Electron-specific code +├── constants/ # Application constants +├── db/ # Database related code +├── interfaces/ # TypeScript interfaces +└── assets/ # Static assets +``` + +### Entry Points + +- `main.ts` → Base entry +- `main.common.ts` → Shared init +- `main.capacitor.ts` → Mobile entry +- `main.electron.ts` → Electron entry +- `main.web.ts` → Web entry + +## 3. Service Architecture + +### Service Organization + +```tree +services/ +├── QRScanner/ +│ ├── WebInlineQRScanner.ts +│ └── interfaces.ts +├── platforms/ +│ ├── WebPlatformService.ts +│ ├── CapacitorPlatformService.ts +│ └── ElectronPlatformService.ts +└── factory/ + └── PlatformServiceFactory.ts +``` + +### Factory Pattern + +Use a **singleton factory** to select platform services via +`process.env.VITE_PLATFORM`. + +## 4. Feature Guidelines + +### QR Code Scanning + +- Define `QRScannerService` interface. +- Implement platform-specific classes (`WebInlineQRScanner`, Capacitor, + etc). +- Provide `addListener` and `onStream` hooks for composability. + +### Deep Linking + +- URL format: `timesafari://[/][?query=value]` +- Web: `router.beforeEach` → parse query +- Capacitor: `App.addListener("appUrlOpen", …)` + +## 5. Build Process + +- `vite.config.common.mts` → shared config +- Platform configs: `vite.config.web.mts`, `.capacitor.mts`, + `.electron.mts` +- Use `process.env.VITE_PLATFORM` for conditional loading. + +```bash +npm run build:web +npm run build:capacitor +npm run build:electron +``` + +## 6. Testing Strategy + +- **Unit tests** for services. +- **Playwright** for Web + Capacitor: + - `playwright.config-local.ts` includes web + Pixel 5. +- **Electron tests**: add `spectron` or Playwright-Electron. +- Mark tests with platform tags: + + ```ts + test.skip(!process.env.MOBILE_TEST, "Mobile-only test"); + ``` + +> 🔗 **Human Hook:** Before merging new tests, hold a short sync (≤15 +> min) with QA to align on coverage and flaky test risks. + +## 7. Error Handling + +- Global Vue error handler → logs with component name. +- Platform-specific wrappers log API errors with platform prefix + (`[Capacitor API Error]`, etc). +- Use structured logging (not `console.log`). + +## 8. Best Practices + +- Keep platform code **isolated** in `platforms/`. +- Always define a **shared interface** first. +- Use feature detection, not platform detection, when possible. +- Dependency injection for services → improves testability. +- Maintain **Competence Hooks** in PRs (2–3 prompts for dev + discussion). + +## 9. Dependency Management + +- Key deps: `@capacitor/core`, `electron`, `vue`. +- Use conditional `import()` for platform-specific libs. + +## 10. Security Considerations + +- **Permissions**: Always check + request gracefully. +- **Storage**: Secure storage for sensitive data; encrypt when possible. +- **Audits**: Schedule quarterly security reviews. + +## 11. ADR Process + +- All major architecture choices → log in `doc/adr/`. +- Use ADR template with Context, Decision, Consequences, Status. +- Link related ADRs in PR descriptions. + +> 🔗 **Human Hook:** When proposing a new ADR, schedule a 30-min +> design sync for discussion, not just async review. + ## 12. Collaboration Hooks -- **QR features**: Sync with Security before merging → permissions & privacy. -- **New platform builds**: Demo in team meeting → confirm UX differences. -- **Critical ADRs**: Present in guild or architecture review. +- **QR features**: Sync with Security before merging → permissions & + privacy. +- **New platform builds**: Demo in team meeting → confirm UX + differences. +- **Critical ADRs**: Present in guild or architecture review. + +## Self-Check + +- [ ] Does this feature implement a shared interface? +- [ ] Are fallbacks + errors handled gracefully? +- [ ] Have relevant ADRs been updated/linked? +- [ ] Did I add competence hooks or prompts for the team? +- [ ] Was human interaction (sync/review/demo) scheduled? --- -# Self-Check +**Status**: Active architecture guidelines +**Priority**: High +**Estimated Effort**: Ongoing reference +**Dependencies**: Vue 3, Capacitor, Electron, Vite +**Stakeholders**: Development team, Architecture team -- [ ] Does this feature implement a shared interface? - [ ] Are fallbacks + errors handled gracefully? - [ ] Have relevant ADRs been updated/linked? - [ ] Did I add competence hooks or prompts for the team? diff --git a/.cursor/rules/app/timesafari.mdc b/.cursor/rules/app/timesafari.mdc index c32804be..ccc37996 100644 --- a/.cursor/rules/app/timesafari.mdc +++ b/.cursor/rules/app/timesafari.mdc @@ -1,316 +1,181 @@ ---- -description: -globs: -alwaysApply: true ---- # Time Safari Context +**Author**: Matthew Raymer +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Core application 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 makes it 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: +## Core Goals -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. -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, showing the impact + gifts make in people's lives. +## Technical Foundation -## Core Approaches +### Architecture -Time Safari should help everyday users build meaningful connections and organize -collective efforts by: +- **Privacy-preserving claims architecture** via endorser.ch +- **Decentralized Identifiers (DIDs)**: User identities based on + public/private key pairs stored on devices +- **Cryptographic Verification**: All claims and confirmations are + cryptographically signed +- **User-Controlled Visibility**: Users explicitly control who can see their + identifiers and data +- **Cross-Platform**: Web (PWA), Mobile (Capacitor), Desktop (Electron) -1. **Recognizing Contributions**: Creating permanent, verifiable records of gifts -and contributions people give to each other and their communities. +### Current Database State -2. **Facilitating Collaboration**: Making it ridiculously easy for people to ask -for or propose help on projects and interests that matter to them. +- **Database**: SQLite via Absurd SQL (browser) and native SQLite + (mobile/desktop) +- **Legacy Support**: IndexedDB (Dexie) for backward compatibility +- **Status**: Modern database architecture fully implemented -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. +### Core Technologies -4. **Preserving Privacy**: Ensuring personal identifiers are only shared with -explicitly authorized contacts, allowing private individuals including children -to participate safely. +- **Frontend**: Vue 3 + TypeScript + vue-facing-decorator +- **Styling**: TailwindCSS +- **Build**: Vite with platform-specific configs +- **Testing**: Playwright E2E, Jest unit tests +- **Database**: SQLite (Absurd SQL in browser), IndexedDB (legacy) +- **State**: Pinia stores +- **Platform Services**: Abstracted behind interfaces with factory pattern -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. +## Development Principles +### Code Organization -## Technical Foundation +- **Platform Services**: Abstract platform-specific code behind interfaces +- **Service Factory**: Use `PlatformServiceFactory` for platform selection +- **Type Safety**: Strict TypeScript, no `any` types, use type guards +- **Modern Architecture**: Use current platform service patterns -This application is built on a privacy-preserving claims architecture (via -endorser.ch) with these key characteristics: +### Architecture Patterns -- **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 +- **Dependency Injection**: Services injected via mixins and factory pattern +- **Interface Segregation**: Small, focused interfaces over large ones +- **Composition over Inheritance**: Prefer mixins and composition +- **Single Responsibility**: Each component/service has one clear purpose -## User Journey +### Testing Strategy -The typical progression of usage follows these stages: +- **E2E**: Playwright for critical user journeys +- **Unit**: Jest with F.I.R.S.T. principles +- **Platform Coverage**: Web + Capacitor (Pixel 5) in CI +- **Quality Assurance**: Comprehensive testing and validation -1. **Gratitude & Recognition**: Users begin by expressing and recording gratitude -for gifts received, building a foundation of acknowledgment. +## Current Development Focus -2. **Project Proposals**: Users propose projects and ideas, reaching out to connect -with others who share similar interests. +### Active Development -3. **Action Triggers**: Offers of help serve as triggers and motivations to execute -proposed projects, moving from ideas to action. +- **Feature Development**: Build new functionality using modern platform + services +- **Performance Optimization**: Improve app performance and user experience +- **Platform Enhancement**: Leverage platform-specific capabilities +- **Code Quality**: Maintain high standards and best practices -## Context for LLM Development +### Development Metrics -When developing new functionality for Time Safari, consider these design principles: +- **Code Quality**: High standards maintained across all platforms +- **Performance**: Optimized for all target devices +- **Testing**: Comprehensive coverage maintained +- **User Experience**: Focus on intuitive, accessible interfaces -1. **Accessibility First**: Features should be usable by non-technical users with -minimal learning curve. +## Platform-Specific Considerations -2. **Privacy by Design**: All features must respect user privacy and data sovereignty. +### Web (PWA) -3. **Progressive Enhancement**: Core functionality should work across all devices, -with richer experiences where supported. +- **QR Scanning**: WebInlineQRScanner +- **Deep Linking**: URL parameters +- **File System**: Limited browser APIs +- **Build**: `npm run build:web` (development build) -4. **Voluntary Collaboration**: The system should enable but never coerce participation. +### Mobile (Capacitor) -5. **Trust Building**: Features should help build verifiable trust between users. +- **QR Scanning**: @capacitor-mlkit/barcode-scanning +- **Deep Linking**: App URL open events +- **File System**: Capacitor Filesystem +- **Build**: `npm run build:capacitor` -6. **Network Effects**: Consider how features scale as more users join the platform. +### Desktop (Electron) -7. **Low Resource Requirements**: The system should be lightweight enough to run -on inexpensive devices users already own. +- **File System**: Node.js fs +- **Build**: `npm run build:electron` +- **Distribution**: AppImage, DEB, DMG packages -## Use Cases to Support +## Development Workflow + +### Build Commands -LLM development should focus on enhancing these key use cases: +```bash +# Web (development) +npm run build:web -1. **Community Building**: Tools that help people find others with shared -interests and values. +# Mobile +npm run build:capacitor +npm run build:native -2. **Project Coordination**: Features that make it easy to propose collaborative -projects and to submit suggestions and offers to existing ones. +# Desktop +npm run build:electron +npm run build:electron:appimage +npm run build:electron:deb +npm run build:electron:dmg +``` -3. **Reputation Building**: Methods for users to showcase their contributions -and reliability, in contexts where they explicitly reveal that information. +### Testing Commands -4. **Governance Experimentation**: Features that facilitate decision-making and -collective governance. +```bash +# Web E2E +npm run test:web -## Constraints - -When developing new features, be mindful of these constraints: +# Mobile +npm run test:mobile +npm run test:android +npm run test:ios + +# Type checking +npm run type-check +npm run lint-fix +``` + +## Key Constraints + +1. **Privacy First**: User identifiers remain private except when explicitly + shared +2. **Platform Compatibility**: Features must work across all target platforms +3. **Performance**: Must remain performant on older/simpler devices +4. **Modern Architecture**: New features should use current platform services +5. **Offline Capability**: Key functionality should work offline when feasible + +## Use Cases to Support + +1. **Community Building**: Tools for finding others with shared interests +2. **Project Coordination**: Easy proposal and collaboration on projects +3. **Reputation Building**: Showcasing contributions and reliability +4. **Governance**: Facilitating decision-making and collective governance + +## Resources + +- **Testing**: `docs/migration-testing/` +- **Architecture**: `docs/architecture-decisions.md` +- **Build Context**: `docs/build-modernization-context.md` + +--- -1. **Privacy Preservation**: User identifiers must remain private except when -explicitly shared. +## Status: Active application context -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. - -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. - -## Project Technologies - -- Typescript using ES6 classes using vue-facing-decorator -- TailwindCSS -- Vite Build Tool -- Playwright E2E testing -- IndexDB -- Camera, Image uploads, QR Code reader, ... - -## Mobile Features - -- Deep Linking -- Local Notifications via a custom Capacitor plugin - -## Project Architecture - -- 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 - - Implement service classes for shared business logic - - Use mixins for cross-cutting concerns - - Leverage TypeScript interfaces for shared type definitions - -- **Component Patterns** - - Create base components for common UI elements - - Implement higher-order components for shared behavior - - Use slot patterns for flexible component composition - - Create composable services for business logic - - Implement factory patterns for component creation - -- **State Management** - - Centralize state in Pinia stores - - Use computed properties for derived state - - Implement shared state selectors - - Create reusable state mutations - - Use action creators for common operations - -- **Error Handling** - - Implement centralized error handling - - Create reusable error components - - Use error boundary components - - Implement consistent error logging - - Create error type definitions - -- **Type Definitions** - - Create shared interfaces for common data structures - - Use type aliases for complex types - - Implement generic types for reusable components - - Create utility types for common patterns - - Use discriminated unions for state management - -- **API Integration** - - Create reusable API client classes - - Implement request/response interceptors - - Use consistent error handling patterns - - Create type-safe API endpoints - - Implement caching strategies - -- **Platform Services** - - Abstract platform-specific code behind interfaces - - Create platform-agnostic service layers - - Implement feature detection - - Use dependency injection for services - - Create service factories - -- **Testing** - - Create reusable test utilities - - Implement test factories - - 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 - - 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) - - Utilities should provide focused helper functions - -- **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 - -- **Liskov Substitution**: Objects should be replaceable with their subtypes - - Platform services should work consistently across web/mobile - - Authentication providers should be interchangeable - - Storage implementations should be swappable - -- **Interface Segregation**: Clients shouldn't depend on interfaces they don't use - - Break down large service interfaces into smaller, focused ones - - Component props should be minimal and purposeful - - Event emissions should be specific and targeted - -- **Dependency Inversion**: High-level modules shouldn't depend on low-level modules - - Use dependency injection for services - - Abstract platform-specific code behind interfaces - - 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 -- Implement facade patterns for subsystem access -- 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 -- Create higher-order components for common patterns -- 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 -- Use TypeScript interfaces for type definitions -- Implement role-based interfaces for different use cases - -### Fail Fast - -- Validate inputs early in the process -- Use TypeScript strict mode -- Implement comprehensive error handling -- Add runtime checks for critical operations -- Use assertions for development-time validation - -### Principle of Least Astonishment - -- Follow Vue.js conventions consistently -- Use familiar naming patterns -- Implement predictable component behaviors -- Maintain consistent error handling -- Keep UI interactions intuitive - -### Information Hiding - -- Encapsulate implementation details -- Use private class members -- Implement proper access modifiers -- Hide complex logic behind simple interfaces -- Use TypeScript's access modifiers effectively - -### Single Source of Truth - -- Use Pinia for state management -- Maintain one source for user data -- Centralize configuration management -- Use computed properties for derived state -- 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 +- **Priority**: Critical +- **Estimated Effort**: Ongoing reference +- **Dependencies**: Vue 3, TypeScript, SQLite, Capacitor, Electron +- **Stakeholders**: Development team, Product team diff --git a/.cursor/rules/asset_configuration.mdc b/.cursor/rules/asset_configuration.mdc index 916ecdd6..aa493fe9 100644 --- a/.cursor/rules/asset_configuration.mdc +++ b/.cursor/rules/asset_configuration.mdc @@ -1,32 +1,61 @@ --- -alwaysApply: true +description: when doing anything with capacitor assets +alwaysApply: false --- # Asset Configuration Directive -*Scope: Assets Only (icons, splashes, image pipelines) — not overall build orchestration* + +**Author**: Matthew Raymer +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Asset management guidelines + +*Scope: Assets Only (icons, splashes, image pipelines) — not overall build +orchestration* ## Intent + - Version **asset configuration files** (optionally dev-time generated). -- **Do not** version platform asset outputs (Android/iOS/Electron); generate them **at build-time** with standard tools. +- **Do not** version platform asset outputs (Android/iOS/Electron); generate + them **at build-time** with standard tools. - Keep existing per-platform build scripts unchanged. ## Source of Truth + - **Preferred (Capacitor default):** `resources/` as the single master source. -- **Alternative:** `assets/` is acceptable **only** if `capacitor-assets` is explicitly configured to read from it. -- **Never** maintain both `resources/` and `assets/` as parallel sources. Migrate and delete the redundant folder. +- **Alternative:** `assets/` is acceptable **only** if `capacitor-assets` is + explicitly configured to read from it. +- **Never** maintain both `resources/` and `assets/` as parallel sources. + Migrate and delete the redundant folder. ## Config Files + - Live under: `config/assets/` (committed). - Examples: - - `config/assets/capacitor-assets.config.json` (or the path the tool expects) + - `config/assets/capacitor-assets.config.json` (or the path the tool + expects) - `config/assets/android.assets.json` - `config/assets/ios.assets.json` - `config/assets/common.assets.yaml` (optional shared layer) -- **Dev-time generation allowed** for these configs; **build-time generation is forbidden**. +- **Dev-time generation allowed** for these configs; **build-time + generation is forbidden**. ## Build-Time Behavior + - Build generates platform assets (not configs) using the standard chain: - ```bash - npm run build:capacitor # web build via Vite (.mts) - npx cap sync + +```bash +npm run build:capacitor # web build via Vite (.mts) +npx cap sync +npx capacitor-assets generate # produces platform assets; not committed +# then platform-specific build steps +``` + +--- + +**Status**: Active asset management directive +**Priority**: Medium +**Estimated Effort**: Ongoing reference +**Dependencies**: capacitor-assets toolchain +**Stakeholders**: Development team, Build team + npx capacitor-assets generate # produces platform assets; not committed # then platform-specific build steps diff --git a/.cursor/rules/base_context.mdc b/.cursor/rules/base_context.mdc index 9600ba4b..4585c232 100644 --- a/.cursor/rules/base_context.mdc +++ b/.cursor/rules/base_context.mdc @@ -1,7 +1,6 @@ --- alwaysApply: true --- - ```json { "coaching_level": "standard", @@ -14,7 +13,12 @@ alwaysApply: true # Base Context — Human Competence First +**Author**: Matthew Raymer +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Core interaction guidelines + ## Purpose + All interactions must *increase the human's competence over time* while completing the task efficiently. The model may handle menial work and memory extension, but must also promote learning, autonomy, and healthy work habits. @@ -25,167 +29,79 @@ machine-driven steps. ## Principles -1) Competence over convenience: finish the task *and* leave the human more +1. Competence over convenience: finish the task *and* leave the human more capable next time. -2) Mentorship, not lectures: be concise, concrete, and immediately applicable. -3) Transparency: show assumptions, limits, and uncertainty; cite when non-obvious. -4) Optional scaffolding: include small, skimmable learning hooks that do not +2. Mentorship, not lectures: be concise, concrete, and immediately applicable. +3. Transparency: show assumptions, limits, and uncertainty; cite when + non-obvious. +4. Optional scaffolding: include small, skimmable learning hooks that do not bloat output. -5) Time respect: default to **lean output**; offer opt-in depth via toggles. -6) Psychological safety: encourage, never condescend; no medical/clinical advice. - No censorship! -7) Reusability: structure outputs so they can be saved, searched, reused, and repurposed. -8) **Collaborative Bias**: Favor solutions that invite human review, discussion, - and iteration. When in doubt, ask "Who should this be shown to?" or "Which human - input would improve this?" +5. Time respect: default to **lean output**; offer opt-in depth via toggles. +6. Psychological safety: encourage, never condescend; no medical/clinical + advice. No censorship! +7. Reusability: structure outputs so they can be saved, searched, reused, and + repurposed. +8. **Collaborative Bias**: Favor solutions that invite human review, + discussion, and iteration. When in doubt, ask "Who should this be shown + to?" or "Which human input would improve this?" ## Toggle Definitions ### coaching_level -Determines the depth of learning support: `light` (short hooks), `standard` -(balanced), `deep` (detailed). +Determines the depth of learning support: `light` (short hooks), +`standard` (balanced), `deep` (detailed). ### socratic_max_questions The number of clarifying questions the model may ask before proceeding. -If >0, questions should be targeted, minimal, and followed by reasonable assumptions if unanswered. +If >0, questions should be targeted, minimal, and followed by reasonable +assumptions if unanswered. ### verbosity -'terse' (just a sentence), `concise` (minimum commentary), `normal` (balanced explanation), or other project-defined levels. - -### timebox_minutes -*integer or null* — When set to a positive integer (e.g., `5`), this acts as a **time budget** guiding the model to prioritize delivering the most essential parts of the task within that constraint. -Behavior when set: -1. **Prioritize Core Output** — Deliver the minimum viable solution or result first. -2. **Limit Commentary** — Competence Hooks and Collaboration Hooks must be shorter than normal. -3. **Signal Skipped Depth** — Omitted details should be listed under *Deferred for depth*. -4. **Order by Value** — Start with blocking or high-value items, then proceed to nice-to-haves if budget allows. -If `null`, there is no timebox — the model can produce full-depth responses. - -### format_enforcement -`strict` (reject outputs with format drift) or `relaxed` (minor deviations acceptable). - -## Modes (select or combine) -- **Doer**: produce the artifact fast, minimal commentary. -- **Mentor**: add short "why/how" notes + next-step pointers. -- **Socratic**: ask up to N targeted questions when requirements are ambiguous. -- **Pair-Programmer/Pair-Writer**: explain tradeoffs as you implement. -- **Facilitator**: structure output to be reviewable, commentable, and ready for group discussion. - -Default: Doer + short Mentor notes. - -## Competence & Collaboration Levers (keep lightweight) -- "Why this works" (≤3 bullets) -- "Common pitfalls" (≤3 bullets) -- "Next skill unlock" (1 tiny action or reading) -- "Teach-back" (1 sentence prompt the human can answer to self-check) -- "Discussion prompts" (≤2 short questions for peers/stakeholders) - -## Output Contract (apply to every deliverable) -- Clear **Objective** (1 line) -- **Result** (artifact/code/answer) -- **Use/Run** (how to apply/test) -- **Competence Hooks** (the 4 learning levers above, kept terse) -- **Collaboration Hooks** (discussion prompts or group review steps) -- **Assumptions & Limits** -- **References** (if used; links or titles) - -## Do-Not -- No filler, hedging, or moralizing. -- No medical/mental-health advice; keep "healthy habits" to general work practices. -- No invented facts; mark uncertainty plainly. -- No censorship. -- Avoid outputs that bypass human review when such review is valuable. - -## Related Rulesets - -- **software_development.mdc**: For software-specific development practices -- **research_diagnostic.mdc**: For investigation and research workflows - -## Self-Check (model, before responding) -- [ ] Task done *and* at least one competence lever included (≤120 words total). -- [ ] At least one collaboration/discussion hook present. -- [ ] Output follows the **Output Contract** sections. -- [ ] Toggles respected; verbosity remains concise. -- [ ] Uncertainties/assumptions surfaced. -- [ ] No disallowed content. -- [ ] Uncertainties/assumptions surfaced. -- [ ] No disallowed content. -```json -{ - "coaching_level": "standard", - "socratic_max_questions": 7, - "verbosity": "normal", - "timebox_minutes": null, - "format_enforcement": "strict" -} -``` - -# Base Context — Human Competence First - -## Purpose -All interactions must *increase the human's competence over time* while -completing the task efficiently. The model may handle menial work and memory -extension, but must also promote learning, autonomy, and healthy work habits. -The model should also **encourage human interaction and collaboration** rather -than replacing it — outputs should be designed to **facilitate human discussion, -decision-making, and creativity**, not to atomize tasks into isolated, purely -machine-driven steps. - -## Principles - -1) Competence over convenience: finish the task *and* leave the human more - capable next time. -2) Mentorship, not lectures: be concise, concrete, and immediately applicable. -3) Transparency: show assumptions, limits, and uncertainty; cite when non-obvious. -4) Optional scaffolding: include small, skimmable learning hooks that do not - bloat output. -5) Time respect: default to **lean output**; offer opt-in depth via toggles. -6) Psychological safety: encourage, never condescend; no medical/clinical advice. - No censorship! -7) Reusability: structure outputs so they can be saved, searched, reused, and repurposed. -8) **Collaborative Bias**: Favor solutions that invite human review, discussion, - and iteration. When in doubt, ask "Who should this be shown to?" or "Which human - input would improve this?" - -## Toggle Definitions -### coaching_level +'terse' (just a sentence), `concise` (minimum commentary), `normal` +(balanced explanation), or other project-defined levels. -Determines the depth of learning support: `light` (short hooks), `standard` -(balanced), `deep` (detailed). +### timebox_minutes -### socratic_max_questions +*integer or null* — When set to a positive integer (e.g., `5`), this acts +as a **time budget** guiding the model to prioritize delivering the most +essential parts of the task within that constraint. -The number of clarifying questions the model may ask before proceeding. -If >0, questions should be targeted, minimal, and followed by reasonable assumptions if unanswered. +Behavior when set: -### verbosity -'terse' (just a sentence), `concise` (minimum commentary), `normal` (balanced explanation), or other project-defined levels. +1. **Prioritize Core Output** — Deliver the minimum viable solution or + result first. +2. **Limit Commentary** — Competence Hooks and Collaboration Hooks must be + shorter than normal. +3. **Signal Skipped Depth** — Omitted details should be listed under + *Deferred for depth*. +4. **Order by Value** — Start with blocking or high-value items, then + proceed to nice-to-haves if budget allows. -### timebox_minutes -*integer or null* — When set to a positive integer (e.g., `5`), this acts as a **time budget** guiding the model to prioritize delivering the most essential parts of the task within that constraint. -Behavior when set: -1. **Prioritize Core Output** — Deliver the minimum viable solution or result first. -2. **Limit Commentary** — Competence Hooks and Collaboration Hooks must be shorter than normal. -3. **Signal Skipped Depth** — Omitted details should be listed under *Deferred for depth*. -4. **Order by Value** — Start with blocking or high-value items, then proceed to nice-to-haves if budget allows. -If `null`, there is no timebox — the model can produce full-depth responses. +If `null`, there is no timebox — the model can produce full-depth +responses. ### format_enforcement -`strict` (reject outputs with format drift) or `relaxed` (minor deviations acceptable). + +`strict` (reject outputs with format drift) or `relaxed` (minor deviations +acceptable). ## Modes (select or combine) + - **Doer**: produce the artifact fast, minimal commentary. - **Mentor**: add short "why/how" notes + next-step pointers. -- **Socratic**: ask up to N targeted questions when requirements are ambiguous. +- **Socratic**: ask up to N targeted questions when requirements are + ambiguous. - **Pair-Programmer/Pair-Writer**: explain tradeoffs as you implement. -- **Facilitator**: structure output to be reviewable, commentable, and ready for group discussion. +- **Facilitator**: structure output to be reviewable, commentable, and + ready for group discussion. Default: Doer + short Mentor notes. ## Competence & Collaboration Levers (keep lightweight) + - "Why this works" (≤3 bullets) - "Common pitfalls" (≤3 bullets) - "Next skill unlock" (1 tiny action or reading) @@ -193,6 +109,7 @@ Default: Doer + short Mentor notes. - "Discussion prompts" (≤2 short questions for peers/stakeholders) ## Output Contract (apply to every deliverable) + - Clear **Objective** (1 line) - **Result** (artifact/code/answer) - **Use/Run** (how to apply/test) @@ -202,8 +119,10 @@ Default: Doer + short Mentor notes. - **References** (if used; links or titles) ## Do-Not + - No filler, hedging, or moralizing. -- No medical/mental-health advice; keep "healthy habits" to general work practices. +- No medical/mental-health advice; keep "healthy habits" to general work + practices. - No invented facts; mark uncertainty plainly. - No censorship. - Avoid outputs that bypass human review when such review is valuable. @@ -214,11 +133,22 @@ Default: Doer + short Mentor notes. - **research_diagnostic.mdc**: For investigation and research workflows ## Self-Check (model, before responding) -- [ ] Task done *and* at least one competence lever included (≤120 words total). + +- [ ] Task done *and* at least one competence lever included (≤120 words + total). - [ ] At least one collaboration/discussion hook present. - [ ] Output follows the **Output Contract** sections. - [ ] Toggles respected; verbosity remains concise. - [ ] Uncertainties/assumptions surfaced. - [ ] No disallowed content. + +--- + +**Status**: Active core guidelines +**Priority**: Critical +**Estimated Effort**: Ongoing reference +**Dependencies**: None (base ruleset) +**Stakeholders**: All AI interactions + - [ ] Uncertainties/assumptions surfaced. - [ ] No disallowed content. diff --git a/.cursor/rules/database/absurd-sql.mdc b/.cursor/rules/database/absurd-sql.mdc index e8b66e79..954fd8f7 100644 --- a/.cursor/rules/database/absurd-sql.mdc +++ b/.cursor/rules/database/absurd-sql.mdc @@ -1,13 +1,23 @@ --- -globs: **/db/databaseUtil.ts, **/interfaces/absurd-sql.d.ts, **/src/registerSQLWorker.js, **/services/AbsurdSqlDatabaseService.ts +globs: **/db/databaseUtil.ts, **/interfaces/absurd-sql.d.ts, **/src/registerSQLWorker.js, **/ +services/AbsurdSqlDatabaseService.ts alwaysApply: false --- # Absurd SQL - Cursor Development Guide +**Author**: Matthew Raymer +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Database development guidelines + ## Project Overview -Absurd SQL is a backend implementation for sql.js that enables persistent SQLite databases in the browser by using IndexedDB as a block storage system. This guide provides rules and best practices for developing with this project in Cursor. + +Absurd SQL is a backend implementation for sql.js that enables persistent +SQLite databases in the browser by using IndexedDB as a block storage system. +This guide provides rules and best practices for developing with this project +in Cursor. ## Project Structure + ``` absurd-sql/ ├── src/ # Source code @@ -20,36 +30,45 @@ absurd-sql/ ## Development Rules ### 1. Worker Thread Requirements + - All SQL operations MUST be performed in a worker thread - Main thread should only handle worker initialization and communication - Never block the main thread with database operations ### 2. Code Organization + - Keep worker code in separate files (e.g., `*.worker.js`) - Use ES modules for imports/exports - Follow the project's existing module structure ### 3. Required Headers + When developing locally or deploying, ensure these headers are set: + ``` Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp ``` ### 4. Browser Compatibility + - Primary target: Modern browsers with SharedArrayBuffer support - Fallback mode: Safari (with limitations) - Always test in both modes ### 5. Database Configuration + Recommended database settings: + ```sql PRAGMA journal_mode=MEMORY; PRAGMA page_size=8192; -- Optional, but recommended ``` ### 6. Development Workflow + 1. Install dependencies: + ```bash yarn add @jlongster/sql.js absurd-sql ``` @@ -60,17 +79,20 @@ PRAGMA page_size=8192; -- Optional, but recommended - `yarn serve` - Start development server ### 7. Testing Guidelines + - Write tests for both SharedArrayBuffer and fallback modes - Use Jest for testing - Include performance benchmarks for critical operations ### 8. Performance Considerations + - Use bulk operations when possible - Monitor read/write performance - Consider using transactions for multiple operations - Avoid unnecessary database connections ### 9. Error Handling + - Implement proper error handling for: - Worker initialization failures - Database connection issues @@ -78,18 +100,21 @@ PRAGMA page_size=8192; -- Optional, but recommended - Storage quota exceeded scenarios ### 10. Security Best Practices + - Never expose database operations directly to the client - Validate all SQL queries - Implement proper access controls - Handle sensitive data appropriately ### 11. Code Style + - Follow ESLint configuration - Use async/await for asynchronous operations - Document complex database operations - Include comments for non-obvious optimizations ### 12. Debugging + - Use `jest-debug` for debugging tests - Monitor IndexedDB usage in browser dev tools - Check worker communication in console @@ -98,6 +123,7 @@ PRAGMA page_size=8192; -- Optional, but recommended ## Common Patterns ### Worker Initialization + ```javascript // Main thread import { initBackend } from 'absurd-sql/dist/indexeddb-main-thread'; @@ -109,6 +135,7 @@ function init() { ``` ### Database Setup + ```javascript // Worker thread import initSqlJs from '@jlongster/sql.js'; @@ -130,6 +157,7 @@ async function setupDatabase() { ## Troubleshooting ### Common Issues + 1. SharedArrayBuffer not available - Check COOP/COEP headers - Verify browser support @@ -146,7 +174,20 @@ async function setupDatabase() { - Verify transaction usage ## Resources + +- [Project Demo](https://priceless-keller-d097e5.netlify.app/) +- [Example Project](https://github.com/jlongster/absurd-example-project) +- [Blog Post](https://jlongster.com/future-sql-web) +- [SQL.js Documentation](https://github.com/sql-js/sql.js/) + +--- + +**Status**: Active database development guidelines +**Priority**: High +**Estimated Effort**: Ongoing reference +**Dependencies**: Absurd SQL, SQL.js, IndexedDB +**Stakeholders**: Development team, Database team - [Project Demo](https://priceless-keller-d097e5.netlify.app/) - [Example Project](https://github.com/jlongster/absurd-example-project) - [Blog Post](https://jlongster.com/future-sql-web) -- [SQL.js Documentation](https://github.com/sql-js/sql.js/) \ No newline at end of file +- [SQL.js Documentation](https://github.com/sql-js/sql.js/) diff --git a/.cursor/rules/database/legacy_dexie.mdc b/.cursor/rules/database/legacy_dexie.mdc index 5ef07221..ac02aaba 100644 --- a/.cursor/rules/database/legacy_dexie.mdc +++ b/.cursor/rules/database/legacy_dexie.mdc @@ -2,4 +2,7 @@ globs: **/databaseUtil.ts,**/AccountViewView.vue,**/ContactsView.vue,**/DatabaseMigration.vue,**/NewIdentifierView.vue alwaysApply: false --- -All references in the codebase to Dexie apply only to migration from IndexedDb to Sqlite and will be deprecated in future versions. \ No newline at end of file +# What to do with Dexie + +All references in the codebase to Dexie apply only to migration from IndexedDb to +Sqlite and will be deprecated in future versions. diff --git a/.cursor/rules/development/type_safety_guide.mdc b/.cursor/rules/development/type_safety_guide.mdc index 6dba1416..54fd8b57 100644 --- a/.cursor/rules/development/type_safety_guide.mdc +++ b/.cursor/rules/development/type_safety_guide.mdc @@ -1,5 +1,5 @@ --- -globs: **/src/**/*,**/scripts/**/*,**/electron/**/* +description: when dealing with types and Typesript alwaysApply: false --- ```json @@ -15,8 +15,8 @@ alwaysApply: false # TypeScript Type Safety Guidelines **Author**: Matthew Raymer -**Date**: 2025-08-16 -**Status**: 🎯 **ACTIVE** +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Type safety enforcement ## Overview @@ -28,7 +28,8 @@ Practical rules to keep TypeScript strict and predictable. Minimize exceptions. - Use explicit types. If unknown, use `unknown` and **narrow** via guards. 2. **Error handling uses guards** - - Reuse guards from `src/interfaces/**` (e.g., `isDatabaseError`, `isApiError`). + - Reuse guards from `src/interfaces/**` (e.g., `isDatabaseError`, + `isApiError`). - Catch with `unknown`; never cast to `any`. 3. **Dynamic property access is type‑safe** @@ -43,26 +44,36 @@ Practical rules to keep TypeScript strict and predictable. Minimize exceptions. ## Type Safety Enforcement ### Core Type Safety Rules + - **No `any` Types**: Use explicit types or `unknown` with proper type guards -- **Error Handling Uses Guards**: Implement and reuse type guards from `src/interfaces/**` -- **Dynamic Property Access**: Use `keyof` + `in` checks for type-safe property access +- **Error Handling Uses Guards**: Implement and reuse type guards from + `src/interfaces/**` +- **Dynamic Property Access**: Use `keyof` + `in` checks for type-safe + property access ### Type Guard Patterns + - **API Errors**: Use `isApiError(error)` guards for API error handling -- **Database Errors**: Use `isDatabaseError(error)` guards for database operations -- **Axios Errors**: Implement `isAxiosError(error)` guards for HTTP error handling +- **Database Errors**: Use `isDatabaseError(error)` guards for database + operations +- **Axios Errors**: Implement `isAxiosError(error)` guards for HTTP error + handling ### Implementation Guidelines -- **Avoid Type Assertions**: Replace `as any` with proper type guards and interfaces -- **Narrow Types Properly**: Use type guards to narrow `unknown` types safely -- **Document Type Decisions**: Explain complex type structures and their purpose + +- **Avoid Type Assertions**: Replace `as any` with proper type guards and + interfaces +- **Narrow Types Properly**: Use type guards to narrow `unknown` types + safely +- **Document Type Decisions**: Explain complex type structures and their + purpose ## Minimal Special Cases (document in PR when used) -- **Vue refs / instances**: Use `ComponentPublicInstance` or specific component - types for dynamic refs. -- **3rd‑party libs without types**: Narrow immediately to a **known interface**; - do not leave `any` hanging. +- **Vue refs / instances**: Use `ComponentPublicInstance` or specific + component types for dynamic refs. +- **3rd‑party libs without types**: Narrow immediately to a **known + interface**; do not leave `any` hanging. ## Patterns (short) @@ -123,3 +134,15 @@ const keys = Object.keys(newSettings).filter( - TS Handbook — https://www.typescriptlang.org/docs/ - TS‑ESLint — https://typescript-eslint.io/rules/ - Vue 3 + TS — https://vuejs.org/guide/typescript/ + +--- + +**Status**: Active type safety guidelines +**Priority**: High +**Estimated Effort**: Ongoing reference +**Dependencies**: TypeScript, ESLint, Vue 3 +**Stakeholders**: Development team + +- TS Handbook — https://www.typescriptlang.org/docs/ +- TS‑ESLint — https://typescript-eslint.io/rules/ +- Vue 3 + TS — https://vuejs.org/guide/typescript/ diff --git a/.cursor/rules/features/camera-implementation.mdc b/.cursor/rules/features/camera-implementation.mdc index e7fef13c..afeb0e28 100644 --- a/.cursor/rules/features/camera-implementation.mdc +++ b/.cursor/rules/features/camera-implementation.mdc @@ -1,13 +1,13 @@ --- -description: -globs: +description: when dealing with cameras in the application alwaysApply: false --- # Camera Implementation Documentation ## Overview -This document describes how camera functionality is implemented across the TimeSafari application. The application uses cameras for two main purposes: +This document describes how camera functionality is implemented across the +TimeSafari application. The application uses cameras for two main purposes: 1. QR Code scanning 2. Photo capture @@ -219,4 +219,4 @@ Desktop implementation (currently unimplemented). - Multiple browsers - iOS and Android devices - Desktop platforms -- Various network conditions +- Various network conditions diff --git a/.cursor/rules/investigation_report_example.mdc b/.cursor/rules/investigation_report_example.mdc index fcce2b2f..ca3a7d36 100644 --- a/.cursor/rules/investigation_report_example.mdc +++ b/.cursor/rules/investigation_report_example.mdc @@ -1,76 +1,117 @@ # Investigation Report Example +**Author**: Matthew Raymer +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Investigation methodology example + ## Investigation — Registration Dialog Test Flakiness ## Objective -Identify root cause of flaky tests related to registration dialogs in contact import scenarios. + +Identify root cause of flaky tests related to registration dialogs in contact +import scenarios. ## System Map -- User action → ContactInputForm → ContactsView.addContact() → handleRegistrationPrompt() + +- User action → ContactInputForm → ContactsView.addContact() → + handleRegistrationPrompt() - setTimeout(1000ms) → Modal dialog → User response → Registration API call -- Test execution → Wait for dialog → Assert dialog content → Click response button +- Test execution → Wait for dialog → Assert dialog content → Click response + button ## Findings (Evidence) -- **1-second timeout causes flakiness** — evidence: `src/views/ContactsView.vue:971-1000`; setTimeout(..., 1000) in handleRegistrationPrompt() -- **Import flow bypasses dialogs** — evidence: `src/views/ContactImportView.vue:500-520`; importContacts() calls $insertContact() directly, no handleRegistrationPrompt() -- **Dialog only appears in direct add flow** — evidence: `src/views/ContactsView.vue:774-800`; addContact() calls handleRegistrationPrompt() after database insert + +- **1-second timeout causes flakiness** — evidence: + `src/views/ContactsView.vue:971-1000`; setTimeout(..., 1000) in + handleRegistrationPrompt() +- **Import flow bypasses dialogs** — evidence: + `src/views/ContactImportView.vue:500-520`; importContacts() calls + $insertContact() directly, no handleRegistrationPrompt() +- **Dialog only appears in direct add flow** — evidence: + `src/views/ContactsView.vue:774-800`; addContact() calls + handleRegistrationPrompt() after database insert ## Hypotheses & Failure Modes -- H1: 1-second timeout makes dialog appearance unpredictable; would fail when tests run faster than 1000ms -- H2: Test environment timing differs from development; watch for CI vs local test differences + +- H1: 1-second timeout makes dialog appearance unpredictable; would fail when + tests run faster than 1000ms +- H2: Test environment timing differs from development; watch for CI vs local + test differences ## Corrections -- Updated: "Multiple dialogs interfere with imports" → "Import flow never triggers dialogs - they only appear in direct contact addition" -- Updated: "Complex batch registration needed" → "Simple timeout removal and test mode flag sufficient" + +- Updated: "Multiple dialogs interfere with imports" → "Import flow never + triggers dialogs - they only appear in direct contact addition" +- Updated: "Complex batch registration needed" → "Simple timeout removal and + test mode flag sufficient" ## Diagnostics (Next Checks) + - [ ] Repro on CI environment vs local - [ ] Measure actual dialog appearance timing - [ ] Test with setTimeout removed - [ ] Verify import flow doesn't call handleRegistrationPrompt ## Risks & Scope -- Impacted: Contact addition tests, registration workflow tests; Data: None; Users: Test suite reliability + +- Impacted: Contact addition tests, registration workflow tests; Data: None; + Users: Test suite reliability ## Decision / Next Steps + - Owner: Development Team; By: 2025-01-28 -- Action: Remove 1-second timeout + add test mode flag; Exit criteria: Tests pass consistently +- Action: Remove 1-second timeout + add test mode flag; Exit criteria: Tests + pass consistently ## References + - `src/views/ContactsView.vue:971-1000` - `src/views/ContactImportView.vue:500-520` - `src/views/ContactsView.vue:774-800` ## Competence Hooks -- Why this works: Code path tracing revealed separate execution flows, evidence disproved initial assumptions -- Common pitfalls: Assuming related functionality without tracing execution paths, over-engineering solutions to imaginary problems -- Next skill: Learn to trace code execution before proposing architectural changes -- Teach-back: "What evidence shows that contact imports bypass registration dialogs?" ---- +- Why this works: Code path tracing revealed separate execution flows, + evidence disproved initial assumptions +- Common pitfalls: Assuming related functionality without tracing execution + paths, over-engineering solutions to imaginary problems +- Next skill: Learn to trace code execution before proposing architectural + changes +- Teach-back: "What evidence shows that contact imports bypass registration + dialogs?" ## Key Learning Points ### Evidence-First Approach + This investigation demonstrates the importance of: + 1. **Tracing actual code execution** rather than making assumptions 2. **Citing specific evidence** with file:line references 3. **Validating problem scope** before proposing solutions 4. **Considering simpler alternatives** before complex architectural changes ### Code Path Tracing Value + By tracing the execution paths, we discovered: + - Import flow and direct add flow are completely separate - The "multiple dialog interference" problem didn't exist - A simple timeout removal would solve the actual issue ### Prevention of Over-Engineering + The investigation prevented: + - Unnecessary database schema changes - Complex batch registration systems - Migration scripts for non-existent problems - Architectural changes based on assumptions -description: -globs: -alwaysApply: false + --- + +**Status**: Active investigation methodology +**Priority**: High +**Estimated Effort**: Ongoing reference +**Dependencies**: software_development.mdc +**Stakeholders**: Development team, QA team diff --git a/.cursor/rules/logging_standards.mdc b/.cursor/rules/logging_standards.mdc index 729f9a4d..2b9d6507 100644 --- a/.cursor/rules/logging_standards.mdc +++ b/.cursor/rules/logging_standards.mdc @@ -1,11 +1,7 @@ ---- -globs: *.vue,*.ts,*.tsx -alwaysApply: false ---- # Agent Contract — TimeSafari Logging (Unified, MANDATORY) **Author**: Matthew Raymer -**Date**: 2025-08-15 +**Date**: 2025-08-19 **Status**: 🎯 **ACTIVE** - Mandatory logging standards ## Overview @@ -220,6 +216,7 @@ logger.debug('[FeedFilters] Filter toggled', this.hasVisibleDid); --- **Status**: Active and enforced -**Last Updated**: 2025-08-15 08:11:46Z -**Version**: 1.0 -**Maintainer**: Matthew Raymer +**Priority**: Critical +**Estimated Effort**: Ongoing reference +**Dependencies**: TimeSafari logger utility +**Stakeholders**: Development team, Code review team diff --git a/.cursor/rules/research_diagnostic.mdc b/.cursor/rules/research_diagnostic.mdc index d249a300..d82c9097 100644 --- a/.cursor/rules/research_diagnostic.mdc +++ b/.cursor/rules/research_diagnostic.mdc @@ -31,6 +31,7 @@ steps—**not** code changes. ## Enhanced with Software Development Ruleset When investigating software issues, also apply: + - **Code Path Tracing**: Required for technical investigations - **Evidence Validation**: Ensure claims are code-backed - **Solution Complexity Assessment**: Justify architectural changes @@ -117,6 +118,7 @@ Copy/paste and fill: ## Code Path Tracing (Required for Software Investigations) Before proposing solutions, trace the actual execution path: + - [ ] **Entry Points**: Identify where the flow begins (user action, API call, etc.) - [ ] **Component Flow**: Map which components/methods are involved - [ ] **Data Path**: Track how data moves through the system @@ -136,11 +138,13 @@ Before proposing solutions, trace the actual execution path: ## Integration with Other Rulesets ### With software_development.mdc + - **Enhanced Evidence Validation**: Use code path tracing for technical investigations - **Architecture Assessment**: Apply complexity justification to proposed solutions - **Impact Analysis**: Assess effects on existing systems before recommendations ### With base_context.mdc + - **Competence Building**: Focus on technical investigation skills - **Collaboration**: Structure outputs for team review and discussion diff --git a/.cursor/rules/software_development.mdc b/.cursor/rules/software_development.mdc index 745317cd..ed60ff4e 100644 --- a/.cursor/rules/software_development.mdc +++ b/.cursor/rules/software_development.mdc @@ -1,66 +1,144 @@ # Software Development Ruleset +**Author**: Matthew Raymer +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Core development guidelines + ## Purpose -Specialized guidelines for software development tasks including code review, debugging, architecture decisions, and testing. + +Specialized guidelines for software development tasks including code review, +debugging, architecture decisions, and testing. ## Core Principles ### 1. Evidence-First Development -- **Code Citations Required**: Always cite specific file:line references when making claims -- **Execution Path Tracing**: Trace actual code execution before proposing architectural changes + +- **Code Citations Required**: Always cite specific file:line references when + making claims +- **Execution Path Tracing**: Trace actual code execution before proposing + architectural changes - **Assumption Validation**: Flag assumptions as "assumed" vs "evidence-based" ### 2. Code Review Standards -- **Trace Before Proposing**: Always trace execution paths before suggesting changes + +- **Trace Before Proposing**: Always trace execution paths before suggesting + changes - **Evidence Over Inference**: Prefer code citations over logical deductions -- **Scope Validation**: Confirm the actual scope of problems before proposing solutions +- **Scope Validation**: Confirm the actual scope of problems before proposing + solutions ### 3. Problem-Solution Validation + - **Problem Scope**: Does the solution address the actual problem? - **Evidence Alignment**: Does the solution match the evidence? - **Complexity Justification**: Is added complexity justified by real needs? - **Alternative Analysis**: What simpler solutions were considered? +### 4. Dependency Management & Environment Validation + +- **Pre-build Validation**: Always validate critical dependencies before executing + build scripts +- **Environment Consistency**: Ensure team members have identical development + environments +- **Dependency Verification**: Check that required packages are installed and + accessible +- **Path Resolution**: Use `npx` for local dependencies to avoid PATH issues + ## Required Workflows ### Before Proposing Changes + - [ ] **Code Path Tracing**: Map execution flow from entry to exit - [ ] **Evidence Collection**: Gather specific code citations and logs - [ ] **Assumption Surfacing**: Identify what's proven vs. inferred - [ ] **Scope Validation**: Confirm the actual extent of the problem +- [ ] **Dependency Validation**: Verify all required dependencies are available + and accessible ### During Solution Design + - [ ] **Evidence Alignment**: Ensure solution addresses proven problems - [ ] **Complexity Assessment**: Justify any added complexity - [ ] **Alternative Evaluation**: Consider simpler approaches first - [ ] **Impact Analysis**: Assess effects on existing systems +- [ ] **Environment Impact**: Assess how changes affect team member setups ## Software-Specific Competence Hooks ### Evidence Validation + - **"What code path proves this claim?"** - **"How does data actually flow through the system?"** - **"What am I assuming vs. what can I prove?"** ### Code Tracing + - **"What's the execution path from user action to system response?"** - **"Which components actually interact in this scenario?"** - **"Where does the data originate and where does it end up?"** ### Architecture Decisions + - **"What evidence shows this change is necessary?"** - **"What simpler solution could achieve the same goal?"** - **"How does this change affect the existing system architecture?"** +### Dependency & Environment Management + +- **"What dependencies does this feature require and are they properly + declared?"** +- **"How will this change affect team member development environments?"** +- **"What validation can we add to catch dependency issues early?"** + +## Dependency Management Best Practices + +### Pre-build Validation + +- **Check Critical Dependencies**: Validate essential tools before executing build + scripts +- **Use npx for Local Dependencies**: Prefer `npx tsx` over direct `tsx` to + avoid PATH issues +- **Environment Consistency**: Ensure all team members have identical dependency + versions + +### Common Pitfalls + +- **Missing npm install**: Team members cloning without running `npm install` +- **PATH Issues**: Direct command execution vs. npm script execution differences +- **Version Mismatches**: Different Node.js/npm versions across team members + +### Validation Strategies + +- **Dependency Check Scripts**: Implement pre-build validation for critical + dependencies +- **Environment Requirements**: Document and enforce minimum Node.js/npm versions +- **Onboarding Checklist**: Standardize team member setup procedures + +### Error Messages and Guidance + +- **Specific Error Context**: Provide clear guidance when dependency issues occur +- **Actionable Solutions**: Direct users to specific commands (`npm install`, + `npm run check:dependencies`) +- **Environment Diagnostics**: Implement comprehensive environment validation + tools + +### Build Script Enhancements + +- **Early Validation**: Check dependencies before starting build processes +- **Graceful Degradation**: Continue builds when possible but warn about issues +- **Helpful Tips**: Remind users about dependency management best practices + ## Integration with Other Rulesets ### With base_context.mdc + - Inherits generic competence principles - Adds software-specific evidence requirements - Maintains collaboration and learning focus ### With research_diagnostic.mdc + - Enhances investigation with code path tracing - Adds evidence validation to diagnostic workflow - Strengthens problem identification accuracy @@ -68,6 +146,7 @@ Specialized guidelines for software development tasks including code review, deb ## Usage Guidelines ### When to Use This Ruleset + - Code reviews and architectural decisions - Bug investigation and debugging - Performance optimization @@ -75,11 +154,13 @@ Specialized guidelines for software development tasks including code review, deb - Testing strategy development ### When to Combine with Others + - **base_context + software_development**: General development tasks - **research_diagnostic + software_development**: Technical investigations - **All three**: Complex architectural decisions or major refactoring ## Self-Check (model, before responding) + - [ ] Code path traced and documented - [ ] Evidence cited with specific file:line references - [ ] Assumptions clearly flagged as proven vs. inferred @@ -90,55 +171,10 @@ Specialized guidelines for software development tasks including code review, deb - [ ] Environment impact assessed for team members - [ ] Pre-build validation implemented where appropriate -## Additional Core Principles - -### 4. Dependency Management & Environment Validation -- **Pre-build Validation**: Always validate critical dependencies before executing build scripts -- **Environment Consistency**: Ensure team members have identical development environments -- **Dependency Verification**: Check that required packages are installed and accessible -- **Path Resolution**: Use `npx` for local dependencies to avoid PATH issues - -## Additional Required Workflows - -### Dependency Validation (Before Proposing Changes) -- [ ] **Dependency Validation**: Verify all required dependencies are available and accessible - -### Environment Impact Assessment (During Solution Design) -- [ ] **Environment Impact**: Assess how changes affect team member setups - -## Additional Competence Hooks - -### Dependency & Environment Management -- **"What dependencies does this feature require and are they properly declared?"** -- **"How will this change affect team member development environments?"** -- **"What validation can we add to catch dependency issues early?"** - -## Dependency Management Best Practices - -### Pre-build Validation -- **Check Critical Dependencies**: Validate essential tools before executing build scripts -- **Use npx for Local Dependencies**: Prefer `npx tsx` over direct `tsx` to avoid PATH issues -- **Environment Consistency**: Ensure all team members have identical dependency versions - -### Common Pitfalls -- **Missing npm install**: Team members cloning without running `npm install` -- **PATH Issues**: Direct command execution vs. npm script execution differences -- **Version Mismatches**: Different Node.js/npm versions across team members - -### Validation Strategies -- **Dependency Check Scripts**: Implement pre-build validation for critical dependencies -- **Environment Requirements**: Document and enforce minimum Node.js/npm versions -- **Onboarding Checklist**: Standardize team member setup procedures - -### Error Messages and Guidance -- **Specific Error Context**: Provide clear guidance when dependency issues occur -- **Actionable Solutions**: Direct users to specific commands (`npm install`, `npm run check:dependencies`) -- **Environment Diagnostics**: Implement comprehensive environment validation tools - -### Build Script Enhancements -- **Early Validation**: Check dependencies before starting build processes -- **Graceful Degradation**: Continue builds when possible but warn about issues -- **Helpful Tips**: Remind users about dependency management best practices +--- -- **Narrow Types Properly**: Use type guards to narrow `unknown` types safely -- **Document Type Decisions**: Explain complex type structures and their purpose +**Status**: Active development guidelines +**Priority**: High +**Estimated Effort**: Ongoing +**Dependencies**: base_context.mdc, research_diagnostic.mdc +**Stakeholders**: Development team diff --git a/.cursor/rules/time.mdc b/.cursor/rules/time.mdc new file mode 100644 index 00000000..61c962bb --- /dev/null +++ b/.cursor/rules/time.mdc @@ -0,0 +1,329 @@ +--- +alwaysApply: true +--- +# Time Handling in Development Workflow + +**Author**: Matthew Raymer +**Date**: 2025-08-17 +**Status**: 🎯 **ACTIVE** - Production Ready + +## Overview + +This guide establishes **how time should be referenced and used** across the +development workflow. It is not tied to any one project, but applies to **all +feature development, issue investigations, ADRs, and documentation**. + +## General Principles + +- **Explicit over relative**: Always prefer absolute dates (`2025-08-17`) over + relative references like "last week." +- **ISO 8601 Standard**: Use `YYYY-MM-DD` format for all date references in + docs, issues, ADRs, and commits. +- **Time zones**: Default to **UTC** unless explicitly tied to user-facing + behavior. +- **Precision**: Only specify as much precision as needed (date vs. datetime vs. + timestamp). +- **Consistency**: Align time references across ADRs, commits, and investigation + reports. + +## In Documentation & ADRs + +- Record decision dates using **absolute ISO dates**. +- For ongoing timelines, state start and end explicitly (e.g., `2025-08-01` → + `2025-08-17`). +- Avoid ambiguous terms like *recently*, *last month*, or *soon*. +- For time-based experiments (e.g., A/B tests), always include: + + - Start date + - Expected duration + - Review date checkpoint + +## In Code & Commits + +- Use **UTC timestamps** in logs, DB migrations, and serialized formats. +- In commits, link changes to **date-bound ADRs or investigation docs**. +- For migrations, include both **applied date** and **intended version window**. +- Use constants for known fixed dates; avoid hardcoding arbitrary strings. + +## In Investigations & Research + +- Capture **when** an issue occurred (absolute time or version tag). +- When describing failures: note whether they are **time-sensitive** (e.g., after + migrations, cache expirations). +- Record diagnostic timelines in ISO format (not relative). +- For performance regressions, annotate both **baseline timeframe** and + **measurement timeframe**. + +## Collaboration Hooks + +- During reviews, verify **time references are clear, absolute, and + standardized**. +- In syncs, reframe relative terms ("this week") into shared absolute + references. +- Tag ADRs with both **date created** and **review by** checkpoints. + +## Self-Check Before Submitting + +- [ ] Did I check the time using the **developer's actual system time and + timezone**? +- [ ] Am I using absolute ISO dates? +- [ ] Is UTC assumed unless specified otherwise? +- [ ] Did I avoid ambiguous relative terms? +- [ ] If duration matters, did I specify both start and end? +- [ ] For future work, did I include a review/revisit date? + +## Real-Time Context in Developer Interactions + +- The model must always resolve **"current time"** using the **developer's + actual system time and timezone**. +- When generating timestamps (e.g., in investigation logs, ADRs, or examples), + the model should: + + - Use the **developer's current local time** by default. + - Indicate the timezone explicitly (e.g., `2025-08-17T10:32-05:00`). + - Optionally provide UTC alongside if context requires cross-team clarity. + +- When interpreting relative terms like *now*, *today*, *last week*: + + - Resolve them against the **developer's current time**. + - Convert them into **absolute ISO-8601 values** in the output. + +## LLM Time Checking Instructions + +**CRITICAL**: The LLM must actively query the system for current time rather +than assuming or inventing times. + +### How to Check Current Time + +#### 1. **Query System Time (Required)** + +- **Always start** by querying the current system time using available tools +- **Never assume** what the current time is +- **Never use** placeholder values like "current time" or "now" + +#### 2. **Available Time Query Methods** + +- **System Clock**: Use `date` command or equivalent system time function +- **Programming Language**: Use language-specific time functions (e.g., + `Date.now()`, `datetime.now()`) +- **Environment Variables**: Check for time-related environment variables +- **API Calls**: Use time service APIs if available + +#### 3. **Required Time Information** + +When querying time, always obtain: + +- **Current Date**: YYYY-MM-DD format +- **Current Time**: HH:MM:SS format (24-hour) +- **Timezone**: Current system timezone or UTC offset +- **UTC Equivalent**: Convert local time to UTC for cross-team clarity + +#### 4. **Time Query Examples** + +```bash +# Example: Query system time +$ date +# Expected output: Mon Aug 17 10:32:45 EDT 2025 + +# Example: Query UTC time +$ date -u +# Expected output: Mon Aug 17 14:32:45 UTC 2025 +``` + +```python +# Example: Python time query +import datetime +current_time = datetime.datetime.now() +utc_time = datetime.datetime.utcnow() +print(f"Local: {current_time}") +print(f"UTC: {utc_time}") +``` + +```javascript +// Example: JavaScript time query +const now = new Date(); +const utc = new Date().toISOString(); +console.log(`Local: ${now}`); +console.log(`UTC: ${utc}`); +``` + +#### 5. **LLM Time Checking Workflow** + +1. **Query**: Actively query system for current time +2. **Validate**: Confirm time data is reasonable and current +3. **Format**: Convert to ISO 8601 format +4. **Context**: Provide both local and UTC times when helpful +5. **Document**: Show the source of time information + +#### 6. **Error Handling for Time Queries** + +- **If time query fails**: Ask user for current time or use "unknown time" + with explanation +- **If timezone unclear**: Default to UTC and ask for clarification +- **If time seems wrong**: Verify with user before proceeding +- **Always log**: Record when and how time was obtained + +#### 7. **Time Query Verification** + +Before using queried time, verify: + +- [ ] Time is recent (within last few minutes) +- [ ] Timezone information is available +- [ ] UTC conversion is accurate +- [ ] Format follows ISO 8601 standard + +## Model Behavior Rules + +- **Never invent a "fake now"**: All "current time" references must come from + the real system clock available at runtime. +- **Check developer time zone**: If ambiguous, ask for clarification (e.g., + "Should I use UTC or your local timezone?"). +- **Format for clarity**: + + - Local time: `YYYY-MM-DDTHH:mm±hh:mm` + - UTC equivalent (if needed): `YYYY-MM-DDTHH:mmZ` + +## Examples + +### Good + +- "Feature flag rollout started on `2025-08-01` and will be reviewed on + `2025-08-21`." +- "Migration applied on `2025-07-15T14:00Z`." +- "Issue reproduced on `2025-08-17T09:00-05:00 (local)` / + `2025-08-17T14:00Z (UTC)`." + +### Bad + +- "Feature flag rolled out last week." +- "Migration applied recently." +- "Now is August, so we assume this was last month." + +### More Examples + +#### Issue Reports + +- ✅ **Good**: "User reported login failure at `2025-08-17T14:30:00Z`. Issue + persisted until `2025-08-17T15:45:00Z`." +- ❌ **Bad**: "User reported login failure earlier today. Issue lasted for a + while." + +#### Release Planning + +- ✅ **Good**: "Feature X scheduled for release on `2025-08-25`. Testing + window: `2025-08-20` to `2025-08-24`." +- ❌ **Bad**: "Feature X will be released next week after testing." + +#### Performance Monitoring + +- ✅ **Good**: "Baseline performance measured on `2025-08-10T09:00:00Z`. + Regression detected on `2025-08-15T14:00:00Z`." +- ❌ **Bad**: "Performance was good last week but got worse this week." + +## Technical Implementation Notes + +### UTC Storage Principle + +- **Store all timestamps in UTC** in databases, logs, and serialized formats +- **Convert to local time only for user display** +- **Use ISO 8601 format** for all storage: `YYYY-MM-DDTHH:mm:ss.sssZ` + +### Common Implementation Patterns + +#### Database Storage + +```sql +-- ✅ Good: Store in UTC +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + +-- ❌ Bad: Store in local time +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +``` + +#### API Responses + +```json +// ✅ Good: Include both UTC and local time +{ + "eventTime": "2025-08-17T14:00:00Z", + "localTime": "2025-08-17T10:00:00-04:00", + "timezone": "America/New_York" +} + +// ❌ Bad: Only local time +{ + "eventTime": "2025-08-17T10:00:00-04:00" +} +``` + +#### Logging + +```python +# ✅ Good: Log in UTC with timezone info +logger.info(f"User action at {datetime.utcnow().isoformat()}Z (UTC)") + +# ❌ Bad: Log in local time +logger.info(f"User action at {datetime.now()}") +``` + +### Timezone Handling Best Practices + +#### 1. Always Store Timezone Information + +- Include IANA timezone identifier (e.g., `America/New_York`) +- Store UTC offset at time of creation +- Handle daylight saving time transitions automatically + +#### 2. User Display Considerations + +- Convert UTC to user's preferred timezone +- Show timezone abbreviation when helpful +- Use relative time for recent events ("2 hours ago") + +#### 3. Edge Case Handling + +- **Daylight Saving Time**: Use timezone-aware libraries +- **Leap Seconds**: Handle gracefully (rare but important) +- **Invalid Times**: Validate before processing + +### Common Mistakes to Avoid + +#### 1. Timezone Confusion + +- ❌ **Don't**: Assume server timezone is user timezone +- ✅ **Do**: Always convert UTC to user's local time for display + +#### 2. Format Inconsistency + +- ❌ **Don't**: Mix different time formats in the same system +- ✅ **Do**: Standardize on ISO 8601 for all storage + +#### 3. Relative Time References + +- ❌ **Don't**: Use relative terms in persistent storage +- ✅ **Do**: Convert relative terms to absolute timestamps immediately + +## References + +- [ISO 8601 Date and Time Standard](https://en.wikipedia.org/wiki/ISO_8601) +- [IANA Timezone Database](https://www.iana.org/time-zones) +- [ADR Template](./adr_template.md) +- [Research & Diagnostic Workflow](./research_diagnostic.mdc) + +--- + +**Rule of Thumb**: Every time reference in development artifacts should be +**clear in 6 months without context**, and aligned to the **developer's actual +current time**. + +**Technical Rule of Thumb**: **Store in UTC, display in local time, always +include timezone context.** + +--- + +**Status**: Active +**Version**: 1.0 +**Maintainer**: Matthew Raymer +**Next Review**: 2025-09-17 diff --git a/.cursor/rules/workflow/version_control.mdc b/.cursor/rules/workflow/version_control.mdc index 6ae30b64..6e619f5c 100644 --- a/.cursor/rules/workflow/version_control.mdc +++ b/.cursor/rules/workflow/version_control.mdc @@ -1,133 +1,306 @@ --- -alwaysApply: true +description: interacting with git +alwaysApply: false --- # Directive: Peaceful Co-Existence with Developers +**Author**: Matthew Raymer +**Date**: 2025-08-19 +**Status**: 🎯 **ACTIVE** - Version control guidelines + ## 1) Version-Control Ownership -* **MUST NOT** run `git add`, `git commit`, or any write action. -* **MUST** leave staging/committing to the developer. +- **MUST NOT** run `git add`, `git commit`, or any write action. +- **MUST** leave staging/committing to the developer. ## 2) Source of Truth for Commit Text -* **MUST** derive messages **only** from: - - * files **staged** for commit (primary), and - * files **awaiting staging** (context). -* **MUST** use the **diffs** to inform content. -* **MUST NOT** invent changes or imply work not present in diffs. +- **MUST** derive messages **only** from: + - files **staged** for commit (primary), and + - files **awaiting staging** (context). +- **MUST** use the **diffs** to inform content. +- **MUST NOT** invent changes or imply work not present in diffs. ## 3) Mandatory Preview Flow -* **ALWAYS** present, before any real commit: - - * file list + brief per-file notes, - * a **draft commit message** (copy-paste ready), - * nothing auto-applied. +- **ALWAYS** present, before any real commit: + - file list + brief per-file notes, + - a **draft commit message** (copy-paste ready), + - nothing auto-applied. ## 4) Version Synchronization Requirements -* **MUST** check for version changes in `package.json` before committing -* **MUST** ensure `CHANGELOG.md` is updated when `package.json` version changes -* **MUST** validate version format consistency between both files -* **MUST** include version bump commits in changelog with proper semantic versioning +- **MUST** check for version changes in `package.json` before committing +- **MUST** ensure `CHANGELOG.md` is updated when `package.json` version + changes +- **MUST** validate version format consistency between both files +- **MUST** include version bump commits in changelog with proper semantic + versioning ### Version Sync Checklist (Before Commit) - [ ] `package.json` version matches latest `CHANGELOG.md` entry -- [ ] New version follows semantic versioning (MAJOR.MINOR.PATCH[-PRERELEASE]) +- [ ] New version follows semantic versioning + (MAJOR.MINOR.PATCH[-PRERELEASE]) - [ ] Changelog entry includes all significant changes since last version -- [ ] Version bump commit message follows `build(version): bump to X.Y.Z` format +- [ ] Version bump commit message follows `build(version): bump to X.Y.Z` + format - [ ] Breaking changes properly documented with migration notes - [ ] Alert developer in chat message that version has been updated ### Version Change Detection -* **Check for version changes** in staged/unstaged `package.json` -* **Alert developer** if version changed but changelog not updated -* **Suggest changelog update** with proper format and content -* **Validate semantic versioning** compliance +- **Check for version changes** in staged/unstaged `package.json` +- **Alert developer** if version changed but changelog not updated +- **Suggest changelog update** with proper format and content +- **Validate semantic versioning** compliance ### Implementation Notes -* **Version Detection**: Compare `package.json` version field with latest changelog entry -* **Semantic Validation**: Ensure version follows `X.Y.Z[-PRERELEASE]` format -* **Changelog Format**: Follow [Keep a Changelog](https://keepachangelog.com/) standards -* **Breaking Changes**: Use `!` in commit message and `BREAKING CHANGE:` in changelog -* **Pre-release Versions**: Include beta/alpha/rc suffixes in both files consistently +- **Version Detection**: Compare `package.json` version field with latest + changelog entry +- **Semantic Validation**: Ensure version follows `X.Y.Z[-PRERELEASE]` + format +- **Changelog Format**: Follow [Keep a Changelog](https://keepachangelog.com/) + standards +- **Breaking Changes**: Use `!` in commit message and `BREAKING CHANGE:` + in changelog +- **Pre-release Versions**: Include beta/alpha/rc suffixes in both files + consistently ---- - -# Commit Message Format (Normative) +## Commit Message Format (Normative) -## A. Subject Line (required) +### A. Subject Line (required) ``` ():

``` -* **type** (lowercase, Conventional Commits): `feat|fix|refactor|perf|docs|test|build|chore|ci|revert` -* **scope**: optional module/package/area (e.g., `api`, `ui/login`, `db`) -* **!**: include when a breaking change is introduced -* **summary**: imperative mood, ≤ 72 chars, no trailing period +- **type** (lowercase, Conventional Commits): + `feat|fix|refactor|perf|docs|test|build|chore|ci|revert` +- **scope**: optional module/package/area (e.g., `api`, `ui/login`, `db`) +- **!**: include when a breaking change is introduced +- **summary**: imperative mood, ≤ 72 chars, no trailing period **Examples** -* `fix(api): handle null token in refresh path` -* `feat(ui/login)!: require OTP after 3 failed attempts` +- `fix(api): handle null token in refresh path` +- `feat(ui/login)!: require OTP after 3 failed attempts` -## B. Body (optional, when it adds non-obvious value) +### B. Body (optional, when it adds non-obvious value) -* One blank line after subject. -* Wrap at \~72 chars. -* Explain **what** and **why**, not line-by-line “how”. -* Include brief notes like tests passing or TS/lint issues resolved **only if material**. +- One blank line after subject. +- Wrap at ~72 chars. +- Explain **what** and **why**, not line-by-line "how". +- Include brief notes like tests passing or TS/lint issues resolved + **only if material**. **Body checklist** -* [ ] Problem/symptom being addressed -* [ ] High-level approach or rationale -* [ ] Risks, tradeoffs, or follow-ups (if any) +- [ ] Problem/symptom being addressed +- [ ] High-level approach or rationale +- [ ] Risks, tradeoffs, or follow-ups (if any) -## C. Footer (optional) +### C. Footer (optional) -* Issue refs: `Closes #123`, `Refs #456` -* Breaking change (alternative to `!`): +- Issue refs: `Closes #123`, `Refs #456` +- Breaking change (alternative to `!`): `BREAKING CHANGE: ` -* Authors: `Co-authored-by: Name ` -* Security: `CVE-XXXX-YYYY: ` (if applicable) - ---- +- Authors: `Co-authored-by: Name ` +- Security: `CVE-XXXX-YYYY: ` (if applicable) ## Content Guidance ### Include (when relevant) -* Specific fixes/features delivered -* Symptoms/problems fixed -* Brief note that tests passed or TS/lint errors resolved +- Specific fixes/features delivered +- Symptoms/problems fixed +- Brief note that tests passed or TS/lint errors resolved ### Avoid -* Vague: *improved, enhanced, better* -* Trivialities: tiny docs, one-liners, pure lint cleanups (separate, focused commits if needed) -* Redundancy: generic blurbs repeated across files -* Multi-purpose dumps: keep commits **narrow and focused** -* Long explanations that good inline code comments already cover +- Vague: *improved, enhanced, better* +- Trivialities: tiny docs, one-liners, pure lint cleanups (separate, + focused commits if needed) +- Redundancy: generic blurbs repeated across files +- Multi-purpose dumps: keep commits **narrow and focused** +- Long explanations that good inline code comments already cover + +**Guiding Principle:** Let code and inline docs speak. Use commits to +highlight what isn't obvious. + +## Copy-Paste Templates + +### Minimal (no body) + +```text +(): +``` + +### Standard (with body & footer) + +```text +(): + + + + + +Closes # +BREAKING CHANGE: +Co-authored-by: +``` -**Guiding Principle:** Let code and inline docs speak. Use commits to highlight what isn’t obvious. +## Assistant Output Checklist (before showing the draft) + +- [ ] List changed files + 1–2 line notes per file +- [ ] Provide **one** focused draft message (subject/body/footer) +- [ ] Subject ≤ 72 chars, imperative mood, correct `type(scope)!` syntax +- [ ] Body only if it adds non-obvious value +- [ ] No invented changes; aligns strictly with diffs +- [ ] Render as a single copy-paste block for the developer --- -# Copy-Paste Templates +**Status**: Active version control guidelines +**Priority**: High +**Estimated Effort**: Ongoing reference +**Dependencies**: git, package.json, CHANGELOG.md +**Stakeholders**: Development team, AI assistants + +- [ ] No invented changes; aligns strictly with diffs +- [ ] Render as a single copy-paste block for the developer + +## 1) Version-Control Ownership + +- **MUST NOT** run `git add`, `git commit`, or any write action. +- **MUST** leave staging/committing to the developer. + +## 2) Source of Truth for Commit Text + +- **MUST** derive messages **only** from: + - files **staged** for commit (primary), and + - files **awaiting staging** (context). +- **MUST** use the **diffs** to inform content. +- **MUST NOT** invent changes or imply work not present in diffs. + +## 3) Mandatory Preview Flow + +- **ALWAYS** present, before any real commit: + - file list + brief per-file notes, + - a **draft commit message** (copy-paste ready), + - nothing auto-applied. + +## 4) Version Synchronization Requirements + +- **MUST** check for version changes in `package.json` before committing +- **MUST** ensure `CHANGELOG.md` is updated when `package.json` version + changes +- **MUST** validate version format consistency between both files +- **MUST** include version bump commits in changelog with proper semantic + versioning + +### Version Sync Checklist (Before Commit) + +- [ ] `package.json` version matches latest `CHANGELOG.md` entry +- [ ] New version follows semantic versioning + (MAJOR.MINOR.PATCH[-PRERELEASE]) +- [ ] Changelog entry includes all significant changes since last version +- [ ] Version bump commit message follows `build(version): bump to X.Y.Z` + format +- [ ] Breaking changes properly documented with migration notes +- [ ] Alert developer in chat message that version has been updated + +### Version Change Detection + +- **Check for version changes** in staged/unstaged `package.json` +- **Alert developer** if version changed but changelog not updated +- **Suggest changelog update** with proper format and content +- **Validate semantic versioning** compliance + +### Implementation Notes + +- **Version Detection**: Compare `package.json` version field with latest + changelog entry +- **Semantic Validation**: Ensure version follows `X.Y.Z[-PRERELEASE]` + format +- **Changelog Format**: Follow [Keep a Changelog](https://keepachangelog.com/) + standards +- **Breaking Changes**: Use `!` in commit message and `BREAKING CHANGE:` + in changelog +- **Pre-release Versions**: Include beta/alpha/rc suffixes in both files + consistently + +## Commit Message Format (Normative) + +### A. Subject Line (required) + +``` +(): +``` + +- **type** (lowercase, Conventional Commits): + `feat|fix|refactor|perf|docs|test|build|chore|ci|revert` +- **scope**: optional module/package/area (e.g., `api`, `ui/login`, `db`) +- **!**: include when a breaking change is introduced +- **summary**: imperative mood, ≤ 72 chars, no trailing period + +**Examples** -## Minimal (no body) +- `fix(api): handle null token in refresh path` +- `feat(ui/login)!: require OTP after 3 failed attempts` + +### B. Body (optional, when it adds non-obvious value) + +- One blank line after subject. +- Wrap at ~72 chars. +- Explain **what** and **why**, not line-by-line "how". +- Include brief notes like tests passing or TS/lint issues resolved + **only if material**. + +**Body checklist** + +- [ ] Problem/symptom being addressed +- [ ] High-level approach or rationale +- [ ] Risks, tradeoffs, or follow-ups (if any) + +### C. Footer (optional) + +- Issue refs: `Closes #123`, `Refs #456` +- Breaking change (alternative to `!`): + `BREAKING CHANGE: ` +- Authors: `Co-authored-by: Name ` +- Security: `CVE-XXXX-YYYY: ` (if applicable) + +## Content Guidance + +### Include (when relevant) + +- Specific fixes/features delivered +- Symptoms/problems fixed +- Brief note that tests passed or TS/lint errors resolved + +### Avoid + +- Vague: *improved, enhanced, better* +- Trivialities: tiny docs, one-liners, pure lint cleanups (separate, + focused commits if needed) +- Redundancy: generic blurbs repeated across files +- Multi-purpose dumps: keep commits **narrow and focused** +- Long explanations that good inline code comments already cover + +**Guiding Principle:** Let code and inline docs speak. Use commits to +highlight what isn't obvious. + +## Copy-Paste Templates + +### Minimal (no body) ```text (): ``` -## Standard (with body & footer) +### Standard (with body & footer) ```text (): @@ -141,13 +314,22 @@ BREAKING CHANGE: Co-authored-by: ``` +## Assistant Output Checklist (before showing the draft) + +- [ ] List changed files + 1–2 line notes per file +- [ ] Provide **one** focused draft message (subject/body/footer) +- [ ] Subject ≤ 72 chars, imperative mood, correct `type(scope)!` syntax +- [ ] Body only if it adds non-obvious value +- [ ] No invented changes; aligns strictly with diffs +- [ ] Render as a single copy-paste block for the developer + --- -# Assistant Output Checklist (before showing the draft) +**Status**: Active version control guidelines +**Priority**: High +**Estimated Effort**: Ongoing reference +**Dependencies**: git, package.json, CHANGELOG.md +**Stakeholders**: Development team, AI assistants -* [ ] List changed files + 1–2 line notes per file -* [ ] Provide **one** focused draft message (subject/body/footer) -* [ ] Subject ≤ 72 chars, imperative mood, correct `type(scope)!` syntax -* [ ] Body only if it adds non-obvious value * [ ] No invented changes; aligns strictly with diffs * [ ] Render as a single copy-paste block for the developer From c80ded9e6dad79e0b99464c864b4a73cf61fe516 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Tue, 19 Aug 2025 19:43:24 -0600 Subject: [PATCH 11/35] fix: CHANGELOG version --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c8febc6..19209fb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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.8-beta] - 2025.08.18 +## [1.0.7] - 2025.08.18 ### Fixed - Deep link for onboard-meeting-members From fe08db1e95eeccb95ad796c79d50642e8b8b0bc6 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Tue, 19 Aug 2025 19:55:33 -0600 Subject: [PATCH 12/35] doc: Fix a remaining merge. --- .../rules/development/type_safety_guide.mdc | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/.cursor/rules/development/type_safety_guide.mdc b/.cursor/rules/development/type_safety_guide.mdc index faee146b..9c23938a 100644 --- a/.cursor/rules/development/type_safety_guide.mdc +++ b/.cursor/rules/development/type_safety_guide.mdc @@ -44,7 +44,7 @@ Practical rules to keep TypeScript strict and predictable. Minimize exceptions. ## Type Safety Enforcement ### Core Type Safety Rules -<<<<<<< HEAD + - **No `any` Types**: Use explicit types or `unknown` with proper type guards - **Error Handling Uses Guards**: Implement and reuse type guards from `src/interfaces/**` - **Dynamic Property Access**: Use `keyof` + `in` checks for type-safe property access @@ -58,31 +58,6 @@ Practical rules to keep TypeScript strict and predictable. Minimize exceptions. - **Avoid Type Assertions**: Replace `as any` with proper type guards and interfaces - **Narrow Types Properly**: Use type guards to narrow `unknown` types safely - **Document Type Decisions**: Explain complex type structures and their purpose -======= - -- **No `any` Types**: Use explicit types or `unknown` with proper type guards -- **Error Handling Uses Guards**: Implement and reuse type guards from - `src/interfaces/**` -- **Dynamic Property Access**: Use `keyof` + `in` checks for type-safe - property access - -### Type Guard Patterns - -- **API Errors**: Use `isApiError(error)` guards for API error handling -- **Database Errors**: Use `isDatabaseError(error)` guards for database - operations -- **Axios Errors**: Implement `isAxiosError(error)` guards for HTTP error - handling - -### Implementation Guidelines - -- **Avoid Type Assertions**: Replace `as any` with proper type guards and - interfaces -- **Narrow Types Properly**: Use type guards to narrow `unknown` types - safely -- **Document Type Decisions**: Explain complex type structures and their - purpose ->>>>>>> master ## Minimal Special Cases (document in PR when used) From 7d73e09de71a3fea31c52bced40e5065ce6585ad Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Tue, 19 Aug 2025 19:56:54 -0600 Subject: [PATCH 13/35] doc: Fix merge conflict. --- .cursor/rules/software_development.mdc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.cursor/rules/software_development.mdc b/.cursor/rules/software_development.mdc index 5eb25ac7..2f7c2c71 100644 --- a/.cursor/rules/software_development.mdc +++ b/.cursor/rules/software_development.mdc @@ -171,7 +171,6 @@ debugging, architecture decisions, and testing. - [ ] Environment impact assessed for team members - [ ] Pre-build validation implemented where appropriate -<<<<<<< HEAD ## Additional Core Principles ### 4. Dependency Management & Environment Validation @@ -224,12 +223,3 @@ debugging, architecture decisions, and testing. - **Narrow Types Properly**: Use type guards to narrow `unknown` types safely - **Document Type Decisions**: Explain complex type structures and their purpose -======= ---- - -**Status**: Active development guidelines -**Priority**: High -**Estimated Effort**: Ongoing -**Dependencies**: base_context.mdc, research_diagnostic.mdc -**Stakeholders**: Development team ->>>>>>> master From e73b00572a9de2f75c170d201724c2a47833960e Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 02:26:33 +0000 Subject: [PATCH 14/35] fix(env): resolve malformed comment in .env.test causing shell export errors - Fix multi-line comment spanning lines 12-13 that broke shell parsing - Consolidate comment into single line to prevent export syntax errors - Resolves "export: ' production).=': not a valid identifier" build failure Fixes test environment build blocking issue --- .env.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.test b/.env.test index 5776e66c..dd3d755c 100644 --- a/.env.test +++ b/.env.test @@ -7,7 +7,7 @@ VITE_LOG_LEVEL=info TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app # This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not - production). +# 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=https://test-api.endorser.ch From 618b822c8b38a408ea65b26e4bce760b9e989432 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 02:27:03 +0000 Subject: [PATCH 15/35] fix(services): remove duplicate getErrorUrl method from ProfileService - Remove duplicate method implementation causing TypeScript compilation errors - Consolidate error URL extraction logic into single method - Fix duplicate function implementation errors TS2393 Improves code quality and prevents build failures --- src/services/ProfileService.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/services/ProfileService.ts b/src/services/ProfileService.ts index 62a85970..815c7c87 100644 --- a/src/services/ProfileService.ts +++ b/src/services/ProfileService.ts @@ -255,32 +255,27 @@ export class ProfileService { } /** - * Extract URL from AxiosError without type casting + * Extract error URL safely from error object */ private getErrorUrl(error: unknown): string | undefined { if (this.isAxiosError(error)) { return error.config?.url; } + if (this.isApiError(error) && (error as any).config) { + const config = (error as any).config as { url?: string }; + return config.url; + } return undefined; } + + /** * Type guard for AxiosError */ private isAxiosError(error: unknown): error is AxiosError { return error instanceof AxiosError; } - - /** - * Extract error URL safely from error object - */ - private getErrorUrl(error: unknown): string | undefined { - if (this.isApiError(error) && error.config) { - const config = error.config as { url?: string }; - return config.url; - } - return undefined; - } } /** From 8386804bbd4318cd4a5f8464a47b06cb15b17983 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 02:29:09 +0000 Subject: [PATCH 16/35] feat(build): add comprehensive ESBuild error handling to Vite configurations - Add ESBuild logLevel: 'error' to all Vite configs - Configure logOverride for critical errors: duplicate-export, duplicate-member, syntax-error, invalid-identifier - Ensure builds fail immediately on ESBuild compilation errors - Apply to common, web, and optimized Vite configurations Prevents broken code from being deployed due to build-time errors --- vite.config.common.mts | 17 ++++++++++++++++- vite.config.optimized.mts | 6 +++++- vite.config.utils.mts | 24 ++++++++++++++++++++++++ vite.config.web.mts | 11 +++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/vite.config.common.mts b/vite.config.common.mts index f34e26d8..198f6ba3 100644 --- a/vite.config.common.mts +++ b/vite.config.common.mts @@ -6,7 +6,6 @@ import path from "path"; import { fileURLToPath } from 'url'; // Load environment variables -console.log('NODE_ENV:', process.env.NODE_ENV) dotenv.config({ path: `.env.${process.env.NODE_ENV}` }) @@ -53,6 +52,22 @@ export async function createBuildConfig(platform: string): Promise { format: 'es', plugins: () => [] }, + // ESBuild configuration to fail on errors + esbuild: { + target: 'es2015', + supported: { + 'bigint': true + }, + // Fail on any ESBuild errors + logLevel: 'error', + // Ensure build fails on syntax errors and other critical issues + logOverride: { + 'duplicate-export': 'error', + 'duplicate-member': 'error', + 'syntax-error': 'error', + 'invalid-identifier': 'error' + } + }, define: { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), diff --git a/vite.config.optimized.mts b/vite.config.optimized.mts index 5005ac5a..e9b4ee1d 100644 --- a/vite.config.optimized.mts +++ b/vite.config.optimized.mts @@ -135,7 +135,11 @@ export async function createOptimizedBuildConfig(mode: string): Promise { "dexie-export-import/dist/import/index.js", }, }; +} + +/** + * Shared ESBuild configuration that ensures builds fail on errors + */ +export function getStrictESBuildConfig() { + return { + target: 'es2015', + supported: { + 'bigint': true + }, + // Fail on any ESBuild errors + logLevel: 'error' as const, + // Ensure build fails on syntax errors and other critical issues + logOverride: { + 'duplicate-export': 'error', + 'duplicate-member': 'error', + 'syntax-error': 'error', + 'invalid-identifier': 'error' + }, + // Additional strict settings + keepNames: false, + minifyIdentifiers: false + }; } \ No newline at end of file diff --git a/vite.config.web.mts b/vite.config.web.mts index 79f5ec9c..0bbeb204 100644 --- a/vite.config.web.mts +++ b/vite.config.web.mts @@ -94,6 +94,17 @@ export default defineConfig(async ({ mode }) => { 'absurd-sql/dist/indexeddb-main-thread', 'absurd-sql/dist/indexeddb-backend' ] + }, + // ESBuild configuration to fail on errors + esbuild: { + target: 'es2015', + supported: { + 'bigint': true + }, + // Fail on any ESBuild errors + logLevel: 'error', + // Ensure build fails on syntax errors + logOverride: { 'duplicate-export': 'error' } } }); }); From a37fb51876c88662caa4e8ac3a7345ef4754e098 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 02:30:34 +0000 Subject: [PATCH 17/35] chore(android): update Android Gradle plugin from 8.12.0 to 8.12.1 - Update com.android.tools.build:gradle dependency to latest patch version - Addresses Android Studio update prompt for build tool security - Minor version bump for stability and bug fixes Keeps Android build tools current and secure --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 858b0bc0..4bd6375d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.12.0' + classpath 'com.android.tools.build:gradle:8.12.1' classpath 'com.google.gms:google-services:4.4.0' // NOTE: Do not place your application dependencies here; they belong From fbcd3a50ca465aff622e19f1864ad19fa291689a Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 06:40:48 +0000 Subject: [PATCH 18/35] feat: implement dynamic platform entry point system - Add src/main.ts as dynamic entry point that loads platform-specific code - Update index.html to use dynamic main.ts instead of hardcoded main.web.ts - Remove external capacitor config from vite.config.common.mts to ensure proper bundling - Enables consistent platform detection across all build targets - Use proper logger utility instead of console.log for platform detection logging --- index.html | 2 +- src/main.ts | 26 ++++++++++++++++++++++++++ vite.config.common.mts | 4 ---- 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 src/main.ts diff --git a/index.html b/index.html index d2ce14a5..d276108b 100644 --- a/index.html +++ b/index.html @@ -11,6 +11,6 @@
- + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 00000000..a58becb7 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,26 @@ +/** + * @file Dynamic Main Entry Point + * @author Matthew Raymer + * + * This file dynamically loads the appropriate platform-specific main entry point + * based on the current environment and build configuration. + */ + +import { logger } from "./utils/logger"; + +// Check the platform from environment variables +const platform = process.env.VITE_PLATFORM || "web"; + +logger.info(`[Main] 🚀 Loading TimeSafari for platform: ${platform}`); + +// Dynamically import the appropriate main entry point +if (platform === "capacitor") { + logger.info(`[Main] 📱 Loading Capacitor-specific entry point`); + import("./main.capacitor"); +} else if (platform === "electron") { + logger.info(`[Main] 💻 Loading Electron-specific entry point`); + import("./main.electron"); +} else { + logger.info(`[Main] 🌐 Loading Web-specific entry point`); + import("./main.web"); +} diff --git a/vite.config.common.mts b/vite.config.common.mts index 198f6ba3..848b3b9c 100644 --- a/vite.config.common.mts +++ b/vite.config.common.mts @@ -8,7 +8,6 @@ import { fileURLToPath } from 'url'; // Load environment variables dotenv.config({ path: `.env.${process.env.NODE_ENV}` }) - const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -36,9 +35,6 @@ export async function createBuildConfig(platform: string): Promise { assetsDir: 'assets', chunkSizeWarningLimit: 1000, rollupOptions: { - external: isNative - ? ['@capacitor/app'] - : [], output: { format: 'esm', generatedCode: { From 4422c82c08328d229bdb9d7b49d5550c4a9999f4 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 06:41:37 +0000 Subject: [PATCH 19/35] fix: resolve deeplink listener registration and add comprehensive logging - Fix Capacitor deeplink listener registration timing and duplicate function issues - Add comprehensive logging throughout deeplink processing pipeline - Enhance router navigation logging for better debugging - Resolves deeplink navigation failures on Android platform - Improves debugging capabilities for future deeplink issues --- src/main.capacitor.ts | 120 +++++++++++++-- src/router/index.ts | 72 ++++++--- src/services/deepLinks.ts | 316 ++++++++++++++++++++++---------------- 3 files changed, 346 insertions(+), 162 deletions(-) diff --git a/src/main.capacitor.ts b/src/main.capacitor.ts index 191d356e..adc0d8c5 100644 --- a/src/main.capacitor.ts +++ b/src/main.capacitor.ts @@ -29,14 +29,14 @@ */ import { initializeApp } from "./main.common"; -import { App } from "./libs/capacitor/app"; +import { App as CapacitorApp } from "@capacitor/app"; import router from "./router"; import { handleApiError } from "./services/api"; import { AxiosError } from "axios"; import { DeepLinkHandler } from "./services/deepLinks"; import { logger, safeStringify } from "./utils/logger"; -logger.log("[Capacitor] Starting initialization"); +logger.log("[Capacitor] 🚀 Starting initialization"); logger.log("[Capacitor] Platform:", process.env.VITE_PLATFORM); const app = initializeApp(); @@ -67,23 +67,123 @@ const deepLinkHandler = new DeepLinkHandler(router); * @throws {Error} If URL format is invalid */ const handleDeepLink = async (data: { url: string }) => { + const { url } = data; + logger.info(`[Main] 🌐 Deeplink received from Capacitor: ${url}`); + try { + // Wait for router to be ready + logger.info(`[Main] ⏳ Waiting for router to be ready...`); await router.isReady(); - await deepLinkHandler.handleDeepLink(data.url); + logger.info(`[Main] ✅ Router is ready, processing deeplink`); + + // Process the deeplink + logger.info(`[Main] 🚀 Starting deeplink processing`); + await deepLinkHandler.handleDeepLink(url); + logger.info(`[Main] ✅ Deeplink processed successfully`); } catch (error) { - logger.error("[DeepLink] Error handling deep link: ", error); + logger.error(`[Main] ❌ Deeplink processing failed:`, { + url, + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + timestamp: new Date().toISOString(), + }); + + // Log additional context for debugging + logger.error(`[Main] 🔍 Debug context:`, { + routerReady: router.isReady(), + currentRoute: router.currentRoute.value, + appMounted: app._instance?.isMounted, + timestamp: new Date().toISOString(), + }); + + // Fallback to original error handling let message: string = error instanceof Error ? error.message : safeStringify(error); - if (data.url) { - message += `\nURL: ${data.url}`; + if (url) { + message += `\nURL: ${url}`; } handleApiError({ message } as AxiosError, "deep-link"); } }; -// Register deep link handler with Capacitor -App.addListener("appUrlOpen", handleDeepLink); +// Function to register the deeplink listener +const registerDeepLinkListener = async () => { + try { + logger.info( + `[Main] 🔗 Attempting to register deeplink handler with Capacitor`, + ); + + // Check if Capacitor App plugin is available + logger.info(`[Main] 🔍 Checking Capacitor App plugin availability...`); + if (!CapacitorApp) { + throw new Error("Capacitor App plugin not available"); + } + logger.info(`[Main] ✅ Capacitor App plugin is available`); + + // Check available methods on CapacitorApp + logger.info( + `[Main] 🔍 Capacitor App plugin methods:`, + Object.getOwnPropertyNames(CapacitorApp), + ); + logger.info( + `[Main] 🔍 Capacitor App plugin addListener method:`, + typeof CapacitorApp.addListener, + ); + + // Wait for router to be ready first + await router.isReady(); + logger.info( + `[Main] ✅ Router is ready, proceeding with listener registration`, + ); + + // Try to register the listener + logger.info(`[Main] 🧪 Attempting to register appUrlOpen listener...`); + const listenerHandle = await CapacitorApp.addListener( + "appUrlOpen", + handleDeepLink, + ); + logger.info( + `[Main] ✅ appUrlOpen listener registered successfully with handle:`, + listenerHandle, + ); -logger.log("[Capacitor] Mounting app"); + // Test the listener registration by checking if it's actually registered + logger.info(`[Main] 🧪 Verifying listener registration...`); + + return listenerHandle; + } catch (error) { + logger.error(`[Main] ❌ Failed to register deeplink listener:`, { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + timestamp: new Date().toISOString(), + }); + throw error; + } +}; + +logger.log("[Capacitor] 🚀 Mounting app"); app.mount("#app"); -logger.log("[Capacitor] App mounted"); +logger.info(`[Main] ✅ App mounted successfully`); + +// Register deeplink listener after app is mounted +setTimeout(async () => { + try { + logger.info( + `[Main] ⏳ Delaying listener registration to ensure Capacitor is ready...`, + ); + await registerDeepLinkListener(); + logger.info(`[Main] 🎉 Deep link system fully initialized!`); + } catch (error) { + logger.error(`[Main] ❌ Deep link system initialization failed:`, error); + } +}, 2000); // 2 second delay to ensure Capacitor is fully ready + +// Log app initialization status +setTimeout(() => { + logger.info(`[Main] 📊 App initialization status:`, { + routerReady: router.isReady(), + currentRoute: router.currentRoute.value, + appMounted: app._instance?.isMounted, + timestamp: new Date().toISOString(), + }); +}, 1000); diff --git a/src/router/index.ts b/src/router/index.ts index 043d3d0c..f80d7a48 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -321,24 +321,21 @@ const errorHandler = ( router.onError(errorHandler); // Assign the error handler to the router instance /** - * Global navigation guard to ensure user identity exists - * - * This guard checks if the user has any identities before navigating to most routes. - * If no identity exists, it automatically creates one using the default seed-based method. - * - * Routes that are excluded from this check: - * - /start - Manual identity creation selection - * - /new-identifier - Manual seed-based creation - * - /import-account - Manual import flow - * - /import-derive - Manual derivation flow - * - /database-migration - Migration utilities - * - /deep-link-error - Error page - * + * Navigation guard to ensure user has an identity before accessing protected routes * @param to - Target route - * @param from - Source route + * @param _from - Source route (unused) * @param next - Navigation function */ router.beforeEach(async (to, _from, next) => { + logger.info(`[Router] 🧭 Navigation guard triggered:`, { + from: _from?.path || "none", + to: to.path, + name: to.name, + params: to.params, + query: to.query, + timestamp: new Date().toISOString(), + }); + try { // Skip identity check for routes that handle identity creation manually const skipIdentityRoutes = [ @@ -351,32 +348,67 @@ router.beforeEach(async (to, _from, next) => { ]; if (skipIdentityRoutes.includes(to.path)) { + logger.debug(`[Router] ⏭️ Skipping identity check for route: ${to.path}`); return next(); } + logger.info(`[Router] 🔍 Checking user identity for route: ${to.path}`); + // Check if user has any identities const allMyDids = await retrieveAccountDids(); + logger.info(`[Router] 📋 Found ${allMyDids.length} user identities`); if (allMyDids.length === 0) { - logger.info("[Router] No identities found, creating default identity"); + logger.info("[Router] ⚠️ No identities found, creating default identity"); // Create identity automatically using seed-based method await generateSaveAndActivateIdentity(); - logger.info("[Router] Default identity created successfully"); + logger.info("[Router] ✅ Default identity created successfully"); + } else { + logger.info( + `[Router] ✅ User has ${allMyDids.length} identities, proceeding`, + ); } + logger.info(`[Router] ✅ Navigation guard passed for: ${to.path}`); next(); } catch (error) { - logger.error( - "[Router] Identity creation failed in navigation guard:", - error, - ); + logger.error("[Router] ❌ Identity creation failed in navigation guard:", { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + route: to.path, + timestamp: new Date().toISOString(), + }); // Redirect to start page if identity creation fails // This allows users to manually create an identity or troubleshoot + logger.info( + `[Router] 🔄 Redirecting to /start due to identity creation failure`, + ); next("/start"); } }); +// Add navigation success logging +router.afterEach((to, from) => { + logger.info(`[Router] ✅ Navigation completed:`, { + from: from?.path || "none", + to: to.path, + name: to.name, + params: to.params, + query: to.query, + timestamp: new Date().toISOString(), + }); +}); + +// Add error logging +router.onError((error) => { + logger.error(`[Router] ❌ Navigation error:`, { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + timestamp: new Date().toISOString(), + }); +}); + export default router; diff --git a/src/services/deepLinks.ts b/src/services/deepLinks.ts index ee6095bb..750848a3 100644 --- a/src/services/deepLinks.ts +++ b/src/services/deepLinks.ts @@ -1,46 +1,12 @@ /** - * @file Deep Link Handler Service - * @author Matthew Raymer - * - * This service handles the processing and routing of deep links in the TimeSafari app. - * It provides a type-safe interface between the raw deep links and the application router. - * - * Architecture: - * 1. DeepLinkHandler class encapsulates all deep link processing logic - * 2. Uses Zod schemas from interfaces/deepLinks for parameter validation - * 3. Provides consistent error handling and logging - * 4. Maps validated parameters to Vue router calls - * - * Error Handling Strategy: - * - All errors are wrapped in DeepLinkError interface - * - Errors include error codes for systematic handling - * - Detailed error information is logged for debugging - * - Errors are propagated to the global error handler - * - * Validation Strategy: - * - URL structure validation - * - Route-specific parameter validation using Zod schemas - * - Query parameter validation and sanitization - * - Type-safe parameter passing to router - * - * Deep Link Format: - * timesafari://[/][?queryParam1=value1&queryParam2=value2] + * DeepLinks Service * - * Supported Routes: - * - claim: View claim - * - claim-add-raw: Add raw claim - * - claim-cert: View claim certificate - * - confirm-gift - * - contact-import: Import contacts - * - did: View DID - * - invite-one-accept: Accept invitation - * - onboard-meeting-members - * - project: View project details - * - user-profile: View user profile + * Handles deep link processing and routing for the TimeSafari application. + * Supports both path parameters and query parameters with comprehensive validation. * - * @example - * const handler = new DeepLinkHandler(router); - * await handler.handleDeepLink("timesafari://claim/123?view=details"); + * @author Matthew Raymer + * @version 2.0.0 + * @since 2025-01-25 */ import { Router } from "vue-router"; @@ -48,7 +14,6 @@ import { z } from "zod"; import { deepLinkPathSchemas, - baseUrlSchema, routeSchema, DeepLinkRoute, deepLinkQuerySchemas, @@ -104,83 +69,142 @@ export class DeepLinkHandler { } /** - - * Parses deep link URL into path, params and query components. - * Validates URL structure using Zod schemas. - * - * @param url - The deep link URL to parse (format: scheme://path[?query]) - * @throws {DeepLinkError} If URL format is invalid - * @returns Parsed URL components (path: string, params: {KEY: string}, query: {KEY: string}) + * Main entry point for processing deep links + * @param url - The deep link URL to process + * @throws {DeepLinkError} If validation fails or route is invalid */ - private parseDeepLink(url: string) { - const parts = url.split("://"); - if (parts.length !== 2) { - throw { code: "INVALID_URL", message: "Invalid URL format" }; - } + async handleDeepLink(url: string): Promise { + logger.info(`[DeepLink] 🚀 Starting deeplink processing for URL: ${url}`); - // Validate base URL structure - baseUrlSchema.parse({ - scheme: parts[0], - path: parts[1], - queryParams: {}, // Will be populated below - }); + try { + logger.info(`[DeepLink] 📍 Parsing URL: ${url}`); + const { path, params, query } = this.parseDeepLink(url); - const [path, queryString] = parts[1].split("?"); - const [routePath, ...pathParams] = path.split("/"); + logger.info(`[DeepLink] ✅ URL parsed successfully:`, { + path, + params: Object.keys(params), + query: Object.keys(query), + fullParams: params, + fullQuery: query, + }); - // Validate route exists before proceeding - if (!ROUTE_MAP[routePath]) { - throw { - code: "INVALID_ROUTE", - message: `Invalid route path: ${routePath}`, - details: { routePath }, - }; - } + // Sanitize parameters (remove undefined values) + const sanitizedParams = Object.fromEntries( + Object.entries(params).map(([key, value]) => [key, value ?? ""]), + ); - const query: Record = {}; - if (queryString) { - new URLSearchParams(queryString).forEach((value, key) => { - query[key] = value; + logger.info(`[DeepLink] 🧹 Parameters sanitized:`, sanitizedParams); + + await this.validateAndRoute(path, sanitizedParams, query); + logger.info(`[DeepLink] 🎯 Deeplink processing completed successfully`); + } catch (error) { + logger.error(`[DeepLink] ❌ Deeplink processing failed:`, { + url, + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, }); - } - const params: Record = {}; - if (pathParams) { - // Now we know routePath exists in ROUTE_MAP - const routeConfig = ROUTE_MAP[routePath]; - params[routeConfig.paramKey ?? "id"] = pathParams.join("/"); + const deepLinkError = error as DeepLinkError; + throw deepLinkError; } + } - // logConsoleAndDb( - // `[DeepLink] Debug: Route Path: ${routePath} Path Params: ${JSON.stringify(params)} Query String: ${JSON.stringify(query)}`, - // false, - // ); - return { path: routePath, params, query }; + /** + * Parse a deep link URL into its components + * @param url - The deep link URL + * @returns Parsed components + */ + private parseDeepLink(url: string): { + path: string; + params: Record; + query: Record; + } { + logger.debug(`[DeepLink] 🔍 Parsing deep link: ${url}`); + + try { + const parts = url.split("://"); + if (parts.length !== 2) { + throw new Error("Invalid URL format"); + } + + const [path, queryString] = parts[1].split("?"); + const [routePath, ...pathParams] = path.split("/"); + + // Parse path parameters + const params: Record = {}; + if (pathParams.length > 0) { + params.id = pathParams[0]; + logger.debug( + `[DeepLink] 📍 Path parameter extracted: id=${pathParams[0]}`, + ); + } + + // Parse query parameters + const query: Record = {}; + if (queryString) { + const queryParams = new URLSearchParams(queryString); + for (const [key, value] of queryParams.entries()) { + query[key] = value; + } + logger.debug(`[DeepLink] 🔗 Query parameters extracted:`, query); + } + + logger.info(`[DeepLink] ✅ Parse completed:`, { + routePath, + pathParams: pathParams.length, + queryParams: Object.keys(query).length, + }); + + return { path: routePath, params, query }; + } catch (error) { + logger.error(`[DeepLink] ❌ Parse failed:`, { + url, + error: error instanceof Error ? error.message : String(error), + }); + throw error; + } } /** - * Routes the deep link to appropriate view with validated parameters. - * Validates route and parameters using Zod schemas before routing. - * - * @param path - The route path from the deep link - * @param params - URL parameters - * @param query - Query string parameters - * @throws {DeepLinkError} If validation fails or route is invalid + * Validate and route the deep link + * @param path - The route path + * @param params - Path parameters + * @param query - Query parameters */ private async validateAndRoute( path: string, params: Record, query: Record, ): Promise { + logger.info( + `[DeepLink] 🎯 Starting validation and routing for path: ${path}`, + ); + // First try to validate the route path let routeName: string; try { + logger.debug(`[DeepLink] 🔍 Validating route path: ${path}`); // Validate route exists const validRoute = routeSchema.parse(path) as DeepLinkRoute; - routeName = ROUTE_MAP[validRoute].name; + logger.info(`[DeepLink] ✅ Route validation passed: ${validRoute}`); + + // Get route configuration + const routeConfig = ROUTE_MAP[validRoute]; + logger.info(`[DeepLink] 📋 Route config retrieved:`, routeConfig); + + if (!routeConfig) { + logger.error(`[DeepLink] ❌ No route config found for: ${validRoute}`); + throw new Error(`Route configuration missing for: ${validRoute}`); + } + + routeName = routeConfig.name; + logger.info(`[DeepLink] 🎯 Route name resolved: ${routeName}`); } catch (error) { - logger.error(`[DeepLink] Invalid route path: ${path}`); + logger.error(`[DeepLink] ❌ Route validation failed:`, { + path, + error: error instanceof Error ? error.message : String(error), + }); // Redirect to error page with information about the invalid link await this.router.replace({ @@ -194,30 +218,66 @@ export class DeepLinkHandler { }, }); - // This previously threw an error but we're redirecting so there's no need. + logger.info( + `[DeepLink] 🔄 Redirected to error page for invalid route: ${path}`, + ); return; } - // Continue with parameter validation as before... + // Continue with parameter validation + logger.info( + `[DeepLink] 🔍 Starting parameter validation for route: ${routeName}`, + ); + const pathSchema = deepLinkPathSchemas[path as keyof typeof deepLinkPathSchemas]; const querySchema = deepLinkQuerySchemas[path as keyof typeof deepLinkQuerySchemas]; + logger.debug(`[DeepLink] 📋 Schemas found:`, { + hasPathSchema: !!pathSchema, + hasQuerySchema: !!querySchema, + pathSchemaType: pathSchema ? typeof pathSchema : "none", + querySchemaType: querySchema ? typeof querySchema : "none", + }); + let validatedPathParams: Record = {}; let validatedQueryParams: Record = {}; + try { if (pathSchema) { + logger.debug(`[DeepLink] 🔍 Validating path parameters:`, params); validatedPathParams = await pathSchema.parseAsync(params); + logger.info( + `[DeepLink] ✅ Path parameters validated:`, + validatedPathParams, + ); + } else { + logger.debug(`[DeepLink] ⚠️ No path schema found for: ${path}`); + validatedPathParams = params; } + if (querySchema) { + logger.debug(`[DeepLink] 🔍 Validating query parameters:`, query); validatedQueryParams = await querySchema.parseAsync(query); + logger.info( + `[DeepLink] ✅ Query parameters validated:`, + validatedQueryParams, + ); + } else { + logger.debug(`[DeepLink] ⚠️ No query schema found for: ${path}`); + validatedQueryParams = query; } } catch (error) { - // For parameter validation errors, provide specific error feedback - logger.error( - `[DeepLink] Invalid parameters for route name ${routeName} for path: ${path} ... with error: ${JSON.stringify(error)} ... with params: ${JSON.stringify(params)} ... and query: ${JSON.stringify(query)}`, - ); + logger.error(`[DeepLink] ❌ Parameter validation failed:`, { + routeName, + path, + params, + query, + error: error instanceof Error ? error.message : String(error), + errorDetails: JSON.stringify(error), + }); + await this.router.replace({ name: "deep-link-error", params, @@ -229,60 +289,52 @@ export class DeepLinkHandler { }, }); - // This previously threw an error but we're redirecting so there's no need. + logger.info( + `[DeepLink] 🔄 Redirected to error page for invalid parameters`, + ); return; } + // Attempt navigation try { + logger.info(`[DeepLink] 🚀 Attempting navigation:`, { + routeName, + pathParams: validatedPathParams, + queryParams: validatedQueryParams, + }); + await this.router.replace({ name: routeName, params: validatedPathParams, query: validatedQueryParams, }); + + logger.info(`[DeepLink] ✅ Navigation successful to: ${routeName}`); } catch (error) { - logger.error( - `[DeepLink] Error routing to route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with validated params: ${JSON.stringify(validatedPathParams)} ... and query: ${JSON.stringify(validatedQueryParams)}`, - ); - // For parameter validation errors, provide specific error feedback + logger.error(`[DeepLink] ❌ Navigation failed:`, { + routeName, + path, + validatedPathParams, + validatedQueryParams, + error: error instanceof Error ? error.message : String(error), + errorDetails: JSON.stringify(error), + }); + + // Redirect to error page for navigation failures await this.router.replace({ name: "deep-link-error", params: validatedPathParams, query: { originalPath: path, errorCode: "ROUTING_ERROR", - errorMessage: `Error routing to ${routeName}: ${JSON.stringify(error)}`, + errorMessage: `Error routing to ${routeName}: ${(error as Error).message}`, ...validatedQueryParams, }, }); - } - } - /** - * Processes incoming deep links and routes them appropriately. - * Handles validation, error handling, and routing to the correct view. - * - * @param url - The deep link URL to process - * @throws {DeepLinkError} If URL processing fails - */ - async handleDeepLink(url: string): Promise { - try { - const { path, params, query } = this.parseDeepLink(url); - // Ensure params is always a Record by converting undefined to empty string - const sanitizedParams = Object.fromEntries( - Object.entries(params).map(([key, value]) => [key, value ?? ""]), - ); - await this.validateAndRoute(path, sanitizedParams, query); - } catch (error) { - const deepLinkError = error as DeepLinkError; - logger.error( - `[DeepLink] Error (${deepLinkError.code}): ${deepLinkError.details}`, + logger.info( + `[DeepLink] 🔄 Redirected to error page for navigation failure`, ); - - throw { - code: deepLinkError.code || "UNKNOWN_ERROR", - message: deepLinkError.message, - details: deepLinkError.details, - }; } } } From ce107fba5234e9ed90352a73630d9b2e0e691e22 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 06:43:08 +0000 Subject: [PATCH 20/35] style: clean up ProfileService formatting - Remove extra blank lines for consistent code formatting - Maintains code readability and follows project style guidelines --- src/services/ProfileService.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/services/ProfileService.ts b/src/services/ProfileService.ts index 815c7c87..8f8abcdc 100644 --- a/src/services/ProfileService.ts +++ b/src/services/ProfileService.ts @@ -268,8 +268,6 @@ export class ProfileService { return undefined; } - - /** * Type guard for AxiosError */ From 612c0b51cc816fbe5d013017cc74c017d38bea55 Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Wed, 20 Aug 2025 16:05:29 +0800 Subject: [PATCH 21/35] Fix: use route-specific parameter keys in deep link parser Fix iOS deep link "Invalid Deep Link" error by updating parseDeepLink to use correct parameter keys from ROUTE_MAP instead of always using 'id'. - Replace hardcoded 'id' parameter assignment with dynamic lookup - Use routeConfig.paramKey for route-specific parameter names (e.g., groupId for onboard-meeting-members) - Maintain backward compatibility with fallback to 'id' for routes without explicit paramKey --- src/services/deepLinks.ts | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/services/deepLinks.ts b/src/services/deepLinks.ts index 750848a3..aa0cda81 100644 --- a/src/services/deepLinks.ts +++ b/src/services/deepLinks.ts @@ -130,13 +130,23 @@ export class DeepLinkHandler { const [path, queryString] = parts[1].split("?"); const [routePath, ...pathParams] = path.split("/"); - // Parse path parameters + // Parse path parameters using route-specific configuration const params: Record = {}; if (pathParams.length > 0) { - params.id = pathParams[0]; - logger.debug( - `[DeepLink] 📍 Path parameter extracted: id=${pathParams[0]}`, - ); + // Get the correct parameter key for this route + const routeConfig = ROUTE_MAP[routePath]; + if (routeConfig?.paramKey) { + params[routeConfig.paramKey] = pathParams[0]; + logger.debug( + `[DeepLink] 📍 Path parameter extracted: ${routeConfig.paramKey}=${pathParams[0]}`, + ); + } else { + // Fallback to 'id' for backward compatibility + params.id = pathParams[0]; + logger.debug( + `[DeepLink] 📍 Path parameter extracted: id=${pathParams[0]} (fallback)`, + ); + } } // Parse query parameters From 9de6ebbf696dcceb02e4f7777e8efe6a2ef6774c Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 09:18:09 +0000 Subject: [PATCH 22/35] fix(build): resolve web app loading failure by simplifying Vite configuration - Simplify vite.config.web.mts to match working capacitor configuration - Remove complex mergeConfig() approach that was causing Vue compilation errors - Eliminate environment-specific build configurations that weren't needed - Fix "TypeError: Cannot read properties of undefined (reading 'on')" at App.vue:1 Problem: The web build was failing during Vue component compilation with a cryptic error at line 1 of App.vue. Investigation revealed the issue was in the overly complex Vite configuration that used mergeConfig() with environment-specific settings, while the working capacitor build used the simple direct approach. Solution: Simplified web config to use createBuildConfig('web') directly, matching the proven capacitor pattern. This eliminates the Vue compilation failure while preserving all functionality including deep links. Root cause: Complex build configuration was interfering with Vue's component processing, causing the .on() error during initial component registration. Files changed: - vite.config.web.mts: Simplified to match capacitor configuration pattern - vite.config.common.mts: Temporarily disabled ESBuild error handling (not root cause) Testing: Web app now loads successfully, Vue compilation completes, deep links preserved, and build architecture maintained. --- package-lock.json | 3243 +++++++++++++++++++++------------------- package.json | 4 +- vite.config.common.mts | 32 +- vite.config.web.mts | 110 +- 4 files changed, 1709 insertions(+), 1680 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8c11390..4806f89f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,9 +85,9 @@ "three": "^0.156.1", "ua-parser-js": "^1.0.37", "uint8arrays": "^5.0.0", - "vue": "^3.5.13", + "vue": "3.5.13", "vue-axios": "^3.5.2", - "vue-facing-decorator": "^3.0.4", + "vue-facing-decorator": "3.0.4", "vue-picture-cropper": "^0.7.0", "vue-qrcode-reader": "^5.5.3", "vue-router": "^4.5.0", @@ -221,22 +221,22 @@ } }, "node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", + "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "devOptional": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", + "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.3", + "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -262,14 +262,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", - "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "devOptional": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.0", - "@babel/types": "^7.28.0", + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -337,19 +337,19 @@ "license": "ISC" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", - "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", "license": "MIT", "optional": true, "peer": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.27.1", + "@babel/traverse": "^7.28.3", "semver": "^6.3.1" }, "engines": { @@ -485,15 +485,15 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -608,25 +608,25 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", - "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", + "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", "license": "MIT", "optional": true, "peer": true, "dependencies": { - "@babel/template": "^7.27.1", - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz", - "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", + "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", "devOptional": true, "license": "MIT", "dependencies": { @@ -740,12 +740,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", - "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.0" + "@babel/types": "^7.28.2" }, "bin": { "parser": "bin/babel-parser.js" @@ -1216,9 +1216,9 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.0.tgz", - "integrity": "sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.3.tgz", + "integrity": "sha512-DoEWC5SuxuARF2KdKmGUq3ghfPMO6ZzR12Dnp5gubwbeWJo4dbNWXJPVlwvh4Zlq6Z7YVvL8VFxeSOJgjsx4Sg==", "license": "MIT", "optional": true, "peer": true, @@ -1228,7 +1228,7 @@ "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -1666,9 +1666,9 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.1.tgz", - "integrity": "sha512-P0QiV/taaa3kXpLY+sXla5zec4E+4t4Aqc9ggHlfZ7a2cp8/x/Gv08jfwEtn9gnnYIMvHx6aoOZ8XJL8eU71Dg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.3.tgz", + "integrity": "sha512-K3/M/a4+ESb5LEldjQb+XSrpY0nF+ZBFlTCbSnKaYAMfD8v33O6PMs4uYnOk19HlcsI8WMu3McdFPTiQHF/1/A==", "license": "MIT", "optional": true, "peer": true, @@ -1683,9 +1683,9 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.0.tgz", - "integrity": "sha512-dGopk9nZrtCs2+nfIem25UuHyt5moSJamArzIoh9/vezUQPmYDOzjaHDCkAzuGJibCIkPup8rMT2+wYB6S73cA==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.3.tgz", + "integrity": "sha512-Y6ab1kGqZ0u42Zv/4a7l0l72n9DKP/MKoKWaUSBylrhNZO2prYuqFOLbn5aW5SIFXwSH93yfjbgllL8lxuGKLg==", "license": "MIT", "optional": true, "peer": true, @@ -1850,9 +1850,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", - "integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", + "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", "devOptional": true, "license": "MIT", "engines": { @@ -1875,18 +1875,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", - "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", + "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", "devOptional": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", + "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", + "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", + "@babel/types": "^7.28.2", "debug": "^4.3.1" }, "engines": { @@ -1895,19 +1895,19 @@ }, "node_modules/@babel/traverse--for-generate-function-map": { "name": "@babel/traverse", - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", - "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", + "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", "license": "MIT", "optional": true, "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", + "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", + "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", + "@babel/types": "^7.28.2", "debug": "^4.3.1" }, "engines": { @@ -3613,9 +3613,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", "cpu": [ "ppc64" ], @@ -3626,13 +3626,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", "cpu": [ "arm" ], @@ -3643,13 +3643,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", "cpu": [ "arm64" ], @@ -3660,13 +3660,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", "cpu": [ "x64" ], @@ -3677,13 +3677,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", "cpu": [ "arm64" ], @@ -3694,13 +3694,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", "cpu": [ "x64" ], @@ -3711,13 +3711,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", "cpu": [ "arm64" ], @@ -3728,13 +3728,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", "cpu": [ "x64" ], @@ -3745,13 +3745,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", "cpu": [ "arm" ], @@ -3762,13 +3762,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", "cpu": [ "arm64" ], @@ -3779,13 +3779,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", "cpu": [ "ia32" ], @@ -3796,13 +3796,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", "cpu": [ "loong64" ], @@ -3813,13 +3813,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", "cpu": [ "mips64el" ], @@ -3830,13 +3830,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", "cpu": [ "ppc64" ], @@ -3847,13 +3847,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", "cpu": [ "riscv64" ], @@ -3864,13 +3864,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", "cpu": [ "s390x" ], @@ -3881,13 +3881,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", "cpu": [ "x64" ], @@ -3898,7 +3898,7 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-arm64": { @@ -3919,9 +3919,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", "cpu": [ "x64" ], @@ -3932,7 +3932,7 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/openbsd-arm64": { @@ -3953,9 +3953,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", "cpu": [ "x64" ], @@ -3966,7 +3966,7 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/openharmony-arm64": { @@ -3987,9 +3987,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", "cpu": [ "x64" ], @@ -4000,13 +4000,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", "cpu": [ "arm64" ], @@ -4017,13 +4017,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", "cpu": [ "ia32" ], @@ -4034,13 +4034,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", "cpu": [ "x64" ], @@ -4051,7 +4051,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -6103,9 +6103,9 @@ } }, "node_modules/@expo/plist/node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", "license": "MIT", "optional": true, "peer": true, @@ -6667,9 +6667,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "license": "MIT", "engines": { "node": ">=12" @@ -6888,13 +6888,6 @@ "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "devOptional": true, - "license": "BSD-3-Clause" - }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -7399,9 +7392,9 @@ "license": "MIT" }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "devOptional": true, "license": "MIT", "dependencies": { @@ -7420,9 +7413,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", - "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "license": "MIT", "optional": true, "peer": true, @@ -7432,15 +7425,15 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", "devOptional": true, "license": "MIT", "dependencies": { @@ -7901,14 +7894,14 @@ } }, "node_modules/@react-native/assets-registry": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.80.2.tgz", - "integrity": "sha512-+sI2zIM22amhkZqW+RpD3qDoopeRiezrTtZMP+Y3HI+6/2JbEq7DdyV/2YS1lrSSdyy3STW2V37Lt4dKqP0lEQ==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.0.tgz", + "integrity": "sha512-rZs8ziQ1YRV3Z5Mw5AR7YcgI3q1Ya9NIx6nyuZAT9wDSSjspSi+bww+Hargh/a4JfV2Ajcxpn9X9UiFJr1ddPw==", "license": "MIT", "optional": true, "peer": true, "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, "node_modules/@react-native/babel-plugin-codegen": { @@ -8009,27 +8002,27 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.80.2.tgz", - "integrity": "sha512-UBjsE+lv1YtThs56mgFaUdWv0jNE1oO58Lkbf3dn47F0e7YiTubIcvP6AnlaMhZF2Pmt9ky8J1jTpgItO9tGeg==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.81.0.tgz", + "integrity": "sha512-n04ACkCaLR54NmA/eWiDpjC16pHr7+yrbjQ6OEdRoXbm5EfL8FEre2kDAci7pfFdiSMpxdRULDlKpfQ+EV/GAQ==", "license": "MIT", "optional": true, "peer": true, "dependencies": { - "@react-native/dev-middleware": "0.80.2", - "chalk": "^4.0.0", + "@react-native/dev-middleware": "0.81.0", "debug": "^4.4.0", "invariant": "^2.2.4", - "metro": "^0.82.2", - "metro-config": "^0.82.2", - "metro-core": "^0.82.2", + "metro": "^0.83.1", + "metro-config": "^0.83.1", + "metro-core": "^0.83.1", "semver": "^7.1.3" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" }, "peerDependencies": { - "@react-native-community/cli": "*" + "@react-native-community/cli": "*", + "@react-native/metro-config": "*" }, "peerDependenciesMeta": { "@react-native-community/cli": { @@ -8038,26 +8031,26 @@ } }, "node_modules/@react-native/community-cli-plugin/node_modules/@react-native/debugger-frontend": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.80.2.tgz", - "integrity": "sha512-n3D88bqNk0bY+YjNxbM6giqva06xj+rgEfu91Pg+nJ0szSL2eLl7ULERJqI3hxFt0XGuTpTOxZgw/Po5maXa4g==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.81.0.tgz", + "integrity": "sha512-N/8uL2CGQfwiQRYFUNfmaYxRDSoSeOmFb56rb0PDnP3XbS5+X9ee7X4bdnukNHLGfkRdH7sVjlB8M5zE8XJOhw==", "license": "BSD-3-Clause", "optional": true, "peer": true, "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, "node_modules/@react-native/community-cli-plugin/node_modules/@react-native/dev-middleware": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.80.2.tgz", - "integrity": "sha512-8OeBEZNiApdbZaqTrrzeyFwXn/JwgJox7jdtjVAH56DggTVJXdbnyUjQ4ts6XAacEQgpFOAskoO730eyafOkAA==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.81.0.tgz", + "integrity": "sha512-J/HeC/+VgRyGECPPr9rAbe5S0OL6MCIrvrC/kgNKSME5+ZQLCiTpt3pdAoAMXwXiF9a02Nmido0DnyM1acXTIA==", "license": "MIT", "optional": true, "peer": true, "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.80.2", + "@react-native/debugger-frontend": "0.81.0", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", @@ -8069,7 +8062,7 @@ "ws": "^6.2.3" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, "node_modules/@react-native/community-cli-plugin/node_modules/debug": { @@ -8212,68 +8205,232 @@ } }, "node_modules/@react-native/gradle-plugin": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.80.2.tgz", - "integrity": "sha512-C5/FYbIfCXPFjF/hIcWFKC9rEadDDhPMbxE7tarGR9tmYKyb9o7fYvfNe8fFgbCRKelMHP0ShATz3T73pHHDfA==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.81.0.tgz", + "integrity": "sha512-LGNtPXO1RKLws5ORRb4Q4YULi2qxM4qZRuARtwqM/1f2wyZVggqapoV0OXlaXaz+GiEd2ll3ROE4CcLN6J93jg==", "license": "MIT", "optional": true, "peer": true, "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, "node_modules/@react-native/js-polyfills": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.80.2.tgz", - "integrity": "sha512-f63M3paxHK92p6L9o+AY7hV/YojCZAhb+fdDpSfOtDtCngWbBhd6foJrO6IybzDFERxlwErupUg3pqr5w3KJWw==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.81.0.tgz", + "integrity": "sha512-whXZWIogzoGpqdyTjqT89M6DXmlOkWqNpWoVOAwVi8XFCMO+L7WTk604okIgO6gdGZcP1YtFpQf9JusbKrv/XA==", "license": "MIT", "optional": true, "peer": true, "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, - "node_modules/@react-native/normalize-colors": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.79.5.tgz", - "integrity": "sha512-nGXMNMclZgzLUxijQQ38Dm3IAEhgxuySAWQHnljFtfB0JdaMwpe0Ox9H7Tp2OgrEA+EMEv+Od9ElKlHwGKmmvQ==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@react-native/virtualized-lists": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.80.2.tgz", - "integrity": "sha512-kXsIV2eB73QClbbH/z/lRhZkyj3Dke4tarM5w2yXSNwJthMPMfj4KqLZ6Lnf0nmPPjz7qo/voKtlrGqlM822Rg==", + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.81.0.tgz", + "integrity": "sha512-Mwovr4jJ3JTnbHEQLhdcMvS82LjijpqCydXl1aH2N16WVCrE5oSNFiqTt6NpZBw9zkJX7nijsY+xeCy6m+KK3Q==", "license": "MIT", "optional": true, "peer": true, "dependencies": { - "invariant": "^2.2.4", + "@babel/core": "^7.25.2", + "@react-native/babel-preset": "0.81.0", + "hermes-parser": "0.29.1", "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" }, "peerDependencies": { - "@types/react": "^19.0.0", - "react": "*", - "react-native": "*" + "@babel/core": "*" + } + }, + "node_modules/@react-native/metro-babel-transformer/node_modules/@react-native/babel-plugin-codegen": { + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.81.0.tgz", + "integrity": "sha512-MEMlW91+2Kk9GiObRP1Nc6oTdiyvmSEbPMSC6kzUzDyouxnh5/x28uyNySmB2nb6ivcbmQ0lxaU059+CZSkKXQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.3", + "@react-native/codegen": "0.81.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">= 20.19.4" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", - "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@react-native/metro-babel-transformer/node_modules/@react-native/babel-preset": { + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.81.0.tgz", + "integrity": "sha512-RKMgCUGsso/2b32kgg24lB68LJ6qr2geLoSQTbisY6Usye0uXeXCgbZZDbILIX9upL4uzU4staMldRZ0v08F1g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-proposal-export-default-from": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-flow-strip-types": "^7.25.2", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.25.2", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/template": "^7.25.0", + "@react-native/babel-plugin-codegen": "0.81.0", + "babel-plugin-syntax-hermes-parser": "0.29.1", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/metro-babel-transformer/node_modules/@react-native/codegen": { + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.81.0.tgz", + "integrity": "sha512-gPFutgtj8YqbwKKt3YpZKamUBGd9YZJV51Jq2aiDZ9oThkg1frUBa20E+Jdi7jKn982wjBMxAklAR85QGQ4xMA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "glob": "^7.1.1", + "hermes-parser": "0.29.1", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/metro-babel-transformer/node_modules/babel-plugin-syntax-hermes-parser": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.29.1.tgz", + "integrity": "sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "hermes-parser": "0.29.1" + } + }, + "node_modules/@react-native/metro-babel-transformer/node_modules/hermes-estree": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz", + "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@react-native/metro-babel-transformer/node_modules/hermes-parser": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz", + "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "hermes-estree": "0.29.1" + } + }, + "node_modules/@react-native/metro-config": { + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/metro-config/-/metro-config-0.81.0.tgz", + "integrity": "sha512-5eqLP4TCERHGRYDJSZa//O98CGDFNNEwHVvhs65Msfy6hAoSdw5pAAuTrsQwmbTBp0Fkvu7Bx8BZDhiferZsHg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@react-native/js-polyfills": "0.81.0", + "@react-native/metro-babel-transformer": "0.81.0", + "metro-config": "^0.83.1", + "metro-runtime": "^0.83.1" + }, + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.79.5", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.79.5.tgz", + "integrity": "sha512-nGXMNMclZgzLUxijQQ38Dm3IAEhgxuySAWQHnljFtfB0JdaMwpe0Ox9H7Tp2OgrEA+EMEv+Od9ElKlHwGKmmvQ==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.81.0.tgz", + "integrity": "sha512-p14QC5INHkbMZ96158sUxkSwN6zp138W11G+CRGoLJY4Q9WRJBCe7wHR5Owyy3XczQXrIih/vxAXwgYeZ2XByg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@types/react": "^19.1.0", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.4.tgz", + "integrity": "sha512-B2wfzCJ+ps/OBzRjeds7DlJumCU3rXMxJJS1vzURyj7+KBHGONm7c9q1TfdBl4vCuNMkDvARn3PBl2wZzuR5mw==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8281,9 +8438,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz", - "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.4.tgz", + "integrity": "sha512-FGJYXvYdn8Bs6lAlBZYT5n+4x0ciEp4cmttsvKAZc/c8/JiPaQK8u0c/86vKX8lA7OY/+37lIQSe0YoAImvBAA==", "cpu": [ "arm64" ], @@ -8321,9 +8478,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz", - "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.4.tgz", + "integrity": "sha512-+ToyOMYnSfV8D+ckxO6NthPln/PDNp1P6INcNypfZ7muLmEvPKXqduUiD8DlJpMMT8LxHcE5W0dK9kXfJke9Zw==", "cpu": [ "arm64" ], @@ -8335,9 +8492,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz", - "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.4.tgz", + "integrity": "sha512-cGT6ey/W+sje6zywbLiqmkfkO210FgRz7tepWAzzEVgQU8Hn91JJmQWNqs55IuglG8sJdzk7XfNgmGRtcYlo1w==", "cpu": [ "x64" ], @@ -8349,9 +8506,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz", - "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.4.tgz", + "integrity": "sha512-9fhTJyOb275w5RofPSl8lpr4jFowd+H4oQKJ9XTYzD1JWgxdZKE8bA6d4npuiMemkecQOcigX01FNZNCYnQBdA==", "cpu": [ "arm" ], @@ -8363,9 +8520,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz", - "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.4.tgz", + "integrity": "sha512-+6kCIM5Zjvz2HwPl/udgVs07tPMIp1VU2Y0c72ezjOvSvEfAIWsUgpcSDvnC7g9NrjYR6X9bZT92mZZ90TfvXw==", "cpu": [ "arm" ], @@ -8403,9 +8560,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz", - "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.4.tgz", + "integrity": "sha512-mCBkjRZWhvjtl/x+Bd4fQkWZT8canStKDxGrHlBiTnZmJnWygGcvBylzLVCZXka4dco5ymkWhZlLwKCGFF4ivw==", "cpu": [ "loong64" ], @@ -8417,9 +8574,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz", - "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.4.tgz", + "integrity": "sha512-YMdz2phOTFF+Z66dQfGf0gmeDSi5DJzY5bpZyeg9CPBkV9QDzJ1yFRlmi/j7WWRf3hYIWrOaJj5jsfwgc8GTHQ==", "cpu": [ "ppc64" ], @@ -8431,9 +8588,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz", - "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.4.tgz", + "integrity": "sha512-r0WKLSfFAK8ucG024v2yiLSJMedoWvk8yWqfNICX28NHDGeu3F/wBf8KG6mclghx4FsLePxJr/9N8rIj1PtCnw==", "cpu": [ "riscv64" ], @@ -8445,9 +8602,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz", - "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.4.tgz", + "integrity": "sha512-IaizpPP2UQU3MNyPH1u0Xxbm73D+4OupL0bjo4Hm0496e2wg3zuvoAIhubkD1NGy9fXILEExPQy87mweujEatA==", "cpu": [ "riscv64" ], @@ -8459,9 +8616,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz", - "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.4.tgz", + "integrity": "sha512-aCM29orANR0a8wk896p6UEgIfupReupnmISz6SUwMIwTGaTI8MuKdE0OD2LvEg8ondDyZdMvnaN3bW4nFbATPA==", "cpu": [ "s390x" ], @@ -8512,9 +8669,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz", - "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.4.tgz", + "integrity": "sha512-OiEa5lRhiANpv4SfwYVgQ3opYWi/QmPDC5ve21m8G9pf6ZO+aX1g2EEF1/IFaM1xPSP7mK0msTRXlPs6mIagkg==", "cpu": [ "ia32" ], @@ -8625,9 +8782,9 @@ "license": "MIT" }, "node_modules/@sinclair/typebox": { - "version": "0.34.38", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", - "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "version": "0.34.40", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.40.tgz", + "integrity": "sha512-gwBNIP8ZAYev/ORDWW0QvxdwPXwxBtLsdsJgSc7eDIRt8ubP+rxUBzPsrwnu16fgEF8Bx4lh/+mvQvJzcTM6Kw==", "dev": true, "license": "MIT" }, @@ -9492,9 +9649,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.10.tgz", - "integrity": "sha512-iAFpG6DokED3roLSP0K+ybeDdIX6Bc0Vd3mLW5uDqThPWtNos3E+EqOM11mPQHKzfWHqEBuLjIlsBQQ8CsISmQ==", + "version": "20.19.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.11.tgz", + "integrity": "sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -10657,53 +10814,53 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.18.tgz", - "integrity": "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", + "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.0", - "@vue/shared": "3.5.18", + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.13", "entities": "^4.5.0", "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" + "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.18.tgz", - "integrity": "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", + "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/compiler-core": "3.5.13", + "@vue/shared": "3.5.13" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.18.tgz", - "integrity": "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", + "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.0", - "@vue/compiler-core": "3.5.18", - "@vue/compiler-dom": "3.5.18", - "@vue/compiler-ssr": "3.5.18", - "@vue/shared": "3.5.18", + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.13", + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13", "estree-walker": "^2.0.2", - "magic-string": "^0.30.17", - "postcss": "^8.5.6", - "source-map-js": "^1.2.1" + "magic-string": "^0.30.11", + "postcss": "^8.4.48", + "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.18.tgz", - "integrity": "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", + "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/compiler-dom": "3.5.13", + "@vue/shared": "3.5.13" } }, "node_modules/@vue/devtools-api": { @@ -10958,53 +11115,53 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.18.tgz", - "integrity": "sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz", + "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.18" + "@vue/shared": "3.5.13" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.18.tgz", - "integrity": "sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz", + "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/reactivity": "3.5.13", + "@vue/shared": "3.5.13" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.18.tgz", - "integrity": "sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", + "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.18", - "@vue/runtime-core": "3.5.18", - "@vue/shared": "3.5.18", + "@vue/reactivity": "3.5.13", + "@vue/runtime-core": "3.5.13", + "@vue/shared": "3.5.13", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.18.tgz", - "integrity": "sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz", + "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13" }, "peerDependencies": { - "vue": "3.5.18" + "vue": "3.5.13" } }, "node_modules/@vue/shared": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.18.tgz", - "integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", + "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", "license": "MIT" }, "node_modules/@vueuse/core": { @@ -12019,9 +12176,9 @@ "optional": true }, "node_modules/bare-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.6.tgz", - "integrity": "sha512-25RsLF33BqooOEFNdMcEhMpJy8EoR88zSMrnOQOaM3USnOK2VmaJ1uaQEwPA6AQjrv1lXChScosN6CzbwbO9OQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.2.0.tgz", + "integrity": "sha512-oRfrw7gwwBVAWx9S5zPMo2iiOjxyiZE12DmblmMQREgcogbNO0AFaZ+QBxxkEXiPspcpvO/Qtqn8LabUx4uYXg==", "dev": true, "license": "Apache-2.0", "optional": true, @@ -12065,9 +12222,9 @@ } }, "node_modules/bare-stream": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", - "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz", + "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==", "dev": true, "license": "Apache-2.0", "optional": true, @@ -12465,9 +12622,9 @@ "license": "MIT" }, "node_modules/browserslist": { - "version": "4.25.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz", - "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", + "version": "4.25.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.3.tgz", + "integrity": "sha512-cDGv1kkDI4/0e5yON9yM5G/0A5u8sf5TnmdX5C9qHzI9PPu++sQ9zjm1k9NiOrf3riY4OkK0zSGqfvJyJsgCBQ==", "devOptional": true, "funding": [ { @@ -12485,8 +12642,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001733", - "electron-to-chromium": "^1.5.199", + "caniuse-lite": "^1.0.30001735", + "electron-to-chromium": "^1.5.204", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -12975,9 +13132,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001734", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001734.tgz", - "integrity": "sha512-uhE1Ye5vgqju6OI71HTQqcBCZrvHugk0MjLak7Q+HfoBgoq5Bi+5YnwjP4fjDgrtYr/l8MVRBvzz9dPD4KyK0A==", + "version": "1.0.30001735", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", + "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==", "devOptional": true, "funding": [ { @@ -14136,14 +14293,6 @@ "node": ">=4" } }, - "node_modules/cosmiconfig/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause", - "optional": true, - "peer": true - }, "node_modules/crc": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", @@ -15357,9 +15506,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.199", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.199.tgz", - "integrity": "sha512-3gl0S7zQd88kCAZRO/DnxtBKuhMO4h0EaQIN3YgZfV6+pW+5+bf2AdQeHNESCoaQqo/gjGVYEf2YM4O5HJQqpQ==", + "version": "1.5.207", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.207.tgz", + "integrity": "sha512-mryFrrL/GXDTmAtIVMVf+eIXM09BBPlO5IQ7lUyKmK8d+A4VpRGG+M3ofoVef6qyF8s60rJei8ymlJxjUA8Faw==", "devOptional": true, "license": "ISC" }, @@ -15625,9 +15774,9 @@ } }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -15635,32 +15784,35 @@ "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" } }, "node_modules/escalade": { @@ -18202,14 +18354,10 @@ } }, "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, "engines": { "node": ">= 12" } @@ -18666,9 +18814,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -19548,12 +19696,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "license": "MIT" - }, "node_modules/jsc-safe-url": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", @@ -19655,9 +19797,9 @@ "license": "MIT" }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -21388,9 +21530,9 @@ "license": "MIT" }, "node_modules/metro": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro/-/metro-0.82.5.tgz", - "integrity": "sha512-8oAXxL7do8QckID/WZEKaIFuQJFUTLzfVcC48ghkHhNK2RGuQq8Xvf4AVd+TUA0SZtX0q8TGNXZ/eba1ckeGCg==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.83.1.tgz", + "integrity": "sha512-UGKepmTxoGD4HkQV8YWvpvwef7fUujNtTgG4Ygf7m/M0qjvb9VuDmAsEU+UdriRX7F61pnVK/opz89hjKlYTXA==", "license": "MIT", "optional": true, "peer": true, @@ -21416,18 +21558,18 @@ "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.82.5", - "metro-cache": "0.82.5", - "metro-cache-key": "0.82.5", - "metro-config": "0.82.5", - "metro-core": "0.82.5", - "metro-file-map": "0.82.5", - "metro-resolver": "0.82.5", - "metro-runtime": "0.82.5", - "metro-source-map": "0.82.5", - "metro-symbolicate": "0.82.5", - "metro-transform-plugins": "0.82.5", - "metro-transform-worker": "0.82.5", + "metro-babel-transformer": "0.83.1", + "metro-cache": "0.83.1", + "metro-cache-key": "0.83.1", + "metro-config": "0.83.1", + "metro-core": "0.83.1", + "metro-file-map": "0.83.1", + "metro-resolver": "0.83.1", + "metro-runtime": "0.83.1", + "metro-source-map": "0.83.1", + "metro-symbolicate": "0.83.1", + "metro-transform-plugins": "0.83.1", + "metro-transform-worker": "0.83.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", @@ -21440,13 +21582,13 @@ "metro": "src/cli.js" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-babel-transformer": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.82.5.tgz", - "integrity": "sha512-W/scFDnwJXSccJYnOFdGiYr9srhbHPdxX9TvvACOFsIXdLilh3XuxQl/wXW6jEJfgIb0jTvoTlwwrqvuwymr6Q==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.83.1.tgz", + "integrity": "sha512-r3xAD3964E8dwDBaZNSO2aIIvWXjIK80uO2xo0/pi3WI8XWT9h5SCjtGWtMtE5PRWw+t20TN0q1WMRsjvhC1rQ==", "license": "MIT", "optional": true, "peer": true, @@ -21457,7 +21599,7 @@ "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-babel-transformer/node_modules/hermes-estree": { @@ -21480,9 +21622,9 @@ } }, "node_modules/metro-cache": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.82.5.tgz", - "integrity": "sha512-AwHV9607xZpedu1NQcjUkua8v7HfOTKfftl6Vc9OGr/jbpiJX6Gpy8E/V9jo/U9UuVYX2PqSUcVNZmu+LTm71Q==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.83.1.tgz", + "integrity": "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ==", "license": "MIT", "optional": true, "peer": true, @@ -21490,16 +21632,16 @@ "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", - "metro-core": "0.82.5" + "metro-core": "0.83.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-cache-key": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.82.5.tgz", - "integrity": "sha512-qpVmPbDJuRLrT4kcGlUouyqLGssJnbTllVtvIgXfR7ZuzMKf0mGS+8WzcqzNK8+kCyakombQWR0uDd8qhWGJcA==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.83.1.tgz", + "integrity": "sha512-ZUs+GD5CNeDLxx5UUWmfg26IL+Dnbryd+TLqTlZnDEgehkIa11kUSvgF92OFfJhONeXzV4rZDRGNXoo6JT+8Gg==", "license": "MIT", "optional": true, "peer": true, @@ -21507,13 +21649,13 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-config": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.82.5.tgz", - "integrity": "sha512-/r83VqE55l0WsBf8IhNmc/3z71y2zIPe5kRSuqA5tY/SL/ULzlHUJEMd1szztd0G45JozLwjvrhAzhDPJ/Qo/g==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.83.1.tgz", + "integrity": "sha512-HJhpZx3wyOkux/jeF1o7akFJzZFdbn6Zf7UQqWrvp7gqFqNulQ8Mju09raBgPmmSxKDl4LbbNeigkX0/nKY1QA==", "license": "MIT", "optional": true, "peer": true, @@ -21522,13 +21664,13 @@ "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", - "metro": "0.82.5", - "metro-cache": "0.82.5", - "metro-core": "0.82.5", - "metro-runtime": "0.82.5" + "metro": "0.83.1", + "metro-cache": "0.83.1", + "metro-core": "0.83.1", + "metro-runtime": "0.83.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-config/node_modules/@jest/schemas": { @@ -21636,25 +21778,25 @@ } }, "node_modules/metro-core": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.82.5.tgz", - "integrity": "sha512-OJL18VbSw2RgtBm1f2P3J5kb892LCVJqMvslXxuxjAPex8OH7Eb8RBfgEo7VZSjgb/LOf4jhC4UFk5l5tAOHHA==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.83.1.tgz", + "integrity": "sha512-uVL1eAJcMFd2o2Q7dsbpg8COaxjZBBGaXqO2OHnivpCdfanraVL8dPmY6It9ZeqWLOihUKZ2yHW4b6soVCzH/Q==", "license": "MIT", "optional": true, "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", - "metro-resolver": "0.82.5" + "metro-resolver": "0.83.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-file-map": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.82.5.tgz", - "integrity": "sha512-vpMDxkGIB+MTN8Af5hvSAanc6zXQipsAUO+XUx3PCQieKUfLwdoa8qaZ1WAQYRpaU+CJ8vhBcxtzzo3d9IsCIQ==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.83.1.tgz", + "integrity": "sha512-Yu429lnexKl44PttKw3nhqgmpBR+6UQ/tRaYcxPeEShtcza9DWakCn7cjqDTQZtWR2A8xSNv139izJMyQ4CG+w==", "license": "MIT", "optional": true, "peer": true, @@ -21670,7 +21812,7 @@ "walker": "^1.0.7" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-file-map/node_modules/@jest/schemas": { @@ -21809,9 +21951,9 @@ } }, "node_modules/metro-minify-terser": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.82.5.tgz", - "integrity": "sha512-v6Nx7A4We6PqPu/ta1oGTqJ4Usz0P7c+3XNeBxW9kp8zayS3lHUKR0sY0wsCHInxZlNAEICx791x+uXytFUuwg==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.83.1.tgz", + "integrity": "sha512-kmooOxXLvKVxkh80IVSYO4weBdJDhCpg5NSPkjzzAnPJP43u6+usGXobkTWxxrAlq900bhzqKek4pBsUchlX6A==", "license": "MIT", "optional": true, "peer": true, @@ -21820,13 +21962,13 @@ "terser": "^5.15.0" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-resolver": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.82.5.tgz", - "integrity": "sha512-kFowLnWACt3bEsuVsaRNgwplT8U7kETnaFHaZePlARz4Fg8tZtmRDUmjaD68CGAwc0rwdwNCkWizLYpnyVcs2g==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.83.1.tgz", + "integrity": "sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g==", "license": "MIT", "optional": true, "peer": true, @@ -21834,13 +21976,13 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-runtime": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.82.5.tgz", - "integrity": "sha512-rQZDoCUf7k4Broyw3Ixxlq5ieIPiR1ULONdpcYpbJQ6yQ5GGEyYjtkztGD+OhHlw81LCR2SUAoPvtTus2WDK5g==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.83.1.tgz", + "integrity": "sha512-3Ag8ZS4IwafL/JUKlaeM6/CbkooY+WcVeqdNlBG0m4S0Qz0om3rdFdy1y6fYBpl6AwXJwWeMuXrvZdMuByTcRA==", "license": "MIT", "optional": true, "peer": true, @@ -21849,13 +21991,13 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-source-map": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.82.5.tgz", - "integrity": "sha512-wH+awTOQJVkbhn2SKyaw+0cd+RVSCZ3sHVgyqJFQXIee/yLs3dZqKjjeKKhhVeudgjXo7aE/vSu/zVfcQEcUfw==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.83.1.tgz", + "integrity": "sha512-De7Vbeo96fFZ2cqmI0fWwVJbtHIwPZv++LYlWSwzTiCzxBDJORncN0LcT48Vi2UlQLzXJg+/CuTAcy7NBVh69A==", "license": "MIT", "optional": true, "peer": true, @@ -21865,14 +22007,14 @@ "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-symbolicate": "0.82.5", + "metro-symbolicate": "0.83.1", "nullthrows": "^1.1.1", - "ob1": "0.82.5", + "ob1": "0.83.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-source-map/node_modules/source-map": { @@ -21887,16 +22029,16 @@ } }, "node_modules/metro-symbolicate": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.82.5.tgz", - "integrity": "sha512-1u+07gzrvYDJ/oNXuOG1EXSvXZka/0JSW1q2EYBWerVKMOhvv9JzDGyzmuV7hHbF2Hg3T3S2uiM36sLz1qKsiw==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.83.1.tgz", + "integrity": "sha512-wPxYkONlq/Sv8Ji7vHEx5OzFouXAMQJjpcPW41ySKMLP/Ir18SsiJK2h4YkdKpYrTS1+0xf8oqF6nxCsT3uWtg==", "license": "MIT", "optional": true, "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-source-map": "0.82.5", + "metro-source-map": "0.83.1", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" @@ -21905,7 +22047,7 @@ "metro-symbolicate": "src/index.js" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-symbolicate/node_modules/source-map": { @@ -21920,9 +22062,9 @@ } }, "node_modules/metro-transform-plugins": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.82.5.tgz", - "integrity": "sha512-57Bqf3rgq9nPqLrT2d9kf/2WVieTFqsQ6qWHpEng5naIUtc/Iiw9+0bfLLWSAw0GH40iJ4yMjFcFJDtNSYynMA==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.83.1.tgz", + "integrity": "sha512-1Y+I8oozXwhuS0qwC+ezaHXBf0jXW4oeYn4X39XWbZt9X2HfjodqY9bH9r6RUTsoiK7S4j8Ni2C91bUC+sktJQ==", "license": "MIT", "optional": true, "peer": true, @@ -21935,13 +22077,13 @@ "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-transform-worker": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.82.5.tgz", - "integrity": "sha512-mx0grhAX7xe+XUQH6qoHHlWedI8fhSpDGsfga7CpkO9Lk9W+aPitNtJWNGrW8PfjKEWbT9Uz9O50dkI8bJqigw==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.83.1.tgz", + "integrity": "sha512-owCrhPyUxdLgXEEEAL2b14GWTPZ2zYuab1VQXcfEy0sJE71iciD7fuMcrngoufh7e7UHDZ56q4ktXg8wgiYA1Q==", "license": "MIT", "optional": true, "peer": true, @@ -21951,17 +22093,17 @@ "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", - "metro": "0.82.5", - "metro-babel-transformer": "0.82.5", - "metro-cache": "0.82.5", - "metro-cache-key": "0.82.5", - "metro-minify-terser": "0.82.5", - "metro-source-map": "0.82.5", - "metro-transform-plugins": "0.82.5", + "metro": "0.83.1", + "metro-babel-transformer": "0.83.1", + "metro-cache": "0.83.1", + "metro-cache-key": "0.83.1", + "metro-minify-terser": "0.83.1", + "metro-source-map": "0.83.1", + "metro-transform-plugins": "0.83.1", "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro/node_modules/@jest/schemas": { @@ -23822,9 +23964,9 @@ "license": "MIT" }, "node_modules/ob1": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.82.5.tgz", - "integrity": "sha512-QyQQ6e66f+Ut/qUVjEce0E/wux5nAGLXYZDn1jr15JWstHsCH3l6VVrg8NKDptW9NEiBXKOJeGF/ydxeSDF3IQ==", + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.83.1.tgz", + "integrity": "sha512-ngwqewtdUzFyycomdbdIhFLjePPSOt1awKMUXQ0L7iLHgWEPF3DsCerblzjzfAUHaXuvE9ccJymWQ/4PNNqvnQ==", "license": "MIT", "optional": true, "peer": true, @@ -23832,7 +23974,7 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/object-assign": { @@ -24434,6 +24576,33 @@ "pinia": "^2.0.0" } }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/pirates": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", @@ -24575,9 +24744,9 @@ } }, "node_modules/plist/node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -25509,40 +25678,39 @@ "license": "MIT" }, "node_modules/react-native": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.80.2.tgz", - "integrity": "sha512-6ySV4qTJo/To3lgpG/9Mcg/ZtvExqOVZuT7JVGcO5rS2Bjvl/yUAkQF0hTnbRb2Ch6T5MlKghrM4OeHX+KA9Pg==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.0.tgz", + "integrity": "sha512-RDWhewHGsAa5uZpwIxnJNiv5tW2y6/DrQUjEBdAHPzGMwuMTshern2s4gZaWYeRU3SQguExVddCjiss9IBhxqA==", "license": "MIT", "optional": true, "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.7.0", - "@react-native/assets-registry": "0.80.2", - "@react-native/codegen": "0.80.2", - "@react-native/community-cli-plugin": "0.80.2", - "@react-native/gradle-plugin": "0.80.2", - "@react-native/js-polyfills": "0.80.2", - "@react-native/normalize-colors": "0.80.2", - "@react-native/virtualized-lists": "0.80.2", + "@react-native/assets-registry": "0.81.0", + "@react-native/codegen": "0.81.0", + "@react-native/community-cli-plugin": "0.81.0", + "@react-native/gradle-plugin": "0.81.0", + "@react-native/js-polyfills": "0.81.0", + "@react-native/normalize-colors": "0.81.0", + "@react-native/virtualized-lists": "0.81.0", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", - "babel-plugin-syntax-hermes-parser": "0.28.1", + "babel-plugin-syntax-hermes-parser": "0.29.1", "base64-js": "^1.5.1", - "chalk": "^4.0.0", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", - "metro-runtime": "^0.82.2", - "metro-source-map": "^0.82.2", + "metro-runtime": "^0.83.1", + "metro-source-map": "^0.83.1", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", - "react-devtools-core": "^6.1.1", + "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.26.0", @@ -25556,7 +25724,7 @@ "react-native": "cli.js" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" }, "peerDependencies": { "@types/react": "^19.1.0", @@ -25691,30 +25859,30 @@ } }, "node_modules/react-native/node_modules/@react-native/codegen": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.80.2.tgz", - "integrity": "sha512-eYad9ex9/RS6oFbbpu6LxsczktbhfJbJlTvtRlcWLJjJbFTeNr5Q7CgBT2/m5VtpxnJ/0YdmZ9vdazsJ2yp9kw==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.81.0.tgz", + "integrity": "sha512-gPFutgtj8YqbwKKt3YpZKamUBGd9YZJV51Jq2aiDZ9oThkg1frUBa20E+Jdi7jKn982wjBMxAklAR85QGQ4xMA==", "license": "MIT", "optional": true, "peer": true, "dependencies": { "glob": "^7.1.1", - "hermes-parser": "0.28.1", + "hermes-parser": "0.29.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" }, "peerDependencies": { "@babel/core": "*" } }, "node_modules/react-native/node_modules/@react-native/normalize-colors": { - "version": "0.80.2", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.80.2.tgz", - "integrity": "sha512-08Ax7554Z31NXi5SQ6h1GsiSrlZEOYHQNSC7u+x91Tdiq87IXldW8Ib1N3ThXoDcD8bjr+I+MdlabEJw36/fFg==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.81.0.tgz", + "integrity": "sha512-3gEu/29uFgz+81hpUgdlOojM4rjHTIPwxpfygFNY60V6ywZih3eLDTS8kAjNZfPFHQbcYrNorJzwnL5yFF/uLw==", "license": "MIT", "optional": true, "peer": true @@ -25811,14 +25979,14 @@ } }, "node_modules/react-native/node_modules/babel-plugin-syntax-hermes-parser": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.28.1.tgz", - "integrity": "sha512-meT17DOuUElMNsL5LZN56d+KBp22hb0EfxWfuPUeoSi54e40v1W4C2V36P75FpsH9fVEfDKpw5Nnkahc8haSsQ==", + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.29.1.tgz", + "integrity": "sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA==", "license": "MIT", "optional": true, "peer": true, "dependencies": { - "hermes-parser": "0.28.1" + "hermes-parser": "0.29.1" } }, "node_modules/react-native/node_modules/babel-preset-jest": { @@ -25851,22 +26019,22 @@ } }, "node_modules/react-native/node_modules/hermes-estree": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.28.1.tgz", - "integrity": "sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==", + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz", + "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==", "license": "MIT", "optional": true, "peer": true }, "node_modules/react-native/node_modules/hermes-parser": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.28.1.tgz", - "integrity": "sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==", + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz", + "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==", "license": "MIT", "optional": true, "peer": true, "dependencies": { - "hermes-estree": "0.28.1" + "hermes-estree": "0.29.1" } }, "node_modules/react-native/node_modules/istanbul-lib-instrument": { @@ -27073,9 +27241,9 @@ } }, "node_modules/rollup": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", - "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.4.tgz", + "integrity": "sha512-YbxoxvoqNg9zAmw4+vzh1FkGAiZRK+LhnSrbSrSXMdZYsRPDWoshcSd/pldKRO6lWzv/e9TiJAVQyirYIeSIPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -27089,33 +27257,33 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.46.2", - "@rollup/rollup-android-arm64": "4.46.2", - "@rollup/rollup-darwin-arm64": "4.46.2", - "@rollup/rollup-darwin-x64": "4.46.2", - "@rollup/rollup-freebsd-arm64": "4.46.2", - "@rollup/rollup-freebsd-x64": "4.46.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", - "@rollup/rollup-linux-arm-musleabihf": "4.46.2", - "@rollup/rollup-linux-arm64-gnu": "4.46.2", - "@rollup/rollup-linux-arm64-musl": "4.46.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", - "@rollup/rollup-linux-ppc64-gnu": "4.46.2", - "@rollup/rollup-linux-riscv64-gnu": "4.46.2", - "@rollup/rollup-linux-riscv64-musl": "4.46.2", - "@rollup/rollup-linux-s390x-gnu": "4.46.2", - "@rollup/rollup-linux-x64-gnu": "4.46.2", - "@rollup/rollup-linux-x64-musl": "4.46.2", - "@rollup/rollup-win32-arm64-msvc": "4.46.2", - "@rollup/rollup-win32-ia32-msvc": "4.46.2", - "@rollup/rollup-win32-x64-msvc": "4.46.2", + "@rollup/rollup-android-arm-eabi": "4.46.4", + "@rollup/rollup-android-arm64": "4.46.4", + "@rollup/rollup-darwin-arm64": "4.46.4", + "@rollup/rollup-darwin-x64": "4.46.4", + "@rollup/rollup-freebsd-arm64": "4.46.4", + "@rollup/rollup-freebsd-x64": "4.46.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.46.4", + "@rollup/rollup-linux-arm-musleabihf": "4.46.4", + "@rollup/rollup-linux-arm64-gnu": "4.46.4", + "@rollup/rollup-linux-arm64-musl": "4.46.4", + "@rollup/rollup-linux-loongarch64-gnu": "4.46.4", + "@rollup/rollup-linux-ppc64-gnu": "4.46.4", + "@rollup/rollup-linux-riscv64-gnu": "4.46.4", + "@rollup/rollup-linux-riscv64-musl": "4.46.4", + "@rollup/rollup-linux-s390x-gnu": "4.46.4", + "@rollup/rollup-linux-x64-gnu": "4.46.4", + "@rollup/rollup-linux-x64-musl": "4.46.4", + "@rollup/rollup-win32-arm64-msvc": "4.46.4", + "@rollup/rollup-win32-ia32-msvc": "4.46.4", + "@rollup/rollup-win32-x64-msvc": "4.46.4", "fsevents": "~2.3.2" } }, "node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz", - "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.4.tgz", + "integrity": "sha512-/9qwE/BM7ATw/W/OFEMTm3dmywbJyLQb4f4v5nmOjgYxPIGpw7HaxRi6LnD4Pjn/q7k55FGeHe1/OD02w63apA==", "cpu": [ "arm64" ], @@ -27127,9 +27295,9 @@ ] }, "node_modules/rollup/node_modules/@rollup/rollup-darwin-x64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz", - "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.4.tgz", + "integrity": "sha512-QkWfNbeRuzFnv2d0aPlrzcA3Ebq2mE8kX/5Pl7VdRShbPBjSnom7dbT8E3Jmhxo2RL784hyqGvR5KHavCJQciw==", "cpu": [ "x64" ], @@ -27141,9 +27309,9 @@ ] }, "node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz", - "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.4.tgz", + "integrity": "sha512-SWuXdnsayCZL4lXoo6jn0yyAj7TTjWE4NwDVt9s7cmu6poMhtiras5c8h6Ih6Y0Zk6Z+8t/mLumvpdSPTWub2Q==", "cpu": [ "arm64" ], @@ -27155,9 +27323,9 @@ ] }, "node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz", - "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.4.tgz", + "integrity": "sha512-vDknMDqtMhrrroa5kyX6tuC0aRZZlQ+ipDfbXd2YGz5HeV2t8HOl/FDAd2ynhs7Ki5VooWiiZcCtxiZ4IjqZwQ==", "cpu": [ "arm64" ], @@ -27169,9 +27337,9 @@ ] }, "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz", - "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.4.tgz", + "integrity": "sha512-0Xj1vZE3cbr/wda8d/m+UeuSL+TDpuozzdD4QaSzu/xSOMK0Su5RhIkF7KVHFQsobemUNHPLEcYllL7ZTCP/Cg==", "cpu": [ "x64" ], @@ -27183,9 +27351,9 @@ ] }, "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz", - "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.4.tgz", + "integrity": "sha512-kM/orjpolfA5yxsx84kI6bnK47AAZuWxglGKcNmokw2yy9i5eHY5UAjcX45jemTJnfHAWo3/hOoRqEeeTdL5hw==", "cpu": [ "x64" ], @@ -27197,9 +27365,9 @@ ] }, "node_modules/rollup/node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz", - "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.4.tgz", + "integrity": "sha512-cNLH4psMEsWKILW0isbpQA2OvjXLbKvnkcJFmqAptPQbtLrobiapBJVj6RoIvg6UXVp5w0wnIfd/Q56cNpF+Ew==", "cpu": [ "arm64" ], @@ -27211,9 +27379,9 @@ ] }, "node_modules/rollup/node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz", - "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==", + "version": "4.46.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.4.tgz", + "integrity": "sha512-IKL9mewGZ5UuuX4NQlwOmxPyqielvkAPUS2s1cl6yWjjQvyN3h5JTdVFGD5Jr5xMjRC8setOfGQDVgX8V+dkjg==", "cpu": [ "x64" ], @@ -27962,12 +28130,12 @@ } }, "node_modules/socks": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.6.tgz", - "integrity": "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==", + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -28110,9 +28278,10 @@ } }, "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "devOptional": true, "license": "BSD-3-Clause" }, "node_modules/sql-highlight": { @@ -29367,1203 +29536,1196 @@ "fsevents": "~2.3.3" } }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", - "cpu": [ - "arm" - ], + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "prelude-ls": "^1.2.1" + }, "engines": { - "node": ">=18" + "node": ">= 0.8.0" } }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "devOptional": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" } }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", - "cpu": [ - "x64" - ], + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/typedarray-to-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-1.0.4.tgz", + "integrity": "sha512-vjMKrfSoUDN8/Vnqitw2FmstOfuJ73G6CrSEKnf11A6RmasVxHqfeBcnTb6RsL4pTMuV5Zsv9IiHRphMZyckUw==", "dev": true, + "license": "MIT" + }, + "node_modules/typeorm": { + "version": "0.3.26", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.26.tgz", + "integrity": "sha512-o2RrBNn3lczx1qv4j+JliVMmtkPSqEGpG0UuZkt9tCfWkoXKu8MZnjvp2GjWPll1SehwemQw6xrbVRhmOglj8Q==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@sqltools/formatter": "^1.2.5", + "ansis": "^3.17.0", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "dayjs": "^1.11.13", + "debug": "^4.4.0", + "dedent": "^1.6.0", + "dotenv": "^16.4.7", + "glob": "^10.4.5", + "sha.js": "^2.4.11", + "sql-highlight": "^6.0.0", + "tslib": "^2.8.1", + "uuid": "^11.1.0", + "yargs": "^17.7.2" + }, + "bin": { + "typeorm": "cli.js", + "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", + "typeorm-ts-node-esm": "cli-ts-node-esm.js" + }, "engines": { - "node": ">=18" + "node": ">=16.13.0" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", + "@sap/hana-client": "^2.14.22", + "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", + "ioredis": "^5.0.4", + "mongodb": "^5.8.0 || ^6.0.0", + "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", + "mysql2": "^2.2.5 || ^3.0.1", + "oracledb": "^6.3.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1 || ^4.0.0 || ^5.0.14", + "reflect-metadata": "^0.1.14 || ^0.2.0", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.3", + "ts-node": "^10.7.0", + "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" + }, + "peerDependenciesMeta": { + "@google-cloud/spanner": { + "optional": true + }, + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "ts-node": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/typeorm/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=18" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "node_modules/typeorm/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/typeorm/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=18" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/typeorm/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", "engines": { - "node": ">=18" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } + "node_modules/typeorm/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", - "cpu": [ - "loong64" + "node_modules/typeorm/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typeorm/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" ], - "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "bin": { + "uuid": "dist/esm/bin/uuid" } }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", - "cpu": [ - "mips64el" - ], + "node_modules/types-ramda": { + "version": "0.29.10", + "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.29.10.tgz", + "integrity": "sha512-5PJiW/eiTPyXXBYGZOYGezMl6qj7keBiZheRwfjJZY26QPHsNrjfJnz0mru6oeqqoTHOni893Jfd6zyUXfQRWg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "ts-toolbelt": "^9.6.0" } }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=18" + "node": ">=14.17" } }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", - "cpu": [ - "riscv64" + "node_modules/ua-parser-js": { + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", + "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } ], - "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "bin": { + "ua-parser-js": "script/cli.js" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", - "cpu": [ - "s390x" - ], + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", - "cpu": [ - "x64" - ], + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "optional": true, - "os": [ - "linux" - ], + "bin": { + "uglifyjs": "bin/uglifyjs" + }, "engines": { - "node": ">=18" + "node": ">=0.8.0" } }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" + "node_modules/uint8-varint": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/uint8-varint/-/uint8-varint-2.0.4.tgz", + "integrity": "sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "uint8arraylist": "^2.0.0", + "uint8arrays": "^5.0.0" } }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/uint8arraylist": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.8.tgz", + "integrity": "sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "uint8arrays": "^5.0.1" + } + }, + "node_modules/uint8arrays": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.1.0.tgz", + "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "multiformats": "^13.0.0" + } + }, + "node_modules/uint8arrays/node_modules/multiformats": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.4.0.tgz", + "integrity": "sha512-Mkb/QcclrJxKC+vrcIFl297h52QcKh2Az/9A5vbWytbQt4225UWWWmIuSsKksdww9NkIeYcA7DkfftyLuC/JSg==", + "license": "Apache-2.0 OR MIT" + }, + "node_modules/undici": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", + "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", "license": "MIT", "optional": true, - "os": [ - "openbsd" - ], + "peer": true, "engines": { - "node": ">=18" + "node": ">=18.17" } }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "license": "MIT", "optional": true, - "os": [ - "sunos" - ], + "peer": true, "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "license": "MIT", "optional": true, - "os": [ - "win32" - ], + "peer": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", - "cpu": [ - "ia32" - ], - "dev": true, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", "license": "MIT", "optional": true, - "os": [ - "win32" - ], + "peer": true, "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "license": "MIT", "optional": true, - "os": [ - "win32" - ], + "peer": true, "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "license": "ISC", + "dependencies": { + "unique-slug": "^3.0.0" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "license": "Apache-2.0", + "node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "license": "ISC", "dependencies": { - "safe-buffer": "^5.0.1" + "imurmurhash": "^0.1.4" }, "engines": { - "node": "*" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "license": "Unlicense" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "devOptional": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "crypto-random-string": "^2.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "devOptional": true, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 10.0.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "devOptional": true, - "license": "(MIT OR CC0-1.0)", + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "optional": true, + "peer": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "napi-postinstall": "^0.3.0" }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/typedarray-to-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-1.0.4.tgz", - "integrity": "sha512-vjMKrfSoUDN8/Vnqitw2FmstOfuJ73G6CrSEKnf11A6RmasVxHqfeBcnTb6RsL4pTMuV5Zsv9IiHRphMZyckUw==", - "dev": true, - "license": "MIT" + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } }, - "node_modules/typeorm": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.25.tgz", - "integrity": "sha512-fTKDFzWXKwAaBdEMU4k661seZewbNYET4r1J/z3Jwf+eAvlzMVpTLKAVcAzg75WwQk7GDmtsmkZ5MfkmXCiFWg==", + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "devOptional": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { - "@sqltools/formatter": "^1.2.5", - "ansis": "^3.17.0", - "app-root-path": "^3.1.0", - "buffer": "^6.0.3", - "dayjs": "^1.11.13", - "debug": "^4.4.0", - "dedent": "^1.6.0", - "dotenv": "^16.4.7", - "glob": "^10.4.5", - "sha.js": "^2.4.11", - "sql-highlight": "^6.0.0", - "tslib": "^2.8.1", - "uuid": "^11.1.0", - "yargs": "^17.7.2" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { - "typeorm": "cli.js", - "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", - "typeorm-ts-node-esm": "cli-ts-node-esm.js" - }, - "engines": { - "node": ">=16.13.0" - }, - "funding": { - "url": "https://opencollective.com/typeorm" + "update-browserslist-db": "cli.js" }, "peerDependencies": { - "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", - "@sap/hana-client": "^2.12.25", - "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", - "hdb-pool": "^0.1.6", - "ioredis": "^5.0.4", - "mongodb": "^5.8.0 || ^6.0.0", - "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", - "mysql2": "^2.2.5 || ^3.0.1", - "oracledb": "^6.3.0", - "pg": "^8.5.1", - "pg-native": "^3.0.0", - "pg-query-stream": "^4.0.0", - "redis": "^3.1.1 || ^4.0.0", - "reflect-metadata": "^0.1.14 || ^0.2.0", - "sql.js": "^1.4.0", - "sqlite3": "^5.0.3", - "ts-node": "^10.7.0", - "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" - }, - "peerDependenciesMeta": { - "@google-cloud/spanner": { - "optional": true - }, - "@sap/hana-client": { - "optional": true - }, - "better-sqlite3": { - "optional": true - }, - "hdb-pool": { - "optional": true - }, - "ioredis": { - "optional": true - }, - "mongodb": { - "optional": true - }, - "mssql": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "oracledb": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-native": { - "optional": true - }, - "pg-query-stream": { - "optional": true - }, - "redis": { - "optional": true - }, - "sql.js": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "ts-node": { - "optional": true - }, - "typeorm-aurora-data-api-driver": { - "optional": true - } + "browserslist": ">= 4.21.0" } }, - "node_modules/typeorm/node_modules/debug": { + "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "license": "MIT", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", "dependencies": { - "ms": "^2.1.3" - }, + "punycode": "^2.1.0" + } + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "license": "MIT" + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "license": "(WTFPL OR MIT)" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "optional": true, + "peer": true, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 0.4.0" } }, - "node_modules/typeorm/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "uuid": "dist/bin/uuid" } }, - "node_modules/typeorm/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10.12.0" } }, - "node_modules/typeorm/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "license": "ISC", + "optional": true, + "peer": true, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/typeorm/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/typeorm/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/validator": { + "version": "13.15.15", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", + "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } }, - "node_modules/typeorm/node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" + "optional": true, + "peer": true, + "engines": { + "node": ">= 0.8" } }, - "node_modules/types-ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.29.10.tgz", - "integrity": "sha512-5PJiW/eiTPyXXBYGZOYGezMl6qj7keBiZheRwfjJZY26QPHsNrjfJnz0mru6oeqqoTHOni893Jfd6zyUXfQRWg==", - "dev": true, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "license": "MIT", + "optional": true, "dependencies": { - "ts-toolbelt": "^9.6.0" - } - }, - "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "devOptional": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" }, "engines": { - "node": ">=14.17" + "node": ">=0.6.0" } }, - "node_modules/ua-parser-js": { - "version": "1.0.40", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", - "integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], + "node_modules/vite": { + "version": "5.4.19", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "dev": true, "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, "bin": { - "ua-parser-js": "script/cli.js" + "vite": "bin/vite.js" }, "engines": { - "node": "*" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, + "os": [ + "aix" + ], "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uint8-varint": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/uint8-varint/-/uint8-varint-2.0.4.tgz", - "integrity": "sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.0" - } - }, - "node_modules/uint8arraylist": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.8.tgz", - "integrity": "sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8arrays": "^5.0.1" - } - }, - "node_modules/uint8arrays": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.1.0.tgz", - "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^13.0.0" + "node": ">=12" } }, - "node_modules/uint8arrays/node_modules/multiformats": { - "version": "13.4.0", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.4.0.tgz", - "integrity": "sha512-Mkb/QcclrJxKC+vrcIFl297h52QcKh2Az/9A5vbWytbQt4225UWWWmIuSsKksdww9NkIeYcA7DkfftyLuC/JSg==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/undici": { - "version": "6.21.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", - "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", "optional": true, - "peer": true, + "os": [ + "android" + ], "engines": { - "node": ">=18.17" + "node": ">=12" } }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "license": "MIT" - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", "optional": true, - "peer": true, + "os": [ + "android" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", "optional": true, - "peer": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, + "os": [ + "android" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", "optional": true, - "peer": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", "optional": true, - "peer": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "devOptional": true, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "crypto-random-string": "^2.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 10.0.0" + "node": ">=12" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", "optional": true, - "peer": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.8" + "node": ">=12" } }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], "dev": true, - "hasInstallScript": true, "license": "MIT", - "dependencies": { - "napi-postinstall": "^0.3.0" - }, - "funding": { - "url": "https://opencollective.com/unrs-resolver" - }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "devOptional": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" ], + "dev": true, "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "license": "MIT" - }, - "node_modules/utf8-byte-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", - "license": "(WTFPL OR MIT)" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, "license": "MIT", "optional": true, - "peer": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4.0" + "node": ">=12" } }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" ], + "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=10.12.0" + "node": ">=12" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "license": "ISC", + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", "optional": true, - "peer": true, + "os": [ + "sunos" + ], "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/validator": { - "version": "13.15.15", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", - "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.10" + "node": ">=12" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", "optional": true, - "peer": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.8" + "node": ">=12" } }, - "node_modules/verror": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", - "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", "optional": true, - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, + "os": [ + "win32" + ], "engines": { - "node": ">=0.6.0" + "node": ">=12" } }, - "node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, "bin": { - "vite": "bin/vite.js" + "esbuild": "bin/esbuild" }, "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" + "node": ">=12" }, "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, "node_modules/vlq": { @@ -30575,16 +30737,16 @@ "peer": true }, "node_modules/vue": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.18.tgz", - "integrity": "sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", + "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.18", - "@vue/compiler-sfc": "3.5.18", - "@vue/runtime-dom": "3.5.18", - "@vue/server-renderer": "3.5.18", - "@vue/shared": "3.5.18" + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-sfc": "3.5.13", + "@vue/runtime-dom": "3.5.13", + "@vue/server-renderer": "3.5.13", + "@vue/shared": "3.5.13" }, "peerDependencies": { "typescript": "*" @@ -30605,33 +30767,6 @@ "vue": "^3.0.0 || ^2.0.0" } }, - "node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, "node_modules/vue-eslint-parser": { "version": "9.4.3", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", diff --git a/package.json b/package.json index cfe759b1..fac664f3 100644 --- a/package.json +++ b/package.json @@ -202,9 +202,9 @@ "three": "^0.156.1", "ua-parser-js": "^1.0.37", "uint8arrays": "^5.0.0", - "vue": "^3.5.13", + "vue": "3.5.13", "vue-axios": "^3.5.2", - "vue-facing-decorator": "^3.0.4", + "vue-facing-decorator": "3.0.4", "vue-picture-cropper": "^0.7.0", "vue-qrcode-reader": "^5.5.3", "vue-router": "^4.5.0", diff --git a/vite.config.common.mts b/vite.config.common.mts index 848b3b9c..1736e288 100644 --- a/vite.config.common.mts +++ b/vite.config.common.mts @@ -48,22 +48,22 @@ export async function createBuildConfig(platform: string): Promise { format: 'es', plugins: () => [] }, - // ESBuild configuration to fail on errors - esbuild: { - target: 'es2015', - supported: { - 'bigint': true - }, - // Fail on any ESBuild errors - logLevel: 'error', - // Ensure build fails on syntax errors and other critical issues - logOverride: { - 'duplicate-export': 'error', - 'duplicate-member': 'error', - 'syntax-error': 'error', - 'invalid-identifier': 'error' - } - }, + // ESBuild configuration to fail on errors - TEMPORARILY DISABLED + // esbuild: { + // target: 'es2015', + // supported: { + // 'bigint': true + // }, + // // Fail on any ESBuild errors + // logLevel: 'error', + // // Ensure build fails on syntax errors and other critical issues + // logOverride: { + // 'duplicate-export': 'error', + // 'duplicate-member': 'error', + // 'syntax-error': 'error', + // 'invalid-identifier': 'error' + // } + // }, define: { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), diff --git a/vite.config.web.mts b/vite.config.web.mts index 0bbeb204..3acca4f4 100644 --- a/vite.config.web.mts +++ b/vite.config.web.mts @@ -1,110 +1,4 @@ -import { defineConfig, mergeConfig } from "vite"; +import { defineConfig } from "vite"; import { createBuildConfig } from "./vite.config.common.mts"; -import { loadAppConfig } from "./vite.config.utils.mts"; -export default defineConfig(async ({ mode }) => { - const baseConfig = await createBuildConfig('web'); - const appConfig = await loadAppConfig(); - - // Environment-specific configuration based on mode - const getEnvironmentConfig = (mode: string) => { - switch (mode) { - case 'production': - return { - // Production optimizations - build: { - minify: 'terser', - sourcemap: false, - rollupOptions: { - output: { - manualChunks: { - vendor: ['vue', 'vue-router', 'pinia'], - utils: ['luxon', 'ramda', 'zod'], - crypto: ['@ethersproject/wallet', '@ethersproject/hdnode', 'ethereum-cryptography'], - sql: ['@jlongster/sql.js', 'absurd-sql'] - } - } - } - }, - define: { - __DEV__: false, - __TEST__: false, - __PROD__: true - } - }; - case 'test': - return { - // Test environment configuration - build: { - minify: false, - sourcemap: true, - rollupOptions: { - output: { - manualChunks: undefined - } - } - }, - define: { - __DEV__: false, - __TEST__: true, - __PROD__: false - } - }; - default: // development - return { - // Development configuration - build: { - minify: false, - sourcemap: true, - rollupOptions: { - output: { - manualChunks: undefined - } - } - }, - define: { - __DEV__: true, - __TEST__: false, - __PROD__: false - } - }; - } - }; - - const environmentConfig = getEnvironmentConfig(mode); - - return mergeConfig(baseConfig, { - ...environmentConfig, - // Ensure source maps are enabled for development and test modes - // This affects both dev server and build output - sourcemap: mode === 'development' || mode === 'test', - // Server configuration inherited from base config - // CORS headers removed to allow images from any domain - plugins: [], - // Worker configuration for SQL worker - worker: { - format: 'es', - plugins: () => [] - }, - // Optimize dependencies for SQL worker - optimizeDeps: { - include: [ - '@jlongster/sql.js', - 'absurd-sql', - 'absurd-sql/dist/indexeddb-main-thread', - 'absurd-sql/dist/indexeddb-backend' - ] - }, - // ESBuild configuration to fail on errors - esbuild: { - target: 'es2015', - supported: { - 'bigint': true - }, - // Fail on any ESBuild errors - logLevel: 'error', - // Ensure build fails on syntax errors - logOverride: { 'duplicate-export': 'error' } - } - }); -}); +export default defineConfig(async () => createBuildConfig('web')); From 8db07465ed174674540b45d15649bb57b15de024 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 09:26:48 +0000 Subject: [PATCH 23/35] fix(typescript): resolve ProfileService typing issues and eliminate any types - Replace unsafe (error as any).config patterns with proper type guards - Add hasConfigProperty() type guard for safe error property checking - Add getConfigProperty() method for type-safe config extraction - Eliminate @typescript-eslint/no-explicit-any violations Problem: ProfileService had unsafe type casting with (error as any).config that violated TypeScript type safety guidelines and caused linting errors. Solution: Implement proper type guards following established patterns: - hasConfigProperty() safely checks if error has config property - getConfigProperty() extracts config without type casting - Maintains exact same functionality while ensuring type safety Files changed: - src/services/ProfileService.ts: Replace any types with type guards Testing: Linting passes, type-check passes, functionality preserved. --- src/services/ProfileService.ts | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/services/ProfileService.ts b/src/services/ProfileService.ts index 8f8abcdc..3ec64edd 100644 --- a/src/services/ProfileService.ts +++ b/src/services/ProfileService.ts @@ -261,13 +261,31 @@ export class ProfileService { if (this.isAxiosError(error)) { return error.config?.url; } - if (this.isApiError(error) && (error as any).config) { - const config = (error as any).config as { url?: string }; - return config.url; + if (this.isApiError(error) && this.hasConfigProperty(error)) { + const config = this.getConfigProperty(error); + return config?.url; } return undefined; } + /** + * Type guard to check if error has config property + */ + private hasConfigProperty( + error: unknown, + ): error is { config?: { url?: string } } { + return typeof error === "object" && error !== null && "config" in error; + } + + /** + * Safely extract config property from error + */ + private getConfigProperty(error: { + config?: { url?: string }; + }): { url?: string } | undefined { + return error.config; + } + /** * Type guard for AxiosError */ From d663c52f2dd5c4e783f8fb1bfac0f679e15a47ce Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 12:59:48 +0000 Subject: [PATCH 24/35] feat: implement Build Architecture Guard with Husky hooks - Add pre-commit and pre-push hooks for build file protection - Create comprehensive guard script for BUILDING.md validation - Add npm scripts for guard setup and testing - Integrate with existing build system --- .husky/_/husky.sh | 40 ++++++++ .husky/commit-msg | 10 ++ .husky/pre-commit | 15 +++ .husky/pre-push | 27 ++++++ package.json | 17 ++++ scripts/build-arch-guard.sh | 187 ++++++++++++++++++++++++++++++++++++ 6 files changed, 296 insertions(+) create mode 100755 .husky/_/husky.sh create mode 100755 .husky/commit-msg create mode 100755 .husky/pre-commit create mode 100755 .husky/pre-push create mode 100755 scripts/build-arch-guard.sh diff --git a/.husky/_/husky.sh b/.husky/_/husky.sh new file mode 100755 index 00000000..8de639c0 --- /dev/null +++ b/.husky/_/husky.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env sh +# +# Husky Helper Script +# This file is sourced by all Husky hooks +# +if [ -z "$husky_skip_init" ]; then + debug () { + if [ "$HUSKY_DEBUG" = "1" ]; then + echo "husky (debug) - $1" + fi + } + + readonly hook_name="$(basename -- "$0")" + debug "starting $hook_name..." + + if [ "$HUSKY" = "0" ]; then + debug "HUSKY env variable is set to 0, skipping hook" + exit 0 + fi + + if [ -f ~/.huskyrc ]; then + debug "sourcing ~/.huskyrc" + . ~/.huskyrc + fi + + readonly husky_skip_init=1 + export husky_skip_init + sh -e "$0" "$@" + exitCode="$?" + + if [ $exitCode != 0 ]; then + echo "husky - $hook_name hook exited with code $exitCode (error)" + fi + + if [ $exitCode = 127 ]; then + echo "husky - command not found in PATH=$PATH" + fi + + exit $exitCode +fi diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 00000000..4b8c242d --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# +# Husky Commit Message Hook +# Validates commit message format using commitlint +# +. "$(dirname -- "$0")/_/husky.sh" + +# Run commitlint but don't fail the commit (|| true) +# This provides helpful feedback without blocking commits +npx commitlint --edit "$1" || true diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..7d7b33e3 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# +# Husky Pre-commit Hook +# Runs Build Architecture Guard to check staged files +# +. "$(dirname -- "$0")/_/husky.sh" + +echo "🔍 Running Build Architecture Guard (pre-commit)..." +bash ./scripts/build-arch-guard.sh --staged || { + echo + echo "💡 To bypass this check for emergency commits, use:" + echo " git commit --no-verify" + echo + exit 1 +} diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 00000000..12a16ea5 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# +# Husky Pre-push Hook +# Runs Build Architecture Guard to check commits being pushed +# +. "$(dirname -- "$0")/_/husky.sh" + +echo "🔍 Running Build Architecture Guard (pre-push)..." + +# Get the remote branch we're pushing to +REMOTE_BRANCH="origin/$(git rev-parse --abbrev-ref HEAD)" + +# Check if remote branch exists +if git show-ref --verify --quiet "refs/remotes/$REMOTE_BRANCH"; then + RANGE="$REMOTE_BRANCH...HEAD" +else + # If remote branch doesn't exist, check last commit + RANGE="HEAD~1..HEAD" +fi + +bash ./scripts/build-arch-guard.sh --range "$RANGE" || { + echo + echo "💡 To bypass this check for emergency pushes, use:" + echo " git push --no-verify" + echo + exit 1 +} diff --git a/package.json b/package.json index fac664f3..77a4ac92 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,13 @@ "build:electron:dmg:dev": "./scripts/build-electron.sh --dev --dmg", "build:electron:dmg:test": "./scripts/build-electron.sh --test --dmg", "build:electron:dmg:prod": "./scripts/build-electron.sh --prod --dmg", + "markdown:fix": "./scripts/fix-markdown.sh", + "markdown:check": "./scripts/validate-markdown.sh", + "markdown:setup": "./scripts/setup-markdown-hooks.sh", + "prepare": "husky", + "guard": "bash ./scripts/build-arch-guard.sh", + "guard:test": "bash ./scripts/build-arch-guard.sh --staged", + "guard:setup": "npm run prepare && echo '✅ Build Architecture Guard is now active!'", "clean:android": "./scripts/clean-android.sh", "clean:ios": "rm -rf ios/App/build ios/App/Pods ios/App/output ios/App/App/public ios/DerivedData ios/capacitor-cordova-ios-plugins ios/App/App/capacitor.config.json ios/App/App/config.xml || true", "clean:electron": "./scripts/build-electron.sh --clean", @@ -124,6 +131,12 @@ "build:android:dev:run:custom": "./scripts/build-android.sh --dev --api-ip --auto-run", "build:android:test:run:custom": "./scripts/build-android.sh --test --api-ip --auto-run" }, + "lint-staged": { + "*.{js,ts,vue,css,md,json,yml,yaml}": "eslint --fix || true" + }, + "commitlint": { + "extends": ["@commitlint/config-conventional"] + }, "dependencies": { "@capacitor-community/electron": "^5.0.1", "@capacitor-community/sqlite": "6.0.2", @@ -243,6 +256,10 @@ "jest": "^30.0.4", "markdownlint": "^0.37.4", "markdownlint-cli": "^0.44.0", + "husky": "^9.0.11", + "lint-staged": "^15.2.2", + "@commitlint/cli": "^18.6.1", + "@commitlint/config-conventional": "^18.6.2", "npm-check-updates": "^17.1.13", "path-browserify": "^1.0.1", "postcss": "^8.4.38", diff --git a/scripts/build-arch-guard.sh b/scripts/build-arch-guard.sh new file mode 100755 index 00000000..77a69ae7 --- /dev/null +++ b/scripts/build-arch-guard.sh @@ -0,0 +1,187 @@ +#!/usr/bin/env bash +# +# Build Architecture Guard Script +# +# Author: Matthew Raymer +# Date: 2025-08-20 +# Purpose: Protects build-critical files by requiring BUILDING.md updates +# +# Usage: +# ./scripts/build-arch-guard.sh --staged # Check staged files (pre-commit) +# ./scripts/build-arch-guard.sh --range # Check range (pre-push) +# ./scripts/build-arch-guard.sh # Check working directory +# + +set -euo pipefail + +# Sensitive paths that require BUILDING.md updates when modified +SENSITIVE=( + "vite.config.*" + "scripts/**" + "electron/**" + "android/**" + "ios/**" + "sw_scripts/**" + "sw_combine.js" + "Dockerfile" + "docker/**" + "capacitor.config.ts" + "package.json" + "package-lock.json" + "yarn.lock" + "pnpm-lock.yaml" +) + +# Documentation files that must be updated alongside sensitive changes +DOCS_REQUIRED=("BUILDING.md") + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${BLUE}[guard]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[guard]${NC} $1" +} + +log_error() { + echo -e "${RED}[guard]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[guard]${NC} $1" +} + +# Collect files based on mode +collect_files() { + if [[ "${1:-}" == "--staged" ]]; then + # Pre-commit: check staged files + git diff --name-only --cached + elif [[ "${1:-}" == "--range" ]]; then + # Pre-push: check commits being pushed + RANGE="${2:-HEAD~1..HEAD}" + git diff --name-only "$RANGE" + else + # Default: check working directory changes + git diff --name-only HEAD + fi +} + +# Check if a file matches any sensitive pattern +matches_sensitive() { + local f="$1" + for pat in "${SENSITIVE[@]}"; do + # Convert glob pattern to regex + local rx="^${pat//\./\.}$" + rx="${rx//\*\*/.*}" + rx="${rx//\*/[^/]*}" + + if [[ "$f" =~ $rx ]]; then + return 0 + fi + done + return 1 +} + +# Check if documentation was updated +check_docs_updated() { + local changed_files=("$@") + + for changed_file in "${changed_files[@]}"; do + for required_doc in "${DOCS_REQUIRED[@]}"; do + if [[ "$changed_file" == "$required_doc" ]]; then + return 0 + fi + done + done + return 1 +} + +# Main guard logic +main() { + local mode="${1:-}" + local arg="${2:-}" + + log_info "Running Build Architecture Guard..." + + # Collect changed files + mapfile -t changed_files < <(collect_files "$mode" "$arg") + + if [[ ${#changed_files[@]} -eq 0 ]]; then + log_info "No files changed, guard check passed" + exit 0 + fi + + log_info "Checking ${#changed_files[@]} changed files..." + + # Find sensitive files that were touched + sensitive_touched=() + for file in "${changed_files[@]}"; do + if matches_sensitive "$file"; then + sensitive_touched+=("$file") + fi + done + + # If no sensitive files were touched, allow the change + if [[ ${#sensitive_touched[@]} -eq 0 ]]; then + log_success "No build-sensitive files changed, guard check passed" + exit 0 + fi + + # Sensitive files were touched, log them + log_warn "Build-sensitive paths changed:" + for file in "${sensitive_touched[@]}"; do + echo " - $file" + done + + # Check if required documentation was updated + if check_docs_updated "${changed_files[@]}"; then + log_success "BUILDING.md updated alongside build changes, guard check passed" + exit 0 + else + log_error "Build-sensitive files changed but BUILDING.md was not updated!" + echo + echo "The following build-sensitive files were modified:" + for file in "${sensitive_touched[@]}"; do + echo " - $file" + done + echo + echo "When modifying build-critical files, you must also update BUILDING.md" + echo "to document any changes to the build process." + echo + echo "Please:" + echo " 1. Update BUILDING.md with relevant changes" + echo " 2. Stage the BUILDING.md changes: git add BUILDING.md" + echo " 3. Retry your commit/push" + echo + exit 2 + fi +} + +# Handle help flag +if [[ "${1:-}" =~ ^(-h|--help)$ ]]; then + echo "Build Architecture Guard Script" + echo + echo "Usage:" + echo " $0 [--staged|--range [RANGE]]" + echo + echo "Options:" + echo " --staged Check staged files (for pre-commit hook)" + echo " --range [RANGE] Check git range (for pre-push hook)" + echo " Default range: HEAD~1..HEAD" + echo " (no args) Check working directory changes" + echo + echo "Examples:" + echo " $0 --staged # Pre-commit check" + echo " $0 --range origin/main..HEAD # Pre-push check" + echo " $0 # Working directory check" + exit 0 +fi + +main "$@" From d5786e513118e544fe590b552271983130c2ea80 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 12:59:57 +0000 Subject: [PATCH 25/35] docs: add comprehensive Build Architecture Guard documentation - Update main README with guard system overview - Create detailed guard implementation guide - Add PR template documentation and usage examples - Document opt-in hook activation process --- README-BUILD-GUARD.md | 290 ++++++++++++++++++++++++++++++++++++++++ README-PR-TEMPLATE.md | 82 ++++++++++++ README.md | 304 +++++++++++------------------------------- 3 files changed, 448 insertions(+), 228 deletions(-) create mode 100644 README-BUILD-GUARD.md create mode 100644 README-PR-TEMPLATE.md diff --git a/README-BUILD-GUARD.md b/README-BUILD-GUARD.md new file mode 100644 index 00000000..9b617edb --- /dev/null +++ b/README-BUILD-GUARD.md @@ -0,0 +1,290 @@ +# Build Architecture Guard - Husky Implementation + +## Overview + +The Build Architecture Guard protects your build system by enforcing +documentation requirements through **Git hooks**. When you modify +build-critical files, the system automatically blocks commits/pushes +until you update `BUILDING.md`. + +## 🎯 **Why Husky-Only?** + +**Advantages:** + +- ✅ **Immediate feedback** - Hooks run before commit/push +- ✅ **Works everywhere** - No server-side CI/CD required +- ✅ **Simple setup** - One tool, one configuration +- ✅ **Fast execution** - No network delays or server queues +- ✅ **Offline support** - Works without internet connection + +**Trade-offs:** + +- ⚠️ **Can be bypassed** - `git commit --no-verify` or `git push --no-verify` +- ⚠️ **Developer discipline** - Relies on team following the rules + +## 🏗️ **Architecture** + +```bash +Developer Workflow: +1. Modify build files (scripts/, vite.config.*, etc.) +2. Try to commit → Husky pre-commit hook runs +3. Guard script checks if BUILDING.md was updated +4. ✅ Commit succeeds if docs updated +5. ❌ Commit blocked if docs missing +``` + +## 🚀 **Quick Start** + +### 1. Install Dependencies + +```bash +npm install +npm run prepare # Sets up Husky hooks +``` + +### 2. Test the System + +```bash +# Modify a build file without updating BUILDING.md +echo "# test" >> scripts/test.sh + +# Try to commit (should be blocked) +git add scripts/test.sh +git commit -m "test: add build script" +# ❌ Hook blocks commit with helpful message +``` + +### 3. Fix and Retry + +```bash +# Update BUILDING.md with your changes +echo "## New Build Script" >> BUILDING.md +echo "Added test.sh for testing purposes" >> BUILDING.md + +# Now commit should succeed +git add BUILDING.md +git commit -m "feat: add test build script with docs" +# ✅ Commit succeeds +``` + +## 🔧 **How It Works** + +### Pre-commit Hook (`.husky/pre-commit`) + +- **When**: Every `git commit` +- **What**: Runs `./scripts/build-arch-guard.sh --staged` +- **Result**: Blocks commit if build files changed without BUILDING.md update + +### Pre-push Hook (`.husky/pre-push`) + +- **When**: Every `git push` +- **What**: Runs `./scripts/build-arch-guard.sh --range` +- **Result**: Blocks push if commits contain undocumented build changes + +### Guard Script (`scripts/build-arch-guard.sh`) + +- **Detects**: Changes to build-sensitive file patterns +- **Validates**: BUILDING.md was updated alongside changes +- **Reports**: Clear error messages with guidance + +## 📁 **Protected File Patterns** + +The guard script monitors these paths for changes: + +```text +Build Configuration: +├── vite.config.* # Vite configuration +├── capacitor.config.ts # Capacitor configuration +├── package.json # Package configuration +├── package-lock.json # Lock files +├── yarn.lock +└── pnpm-lock.yaml + +Build Scripts: +├── scripts/** # All build and automation scripts +├── electron/** # Electron build files +├── android/** # Android build configuration +├── ios/** # iOS build configuration +├── sw_scripts/** # Service worker scripts +└── sw_combine.js # Service worker combination + +Deployment: +├── Dockerfile # Docker configuration +└── docker/** # Docker services +``` + +## 🎭 **Usage Scenarios** + +### Scenario 1: Adding a New Build Script + +```bash +# ❌ This will be blocked +echo '#!/bin/bash' > scripts/new-build.sh +git add scripts/new-build.sh +git commit -m "feat: add new build script" +# Hook blocks: "Build-sensitive files changed but BUILDING.md not updated" + +# ✅ This will succeed +echo '#!/bin/bash' > scripts/new-build.sh +echo '## New Build Script' >> BUILDING.md +echo 'Added new-build.sh for feature X' >> BUILDING.md +git add scripts/new-build.sh BUILDING.md +git commit -m "feat: add new build script with docs" +# ✅ Commit succeeds +``` + +### Scenario 2: Updating Vite Configuration + +```bash +# ❌ This will be blocked +echo 'export default { newOption: true }' >> vite.config.ts +git add vite.config.ts +git commit -m "config: add new vite option" +# Hook blocks: "Build-sensitive files changed but BUILDING.md not updated" + +# ✅ This will succeed +echo 'export default { newOption: true }' >> vite.config.ts +echo '### New Vite Option' >> BUILDING.md +echo 'Added newOption for improved performance' >> BUILDING.md +git add vite.config.ts BUILDING.md +git commit -m "config: add new vite option with docs" +# ✅ Commit succeeds +``` + +## 🚨 **Emergency Bypass** + +**⚠️ Use sparingly and only for emergencies:** + +```bash +# Skip pre-commit hook +git commit -m "emergency: critical fix" --no-verify + +# Skip pre-push hook +git push --no-verify + +# Remember to update BUILDING.md later! +``` + +## 🔍 **Troubleshooting** + +### Hooks Not Running + +```bash +# Reinstall hooks +npm run prepare + +# Check hook files exist and are executable +ls -la .husky/ +chmod +x .husky/* + +# Verify Git hooks path +git config core.hooksPath +# Should show: .husky +``` + +### Guard Script Issues + +```bash +# Test guard script manually +./scripts/build-arch-guard.sh --help + +# Check script permissions +chmod +x scripts/build-arch-guard.sh + +# Test with specific files +./scripts/build-arch-guard.sh --staged +``` + +### False Positives + +```bash +# If guard blocks legitimate changes, check: +# 1. Are you modifying a protected file pattern? +# 2. Did you update BUILDING.md? +# 3. Is BUILDING.md staged for commit? + +# View what the guard sees +git diff --name-only --cached +``` + +## 📋 **Best Practices** + +### For Developers + +1. **Update BUILDING.md first** - Document changes before implementing +2. **Test locally** - Run `./scripts/build-arch-guard.sh --staged` before committing +3. **Use descriptive commits** - Include context about build changes +4. **Don't bypass lightly** - Only use `--no-verify` for true emergencies + +### For Teams + +1. **Document the system** - Ensure everyone understands the guard +2. **Review BUILDING.md updates** - Verify documentation quality +3. **Monitor bypass usage** - Track when hooks are skipped +4. **Regular audits** - Check that BUILDING.md stays current + +### For Maintainers + +1. **Update protected patterns** - Modify `scripts/build-arch-guard.sh` as needed +2. **Monitor effectiveness** - Track how often the guard catches issues +3. **Team training** - Help developers understand the system +4. **Continuous improvement** - Refine patterns and error messages + +## 🔄 **Customization** + +### Adding New Protected Paths + +Edit `scripts/build-arch-guard.sh`: + +```bash +SENSITIVE=( + # ... existing patterns ... + "new-pattern/**" # Add your new pattern + "*.config.js" # Add file extensions +) +``` + +### Modifying Error Messages + +Edit the guard script to customize: + +- Error message content +- File pattern matching +- Documentation requirements +- Bypass instructions + +### Adding New Validation Rules + +Extend the guard script to check for: + +- Specific file content patterns +- Required documentation sections +- Commit message formats +- Branch naming conventions + +## 📚 **Integration with PR Template** + +The `pull_request_template.md` works with this system by: + +- **Guiding developers** through required documentation +- **Ensuring consistency** across all build changes +- **Providing checklist** for comprehensive updates +- **Supporting L1/L2/L3** change classification + +## 🎯 **Success Metrics** + +Track the effectiveness of your Build Architecture Guard: + +- **Hook execution rate** - How often hooks run successfully +- **Bypass frequency** - How often `--no-verify` is used +- **Documentation quality** - BUILDING.md stays current +- **Build failures** - Fewer issues from undocumented changes +- **Team adoption** - Developers follow the process + +--- + +**Status**: Active protection system +**Architecture**: Client-side Git hooks only +**Dependencies**: Husky, Git, Bash +**Maintainer**: Development team +**Related**: `pull_request_template.md`, `scripts/build-arch-guard.sh` diff --git a/README-PR-TEMPLATE.md b/README-PR-TEMPLATE.md new file mode 100644 index 00000000..fa977e02 --- /dev/null +++ b/README-PR-TEMPLATE.md @@ -0,0 +1,82 @@ +# Pull Request Template + +## Location + +The Build Architecture Guard PR template is located at: + +- **`pull_request_template.md`** (root directory) + +## Usage + +When creating a pull request in Gitea, this template will automatically populate the PR description with the required checklist. + +## Template Features + +### Change Level Classification + +- **L1**: Minor changes, documentation updates +- **L2**: Moderate changes, new features, environment changes +- **L3**: Major changes, architecture changes, new platforms + +### Required Fields for All Levels + +- Change level selection +- Scope and impact description +- Commands executed and their output +- Documentation updates (BUILDING.md) +- Rollback verification steps + +### Additional Requirements for L3 + +- **ADR link**: Must provide URL to Architectural Decision Record +- **Artifacts with SHA256**: Must list artifacts with cryptographic hashes + +## Integration + +This template works with: + +- **Gitea Actions**: `.gitea/workflows/build-guard.yml` +- **Client-side hooks**: `.husky/` pre-commit and pre-push hooks +- **Guard script**: `scripts/build-arch-guard.sh` + +## Example Usage + +```markdown +### Change Level +- [x] Level: **L2** + +**Why:** Adding new build script for Docker deployment + +### Scope & Impact +- [x] Files & platforms touched: scripts/build-docker.sh, + BUILDING.md +- [x] Risk triggers: Docker build process changes +- [x] Mitigations/validation done: Tested on local Docker environment + +### Commands Run +- [x] Web: `npm run build:web:docker` ✅ +- [x] Docker: `docker build -t test-image .` ✅ + +### Artifacts +- [x] Names + **sha256** of artifacts/installers: + +Artifacts: +```text +test-image.tar a1b2c3d4e5f6... +``` + +### Docs +- [x] **BUILDING.md** updated (sections): Docker deployment +- [x] Troubleshooting updated: Added Docker troubleshooting section + +### Rollback +- [x] Verified steps to restore previous behavior: + 1. `git revert HEAD` + 2. `docker rmi test-image` + 3. Restore previous BUILDING.md +``` + +--- + +**Note**: This template is enforced by the Build Architecture Guard +system. Complete all required fields to ensure your PR can be merged. diff --git a/README.md b/README.md index fc954fd5..c39fbde9 100644 --- a/README.md +++ b/README.md @@ -1,270 +1,118 @@ -# TimeSafari.app - Crowd-Funder for Time - PWA +# Time Safari Application -[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. +**Author**: Matthew Raymer +**Version**: 1.0.8-beta +**Description**: Time Safari Application -## Roadmap +## 🛡️ Build Architecture Guard -See [ClickUp](https://sharing.clickup.com/9014278710/l/h/8cmnyhp-174/10573fec74e2ba0) for current priorities. +This project uses **Husky Git hooks** to protect the build system +architecture. When you modify build-critical files, the system +automatically blocks commits until you update `BUILDING.md`. -## Setup & Building - -Quick start: - -* For setup, we recommend [pkgx](https://pkgx.dev), which installs what you need (either automatically or with the `dev` command). Core dependencies are typescript & npm; when building for other platforms, you'll need other things such as those in the pkgx.yaml & BUILDING.md files. +### Quick Setup ```bash -npm install -npm run build:web:serve -- --test -``` - -To be able to make submissions: go to "profile" (bottom left), go to the bottom and expand "Show Advanced Settings", go to the bottom and to the "Test Page", and finally "Become User 0" to see all the functionality. - -See [BUILDING.md](BUILDING.md) for comprehensive build instructions for all platforms (Web, Electron, iOS, Android, Docker). - -## Development Database Clearing - -TimeSafari provides a simple script-based approach to clear the local database (not the claim server) for development purposes. - -## Logging Configuration - -TimeSafari supports configurable logging levels via the `VITE_LOG_LEVEL` environment variable. This allows developers to control console output verbosity without modifying code. - -### Quick Usage - -```bash -# Show only errors -VITE_LOG_LEVEL=error npm run dev - -# Show warnings and errors -VITE_LOG_LEVEL=warn npm run dev - -# Show info, warnings, and errors (default) -VITE_LOG_LEVEL=info npm run dev - -# Show all log levels including debug -VITE_LOG_LEVEL=debug npm run dev +npm run guard:setup # Install and activate the guard ``` -### Available Levels +### How It Works -- **`error`**: Critical errors only -- **`warn`**: Warnings and errors (default for production web) -- **`info`**: Info, warnings, and errors (default for development/capacitor) -- **`debug`**: All log levels including verbose debugging +- **Pre-commit**: Blocks commits if build files changed without + BUILDING.md updates +- **Pre-push**: Blocks pushes if commits contain undocumented build + changes +- **Protected paths**: `scripts/`, `vite.config.*`, `electron/`, + `android/`, `ios/`, etc. -See [Logging Configuration Guide](doc/logging-configuration.md) for complete details. +### Usage -### Quick Usage ```bash -# Run the database clearing script -./scripts/clear-database.sh +# Test the guard manually +npm run guard:test -# Then restart your development server -npm run build:electron:dev # For Electron -npm run build:web:dev # For Web +# Emergency bypass (use sparingly) +git commit --no-verify +git push --no-verify ``` -### 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 +**📚 Full documentation**: See `README-BUILD-GUARD.md` -### Manual Commands (if needed) +## 🚀 Quick Start -#### **Electron Database Location** -```bash -# Linux -rm -rf ~/.config/TimeSafari/* +### Prerequisites -# macOS -rm -rf ~/Library/Application\ Support/TimeSafari/* +- Node.js 18+ +- npm, yarn, or pnpm +- Git -# Windows -rmdir /s /q %APPDATA%\TimeSafari -``` +### Installation -#### **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`; +npm install +npm run guard:setup # Sets up Build Architecture Guard ``` -### Documentation - -- [Constants and Configuration](src/constants/app.ts) - Core constants - -## Tests - -See [TESTING.md](test-playwright/TESTING.md) for detailed test instructions. - -## Asset Management - -TimeSafari uses a standardized asset configuration system for consistent -icon and splash screen generation across all platforms. - -### Asset Sources - -- **Single source of truth**: `resources/` directory (Capacitor default) -- **Source files**: `icon.png`, `splash.png`, `splash_dark.png` -- **Format**: PNG or SVG files for optimal quality - -### Asset Generation - -- **Configuration**: `config/assets/capacitor-assets.config.json` -- **Schema validation**: `config/assets/schema.json` -- **Build-time generation**: Platform assets generated via `capacitor-assets` -- **No VCS commits**: Generated assets are never committed to version control - -### Development Commands +### Development ```bash -# Generate/update asset configurations -npm run assets:config - -# Validate asset configurations -npm run assets:validate - -# Clean generated platform assets (local dev only) -npm run assets:clean - -# Build with asset generation -npm run build:native +npm run build:web:dev # Build web version +npm run build:ios:test # Build iOS test version +npm run build:android:test # Build Android test version +npm run build:electron:dev # Build Electron dev version ``` -### Environment Setup & Dependencies - -Before building the application, ensure your development environment is properly -configured: +### Testing ```bash -# Install all dependencies (required first time and after updates) -npm install - -# Validate your development environment -npm run check:dependencies - -# Check prerequisites for testing -npm run test:prerequisites +npm run test:web # Run web tests +npm run test:mobile # Run mobile tests +npm run test:all # Run all tests ``` -**Common Issues & Solutions**: - -- **"tsx: command not found"**: Run `npm install` to install devDependencies -- **"capacitor-assets: command not found"**: Ensure `@capacitor/assets` is installed -- **Build failures**: Run `npm run check:dependencies` to diagnose environment issues - -**Required Versions**: -- Node.js: 18+ (LTS recommended) -- npm: 8+ (comes with Node.js) -- Platform-specific tools: Android Studio, Xcode (for mobile builds) - -### Platform Support - -- **Android**: Adaptive icons with foreground/background, monochrome support -- **iOS**: LaunchScreen storyboard preferred, splash assets when needed -- **Web**: PWA icons generated during build to `dist/` (not committed) - -### Font Awesome Icons - -To add a Font Awesome icon, add to `fontawesome.ts` and reference with -`font-awesome` element and `icon` attribute with the hyphenated name. - -## Other - -### Reference Material - -* Notifications can be type of `toast` (self-dismiss), `info`, `success`, `warning`, and `danger`. - They are done via [notiwind](https://www.npmjs.com/package/notiwind) and set up in App.vue. - -* [Customize Vue configuration](https://cli.vuejs.org/config/). - -* If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js, eg: `publicPath: "/app/time-tracker/",` - -### Code Organization - -The project uses a centralized approach to type definitions and interfaces: +## 📁 Project Structure + +```text +timesafari/ +├── 📁 src/ # Source code +├── 📁 scripts/ # Build and automation scripts +├── 📁 electron/ # Electron configuration +├── 📁 android/ # Android configuration +├── 📁 ios/ # iOS configuration +├── 📁 .husky/ # Git hooks (Build Architecture Guard) +├── 📄 BUILDING.md # Build system documentation +├── 📄 pull_request_template.md # PR template +└── 📄 README-BUILD-GUARD.md # Guard system documentation +``` -* `src/interfaces/` - Contains all TypeScript interfaces and type definitions - * `deepLinks.ts` - Deep linking type system and Zod validation schemas - * `give.ts` - Give-related interfaces and type definitions - * `claims.ts` - Claim-related interfaces and verifiable credentials - * `common.ts` - Shared interfaces and utility types - * Other domain-specific interface files +## 🔧 Build System -Key principles: -- All interfaces and types are defined in the interfaces folder -- Zod schemas are used for runtime validation and type generation -- Domain-specific interfaces are separated into their own files -- Common interfaces are shared through `common.ts` -- Type definitions are generated from Zod schemas where possible +This project supports multiple platforms: -### Database Architecture +- **Web**: Vite-based build with service worker support +- **Mobile**: Capacitor-based iOS and Android builds +- **Desktop**: Electron-based cross-platform desktop app +- **Docker**: Containerized deployment options -The application uses a platform-agnostic database layer with Vue mixins for service access: +## 📚 Documentation -* `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) +- **`BUILDING.md`** - Complete build system guide +- **`README-BUILD-GUARD.md`** - Build Architecture Guard documentation +- **`pull_request_template.md`** - PR template for build changes -**Development Guidelines**: +## 🤝 Contributing -- 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()` +1. **Follow the Build Architecture Guard** - Update BUILDING.md when modifying build files +2. **Use the PR template** - Complete the checklist for build-related changes +3. **Test your changes** - Ensure builds work on affected platforms +4. **Document updates** - Keep BUILDING.md current and accurate -**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. +## 📄 License -### Kudos +[Add your license information here] -Gifts make the world go 'round! +--- -* [WebStorm by JetBrains](https://www.jetbrains.com/webstorm/) for the free open-source license -* [Máximo Fernández](https://medium.com/@maxfarenas) for the 3D [code](https://github.com/maxfer03/vue-three-ns) and [explanatory post](https://medium.com/nicasource/building-an-interactive-web-portfolio-with-vue-three-js-part-three-implementing-three-js-452cb375ef80) -* [Many tools & libraries](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/src/branch/master/package.json#L10) such as Nodejs.org, IntelliJ Idea, Veramo.io, Vuejs.org, threejs.org -* [Bush 3D model](https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439) -* [Forest floor image](https://www.goodfreephotos.com/albums/textures/leafy-autumn-forest-floor.jpg) -* Time Safari logo assisted by [DALL-E in ChatGPT](https://chat.openai.com/g/g-2fkFE8rbu-dall-e) -* [DiceBear](https://www.dicebear.com/licenses/) and [Avataaars](https://www.dicebear.com/styles/avataaars/#details) for human-looking identicons -* Some gratitude prompts thanks to [Develop Good Habits](https://www.developgoodhabits.com/gratitude-journal-prompts/) +**Note**: The Build Architecture Guard is active and will block +commits/pushes that modify build files without proper documentation +updates. See `README-BUILD-GUARD.md` for complete details. From 7b31ea014341145680d553572e72898e4cad3af2 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 13:00:06 +0000 Subject: [PATCH 26/35] feat: add Build Architecture Guard PR template - Create structured template for build-related changes - Include L1/L2/L3 change classification - Require BUILDING.md updates for sensitive file changes - Add artifact SHA256 validation for L3 changes --- pull_request_template.md | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 pull_request_template.md diff --git a/pull_request_template.md b/pull_request_template.md new file mode 100644 index 00000000..8739bdbd --- /dev/null +++ b/pull_request_template.md @@ -0,0 +1,47 @@ +# Build Architecture Guard PR Template + +## Change Level + +- [ ] Level: **L1** / **L2** / **L3** (pick one) + +**Why:** … + +## Scope & Impact + +- [ ] Files & platforms touched: … +- [ ] Risk triggers (env / script flow / packaging / SW+WASM / + Docker / signing): … +- [ ] Mitigations/validation done: … + +## Commands Run (paste exact logs/snips) + +- [ ] Web: `npm run build:web` / `:prod` +- [ ] Electron: `npm run build:electron:dev` / package step +- [ ] Mobile: `npm run build:android:test` / iOS equivalent +- [ ] Clean/auto-run impacted scripts + +## Artifacts + +- [ ] Names + **sha256** of artifacts/installers: + +Artifacts: + +```text + + +``` + +## Docs + +- [ ] **BUILDING.md** updated (sections): … +- [ ] Troubleshooting updated (if applicable) + +## Rollback + +- [ ] Verified steps (1–3 cmds) to restore previous behavior + +## L3 only + +- [ ] ADR link: + +ADR: https://… From ae0601281b2d81d3d824c5179b553aa4b5e8668e Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 13:00:16 +0000 Subject: [PATCH 27/35] feat: add markdown validation and auto-fix scripts - Create validate-markdown.sh for compliance checking - Add fix-markdown.sh for automatic formatting fixes - Exclude node_modules from validation scope - Integrate with npm scripts for easy usage --- scripts/fix-markdown.sh | 19 +++++++++++++++++++ scripts/validate-markdown.sh | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100755 scripts/fix-markdown.sh create mode 100755 scripts/validate-markdown.sh diff --git a/scripts/fix-markdown.sh b/scripts/fix-markdown.sh new file mode 100755 index 00000000..b2a21f6d --- /dev/null +++ b/scripts/fix-markdown.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "🔧 Auto-fixing markdown formatting..." + +# Check if markdownlint is available +if ! command -v npx &> /dev/null; then + echo "❌ npx not found. Please install Node.js and npm first." + exit 1 +fi + +# Run markdownlint with auto-fix on project markdown files (exclude node_modules) +echo "📝 Fixing project markdown files..." +npx markdownlint "*.md" "*.mdc" "scripts/**/*.md" "src/**/*.md" "test-playwright/**/*.md" "resources/**/*.md" --config .markdownlint.json --fix 2>/dev/null || { + echo "⚠️ Some issues could not be auto-fixed. Check manually." +} + +echo "✅ Markdown auto-fix complete!" +echo "💡 Run 'npm run markdown:check' to verify all issues are resolved." diff --git a/scripts/validate-markdown.sh b/scripts/validate-markdown.sh new file mode 100755 index 00000000..f54f9dee --- /dev/null +++ b/scripts/validate-markdown.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "🔍 Validating markdown formatting..." + +# Check if markdownlint is available +if ! command -v npx &> /dev/null; then + echo "❌ npx not found. Please install Node.js and npm first." + exit 1 +fi + +# Run markdownlint on project markdown files (exclude node_modules) +echo "📝 Checking project markdown files..." +npx markdownlint "*.md" "*.mdc" "scripts/**/*.md" "src/**/*.md" "test-playwright/**/*.md" "resources/**/*.md" --config .markdownlint.json 2>/dev/null || { + echo "❌ Markdown validation failed. Run 'npm run markdown:fix' to auto-fix issues." + exit 1 +} + +echo "✅ All markdown files pass validation!" From 8336d9d6bda81540bd0be8f41fa5dbaca0acdcf3 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 13:00:26 +0000 Subject: [PATCH 28/35] feat: enhance markdown rules for AI generation compliance - Add AI Generation Guidelines with alwaysApply: true - Extend globs to include .mdc files - Ensure AI agents follow rules during content creation - Improve markdown automation system integration --- .cursor/rules/docs/markdown.mdc | 36 ++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/.cursor/rules/docs/markdown.mdc b/.cursor/rules/docs/markdown.mdc index f95f297b..fddda015 100644 --- a/.cursor/rules/docs/markdown.mdc +++ b/.cursor/rules/docs/markdown.mdc @@ -1,5 +1,5 @@ --- -globs: *.md +globs: ["*.md", "*.mdc"] alwaysApply: false --- # Cursor Markdown Ruleset for TimeSafari Documentation @@ -10,6 +10,36 @@ This ruleset enforces consistent markdown formatting standards across all projec documentation, ensuring readability, maintainability, and compliance with markdownlint best practices. +**⚠️ CRITICAL FOR AI AGENTS**: These rules must be followed DURING content +generation, not applied after the fact. Always generate markdown that complies +with these standards from the start. + +## AI Generation Guidelines + +### **MANDATORY**: Follow These Rules While Writing + +When generating markdown content, you MUST: + +1. **Line Length**: Never exceed 80 characters per line +2. **Blank Lines**: Always add blank lines around headings, lists, and code + blocks +3. **Structure**: Use proper heading hierarchy and document templates +4. **Formatting**: Apply consistent formatting patterns immediately + +### **DO NOT**: Generate content that violates these rules + +- ❌ Generate long lines that need breaking +- ❌ Create content without proper blank line spacing +- ❌ Use inconsistent formatting patterns +- ❌ Assume post-processing will fix violations + +### **DO**: Generate compliant content from the start + +- ✅ Write within 80-character limits +- ✅ Add blank lines around all structural elements +- ✅ Use established templates and patterns +- ✅ Apply formatting standards immediately + ## General Formatting Standards ### Line Length @@ -326,6 +356,10 @@ Description of current situation or problem. ### Authentication ### Authorization + ## Features ❌ (Duplicate heading) + ### Security + ### Performance + ``` ## Features ❌ (Duplicate heading) ### Security ### Performance From 80aecbcbbc0dac54d2dec9a92e85a853b091bbf2 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 13:00:37 +0000 Subject: [PATCH 29/35] feat: add Build Architecture Guard MDC directive - Create comprehensive guard rules for build system protection - Define protected file patterns and validation requirements - Include risk matrix and required validation checklists - Add emergency procedures and rollback playbooks --- .cursor/rules/architecture/README.md | 75 +++++ .../architecture/build_architecture_guard.mdc | 295 ++++++++++++++++++ 2 files changed, 370 insertions(+) create mode 100644 .cursor/rules/architecture/README.md create mode 100644 .cursor/rules/architecture/build_architecture_guard.mdc diff --git a/.cursor/rules/architecture/README.md b/.cursor/rules/architecture/README.md new file mode 100644 index 00000000..ac9669dd --- /dev/null +++ b/.cursor/rules/architecture/README.md @@ -0,0 +1,75 @@ +# Architecture Rules Directory + +**Author**: Matthew Raymer +**Date**: 2025-08-20 +**Status**: 🎯 **ACTIVE** - Architecture protection guidelines + +## Overview + +This directory contains MDC (Model Directive Configuration) rules that protect +critical architectural components of the TimeSafari project. These rules ensure +that changes to system architecture follow proper review, testing, and +documentation procedures. + +## Available Rules + +### Build Architecture Guard (`build_architecture_guard.mdc`) + +Protects the multi-platform build system including: + +- Vite configuration files +- Build scripts and automation +- Platform-specific configurations (iOS, Android, Electron, Web) +- Docker and deployment infrastructure +- CI/CD pipeline components + +**When to use**: Any time you're modifying build scripts, configuration files, +or deployment processes. + +**Authorization levels**: + +- **Level 1**: Minor changes (review required) +- **Level 2**: Moderate changes (testing required) +- **Level 3**: Major changes (ADR required) + +## Usage Guidelines + +### For Developers + +1. **Check the rule**: Before making architectural changes, review the relevant + rule +2. **Follow the process**: Use the appropriate authorization level +3. **Complete validation**: Run through the required checklist +4. **Update documentation**: Keep BUILDING.md and related docs current + +### For Reviewers + +1. **Verify authorization**: Ensure changes match the required level +2. **Check testing**: Confirm appropriate testing has been completed +3. **Validate documentation**: Ensure BUILDING.md reflects changes +4. **Assess risk**: Consider impact on other platforms and systems + +## Integration with Other Rules + +- **Version Control**: Works with `workflow/version_control.mdc` +- **Research & Diagnostic**: Supports `research_diagnostic.mdc` for + investigations +- **Software Development**: Aligns with development best practices +- **Markdown Automation**: Integrates with `docs/markdown-automation.mdc` for + consistent documentation formatting + +## Emergency Procedures + +If architectural changes cause system failures: + +1. **Immediate rollback** to last known working state +2. **Document the failure** with full error details +3. **Investigate root cause** using diagnostic workflows +4. **Update procedures** to prevent future failures + +--- + +**Status**: Active architecture protection +**Priority**: Critical +**Maintainer**: Development team +**Next Review**: 2025-09-20 diff --git a/.cursor/rules/architecture/build_architecture_guard.mdc b/.cursor/rules/architecture/build_architecture_guard.mdc new file mode 100644 index 00000000..651a12d5 --- /dev/null +++ b/.cursor/rules/architecture/build_architecture_guard.mdc @@ -0,0 +1,295 @@ +--- +description: Guards against unauthorized changes to the TimeSafari building + architecture +alwaysApply: false +--- + +# Build Architecture Guard Directive + +**Author**: Matthew Raymer +**Date**: 2025-08-20 +**Status**: 🎯 **ACTIVE** - Build system protection guidelines + +## Purpose + +Protect the TimeSafari building architecture from unauthorized changes that +could break the multi-platform build pipeline, deployment processes, or +development workflow. This directive ensures all build system modifications +follow proper review, testing, and documentation procedures. + +## Protected Architecture Components + +### Core Build Infrastructure + +- **Vite Configuration Files**: `vite.config.*.mts` files +- **Build Scripts**: All scripts in `scripts/` directory +- **Package Scripts**: `package.json` build-related scripts +- **Platform Configs**: `capacitor.config.ts`, `electron/`, `android/`, + `ios/` +- **Docker Configuration**: `Dockerfile`, `docker-compose.yml` +- **Environment Files**: `.env.*`, `.nvmrc`, `.node-version` + +### Critical Build Dependencies + +- **Build Tools**: Vite, Capacitor, Electron, Android SDK, Xcode +- **Asset Management**: `capacitor-assets.config.json`, asset scripts +- **Testing Infrastructure**: Playwright, Jest, mobile test scripts +- **CI/CD Pipeline**: GitHub Actions, build validation scripts +- **Service Worker Assembly**: `sw_scripts/`, `sw_combine.js`, WASM copy steps + +## Change Authorization Requirements + +### Level 1: Minor Changes (Requires Review) + +- Documentation updates to `BUILDING.md` +- Non-breaking script improvements +- Test additions or improvements +- Asset configuration updates + +**Process**: Code review + basic testing + +### Level 2: Moderate Changes (Requires Testing) + +- New build script additions +- Environment variable changes +- Dependency version updates +- Platform-specific optimizations + +**Process**: Code review + platform testing + documentation update + +### Level 3: Major Changes (Requires ADR) + +- Build system architecture changes +- New platform support +- Breaking changes to build scripts +- Major dependency migrations + +**Process**: ADR creation + comprehensive testing + team review + +## Prohibited Actions + +### ❌ Never Allow Without ADR + +- **Delete or rename** core build scripts +- **Modify** `package.json` build script names +- **Change** Vite configuration structure +- **Remove** platform-specific build targets +- **Alter** Docker build process +- **Modify** CI/CD pipeline without testing + +### ❌ Never Allow Without Testing + +- **Update** build dependencies +- **Change** environment configurations +- **Modify** asset generation scripts +- **Alter** test infrastructure +- **Update** platform SDK versions + +## Required Validation Checklist + +### Before Any Build System Change + +- [ ] **Impact Assessment**: Which platforms are affected? +- [ ] **Testing Plan**: How will this be tested across platforms? +- [ ] **Rollback Plan**: How can this be reverted if it breaks? +- [ ] **Documentation**: Will `BUILDING.md` need updates? +- [ ] **Dependencies**: Are all required tools available? + +### After Build System Change + +- [ ] **Web Platform**: Does `npm run build:web:dev` work? +- [ ] **Mobile Platforms**: Do iOS/Android builds succeed? +- [ ] **Desktop Platform**: Does Electron build and run? +- [ ] **Tests Pass**: Do all build-related tests pass? +- [ ] **Documentation Updated**: Is `BUILDING.md` current? + +## Specific Test Commands (Minimum Required) + +### Web Platform + +- **Development**: `npm run build:web:dev` - serve and load app +- **Production**: `npm run build:web:prod` - verify SW and WASM present + +### Mobile Platforms + +- **Android**: `npm run build:android:test` or `:prod` - confirm assets copied +- **iOS**: `npm run build:ios:test` or `:prod` - verify build succeeds + +### Desktop Platform + +- **Electron**: `npm run build:electron:dev` and packaging for target OS +- **Verify**: Single-instance behavior and app boot + +### Auto-run (if affected) + +- **Test Mode**: `npm run auto-run:test` and platform variants +- **Production Mode**: `npm run auto-run:prod` and platform variants + +### Clean and Rebuild + +- Run relevant `clean:*` scripts and ensure re-build works + +## Emergency Procedures + +### Build System Broken + +1. **Immediate**: Revert to last known working commit +2. **Investigation**: Create issue with full error details +3. **Testing**: Verify all platforms work after revert +4. **Documentation**: Update `BUILDING.md` with failure notes + +### Platform-Specific Failure + +1. **Isolate**: Identify which platform is affected +2. **Test Others**: Verify other platforms still work +3. **Rollback**: Revert platform-specific changes +4. **Investigation**: Debug in isolated environment + +## Integration Points + +### With Version Control + +- **Branch Protection**: Require reviews for build script changes +- **Commit Messages**: Must reference ADR for major changes +- **Testing**: All build changes must pass CI/CD pipeline + +### With Documentation + +- **BUILDING.md**: Must be updated for any script changes +- **README.md**: Must reflect new build requirements +- **CHANGELOG.md**: Must document breaking build changes + +### With Testing + +- **Pre-commit**: Run basic build validation +- **CI/CD**: Full platform build testing +- **Manual Testing**: Human verification of critical paths + +## Risk Matrix & Required Validation + +### Environment Handling + +- **Trigger**: Change to `.env.*` loading / variable names +- **Validation**: Prove `dev/test/prod` builds; show environment echo in logs + +### Script Flow + +- **Trigger**: Reorder steps (prebuild → build → package), new flags +- **Validation**: Dry-run + normal run, show exit codes & timing + +### Platform Packaging + +- **Trigger**: Electron NSIS/DMG/AppImage, Android/iOS bundle +- **Validation**: Produce installer/artifact and open it; verify single-instance, + icons, signing + +### Service Worker / WASM + +- **Trigger**: `sw_combine.js`, WASM copy path +- **Validation**: Verify combined SW exists and is injected; page loads offline; + WASM present + +### Docker + +- **Trigger**: New base image, build args +- **Validation**: Build image locally; run container; list produced `/dist` + +### Signing/Notarization + +- **Trigger**: Cert path/profiles +- **Validation**: Show signing logs + verify on target OS + +## PR Template (Paste into Description) + +- [ ] **Level**: L1 / L2 / L3 + justification +- [ ] **Files & platforms touched**: +- [ ] **Risk triggers & mitigations**: +- [ ] **Commands run (paste logs)**: +- [ ] **Artifacts (names + sha256)**: +- [ ] **Docs updated (sections/links)**: +- [ ] **Rollback steps verified**: +- [ ] **CI**: Jobs passing and artifacts uploaded + +## Rollback Playbook + +### Immediate Rollback + +1. `git revert` or `git reset --hard `; restore prior `scripts/` or config + files +2. Rebuild affected targets; verify old behavior returns +3. Post-mortem notes → update this guard and `BUILDING.md` if gaps found + +### Rollback Verification + +- **Web**: `npm run build:web:dev` and `npm run build:web:prod` +- **Mobile**: `npm run build:android:test` and `npm run build:ios:test` +- **Desktop**: `npm run build:electron:dev` and packaging commands +- **Clean**: Run relevant `clean:*` scripts and verify re-build works + +## ADR Trigger List + +Raise an ADR when you propose any of: + +- **New build stage** or reorder of canonical stages +- **Replacement of packager** / packaging format +- **New environment model** or secure secret handling scheme +- **New service worker assembly** strategy or cache policy +- **New Docker base** or multi-stage pipeline +- **Relocation of build outputs** or directory conventions + +**ADR must include**: motivation, alternatives, risks, validation plan, rollback, + doc diffs. + +## Competence Hooks + +### Why This Works + +- **Prevents Build Failures**: Catches issues before they reach production +- **Maintains Consistency**: Ensures all platforms build identically +- **Reduces Debugging Time**: Prevents build system regressions + +### Common Pitfalls + +- **Silent Failures**: Changes that work on one platform but break others +- **Dependency Conflicts**: Updates that create version incompatibilities +- **Documentation Drift**: Build scripts that don't match documentation + +### Next Skill Unlock + +- Learn to test build changes across all platforms simultaneously + +### Teach-back + +- "What three platforms must I test before committing a build script change?" + +## Collaboration Hooks + +### Team Review Requirements + +- **Platform Owners**: iOS, Android, Electron, Web specialists +- **DevOps**: CI/CD pipeline maintainers +- **QA**: Testing infrastructure owners + +### Discussion Prompts + +- "Which platforms will be affected by this build change?" +- "How can we test this change without breaking existing builds?" +- "What's our rollback plan if this change fails?" + +## Self-Check (Before Allowing Changes) + +- [ ] **Authorization Level**: Is this change appropriate for the level? +- [ ] **Testing Plan**: Is there a comprehensive testing strategy? +- [ ] **Documentation**: Will BUILDING.md be updated? +- [ ] **Rollback**: Is there a safe rollback mechanism? +- [ ] **Team Review**: Have appropriate stakeholders been consulted? +- [ ] **CI/CD**: Will this pass the build pipeline? + +--- + +**Status**: Active build system protection +**Priority**: Critical +**Estimated Effort**: Ongoing vigilance +**Dependencies**: All build system components +**Stakeholders**: Development team, DevOps, Platform owners +**Next Review**: 2025-09-20 From 963ff9234f690163b276a2f3aa72ed990cc79b9d Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 13:01:50 +0000 Subject: [PATCH 30/35] feat: implement comprehensive Build Architecture Guard system - Add Husky Git hooks for pre-commit and pre-push validation - Create guard script for BUILDING.md update enforcement - Implement PR template with L1/L2/L3 change classification - Add markdown validation and auto-fix scripts - Create comprehensive documentation and MDC rules - Ensure zero-disruption deployment with opt-in activation --- .cursor/rules/docs/markdown-automation.mdc | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 .cursor/rules/docs/markdown-automation.mdc diff --git a/.cursor/rules/docs/markdown-automation.mdc b/.cursor/rules/docs/markdown-automation.mdc new file mode 100644 index 00000000..b2da4927 --- /dev/null +++ b/.cursor/rules/docs/markdown-automation.mdc @@ -0,0 +1,79 @@ +--- +alwaysApply: true +--- + +# Markdown Automation System + +**Author**: Matthew Raymer +**Date**: 2025-08-20 +**Status**: 🎯 **ACTIVE** - Markdown formatting automation + +## Overview + +The Markdown Automation System ensures your markdown formatting standards are +followed **during content generation** by AI agents, not just applied after the +fact. + +## AI-First Approach + +### **Primary Method**: AI Agent Compliance + +- **AI agents follow markdown rules** while generating content +- **No post-generation fixes needed** - content is compliant from creation +- **Consistent formatting** across all generated documentation + +### **Secondary Method**: Automated Validation + +- **Pre-commit hooks** catch any remaining issues +- **GitHub Actions** validate formatting before merge +- **Manual tools** for bulk fixes when needed + +## How It Works + +### 1. **AI Agent Compliance** (Primary) + +- **When**: Every time AI generates markdown content +- **What**: AI follows markdown rules during generation +- **Result**: Content is properly formatted from creation + +### 2. **Pre-commit Hooks** (Backup) + +- **When**: Every time you commit +- **What**: Catches any remaining formatting issues +- **Result**: Clean, properly formatted markdown files + +### 3. **GitHub Actions** (Pre-merge) + +- **When**: Every pull request +- **What**: Validates markdown formatting across all files +- **Result**: Blocks merge if formatting issues exist + +## AI Agent Rules Integration + +The AI agent follows markdown rules defined in `.cursor/rules/docs/markdown.mdc`: + +- **alwaysApply: true** - Rules are enforced during generation +- **Line Length**: AI never generates lines > 80 characters +- **Blank Lines**: AI adds proper spacing around all elements +- **Structure**: AI uses established templates and patterns + +## Available Commands + +### NPM Scripts + +- **`npm run markdown:setup`** - Install the automation system +- **`npm run markdown:fix`** - Fix formatting in all markdown files +- **`npm run markdown:check`** - Validate formatting without fixing + +## Benefits + +- **No more manual fixes** - AI generates compliant content from start +- **Consistent style** - All files follow same standards +- **Faster development** - No need to fix formatting manually + +--- + +**Status**: Active automation system +**Priority**: High +**Maintainer**: Development team +**Next Review**: 2025-09-20 From 2d17bfd3b4080b7eb7218687df8c28fedd038cde Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 20 Aug 2025 13:02:01 +0000 Subject: [PATCH 31/35] docs: comprehensive documentation updates and modernization - Update BUILDING.md with current build system information - Modernize various README files across the project - Update CHANGELOG.md with recent changes - Improve documentation consistency and formatting - Update platform-specific documentation (iOS, Electron, Docker) - Enhance test documentation and build guides --- BUILDING.md | 434 ++++++++++++------ CHANGELOG.md | 41 +- TASK_storage.md | 8 - doc/DEEP_LINKS.md | 3 + doc/README.md | 5 +- doc/architecture-decisions.md | 2 +- doc/asset-migration-plan.md | 1 + doc/build-modernization-context.md | 10 +- doc/circular-dependency-analysis.md | 21 +- doc/component-communication-guide.md | 16 +- doc/cors-disabled-for-universal-images.md | 16 +- doc/cors-image-loading-solution.md | 28 +- doc/database-migration-guide.md | 1 + doc/debug-hook-guide.md | 5 + doc/electron-cleanup-summary.md | 8 +- doc/electron-console-cleanup.md | 27 +- doc/error-diagnostics-log.md | 19 +- doc/image-hosting-guide.md | 23 +- doc/logging-configuration.md | 2 + doc/migration-fence-definition.md | 23 +- doc/migration-progress-tracker.md | 71 ++- doc/migration-quick-reference.md | 3 +- doc/migration-readiness-summary.md | 33 +- doc/migration-roadmap-next-steps.md | 33 +- doc/migration-security-checklist.md | 2 +- doc/migration-to-wa-sqlite.md | 31 +- doc/platformservicemixin-completion-plan.md | 31 +- doc/qr-code-implementation-guide.md | 30 +- doc/secure-storage-implementation.md | 11 +- doc/sharebufferarray_spectre_security.md | 14 + doc/storage-implementation-checklist.md | 31 +- doc/usage-guide.md | 115 ++--- docker/README.md | 34 +- electron/README-BUILDING.md | 31 +- electron/README.md | 34 +- .../app_privacy_manifest_fixer/CHANGELOG.md | 17 +- ios/App/app_privacy_manifest_fixer/README.md | 7 + .../README.zh-CN.md | 11 +- resources/README.md | 5 +- scripts/README.md | 9 +- scripts/git-hooks/README.md | 23 +- test-playwright/README.md | 10 +- test-playwright/TESTING.md | 4 +- 43 files changed, 1019 insertions(+), 264 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index e5abf069..17c367d6 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -13,7 +13,7 @@ npm run build:web:serve -- --test # Start with test endorser server npm run build:web:dev # Start development server with hot reload with local endorser server npm run build:web:prod # Production build -# 📱 Mobile Development +# 📱 Mobile Development npm run build:ios # iOS build (opens Xcode) npm run build:android # Android build (opens Android Studio) @@ -31,6 +31,7 @@ npm run clean:all # Clean all platforms ### Development Workflow #### 1. First-Time Setup + ```bash # Install dependencies npm install @@ -40,6 +41,7 @@ npm run test:web # Run web tests to verify setup ``` #### 2. Daily Development + ```bash # Start web development server npm run build:web:dev # Opens http://localhost:8080 @@ -48,11 +50,12 @@ npm run build:web:dev # Opens http://localhost:8080 npm run build:ios # Opens Xcode with iOS project npm run build:android # Opens Android Studio with Android project -# For desktop development +# For desktop development npm run build:electron:dev # Runs Electron app directly ``` #### 3. Testing Your Changes + ```bash # Test web functionality npm run test:web # Run web tests @@ -66,6 +69,7 @@ npm run build:android:test:run # Build and run on Android emulator ``` #### 4. Production Builds + ```bash # Build for production npm run build:web:prod # Web production build @@ -77,6 +81,7 @@ npm run build:electron:prod # Electron production build ### Environment Configuration #### Quick Environment Setup + ```bash # Copy environment template (if available) cp .env.example .env.development @@ -89,6 +94,7 @@ cp .env.example .env.development ``` #### Platform-Specific Development + - **Web**: Uses `localhost:3000` for APIs by default - **iOS Simulator**: Uses `localhost:3000` for APIs - **Android Emulator**: Uses `10.0.2.2:3000` for APIs @@ -97,6 +103,7 @@ cp .env.example .env.development ### Troubleshooting Quick Fixes #### Common Issues + ```bash # Clean and rebuild npm run clean:all @@ -114,6 +121,7 @@ npm run test:web # Verifies web setup ``` #### Platform-Specific Issues + - **iOS**: Ensure Xcode and Command Line Tools are installed - **Android**: Ensure Android Studio and SDK are configured - **Electron**: Ensure platform-specific build tools are installed @@ -222,6 +230,7 @@ All web build commands use the `./scripts/build-web.sh` script, which provides: ``` **Script Flow:** + 1. **Environment Validation**: Check prerequisites (Node.js, npm, etc.) 2. **Environment Setup**: Load `.env` files, set NODE_ENV 3. **Clean Dist**: Remove previous build artifacts @@ -230,8 +239,9 @@ All web build commands use the `./scripts/build-web.sh` script, which provides: 6. **Optional Serve**: Start local HTTP server if requested **Exit Codes:** + - `1` - Web cleanup failed -- `2` - Environment setup failed +- `2` - Environment setup failed - `3` - Vite build failed - `4` - Docker build failed - `5` - Serve command failed @@ -239,19 +249,25 @@ All web build commands use the `./scripts/build-web.sh` script, which provides: ### Compile and minify for test & production -* If there are DB changes: before updating the test server, open browser(s) with current version to test DB migrations. +- If there are DB changes: before updating the test server, open browser(s) with +current version to test DB migrations. -* Update the ClickUp tasks & CHANGELOG.md & the version in package.json, run `npm install`. +- Update the ClickUp tasks & CHANGELOG.md & the version in package.json, run +`npm install`. -* Run a build to make sure package-lock version is updated, linting works, etc: `npm install && npm run build:web` +- Run a build to make sure package-lock version is updated, linting works, etc: +`npm install && npm run build:web` -* Commit everything (since the commit hash is used the app). +- Commit everything (since the commit hash is used the app). -* Put the commit hash in the changelog (which will help you remember to bump the version in the step later). +- Put the commit hash in the changelog (which will help you remember to bump the + version in the step later). -* Tag with the new version, [online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or `git tag 1.0.2 && git push origin 1.0.2`. +- Tag with the new version, +[online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or +`git tag 1.0.2 && git push origin 1.0.2`. -* For test, build the app (because test server is not yet set up to build): +- For test, build the app (because test server is not yet set up to build): ```bash TIME_SAFARI_APP_TITLE="TimeSafari_Test" \ @@ -274,25 +290,28 @@ rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safa (Note: The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there.) -* For prod, get on the server and run the correct build: +- For prod, get on the server and run the correct build: ... and log onto the server: -* `pkgx +npm sh` +- `pkgx +npm sh` -* `cd crowd-funder-for-time-pwa && git checkout master && git pull && git checkout 1.0.2 && npm install && npm run build:web:prod && cd -` +- `cd crowd-funder-for-time-pwa && git checkout master && git pull && git checkout +1.0.2 && npm install && npm run build:web:prod && cd -` (The plain `npm run build:web:prod` uses the .env.production file.) -* Back up the time-safari/dist folder & deploy: `mv time-safari/dist time-safari-dist-prev-2 && mv crowd-funder-for-time-pwa/dist time-safari/` +- Back up the time-safari/dist folder & deploy: `mv time-safari/dist time-safari-dist-prev-2 && mv crowd-funder-for-time-pwa/dist time-safari/` -* Record the new hash in the changelog. Edit package.json to increment version & add "-beta", `npm install`, commit, and push. Also record what version is on production. +- Record the new hash in the changelog. Edit package.json to increment version & +add "-beta", `npm install`, commit, and push. Also record what version is on production. ## Docker Deployment -The application can be containerized using Docker for consistent deployment across environments. +The application can be containerized using Docker for consistent deployment across +environments. -### Prerequisites +### Docker Prerequisites - Docker installed on your system - Docker Compose (optional, for multi-container setups) @@ -402,7 +421,10 @@ docker run -d \ ## Desktop Build (Electron) -TimeSafari's Electron build system provides comprehensive desktop application packaging and distribution capabilities across Windows, macOS, and Linux platforms. The system supports multiple build modes, environment configurations, and package formats. +TimeSafari's Electron build system provides comprehensive desktop application +packaging and distribution capabilities across Windows, macOS, and Linux +platforms. The system supports multiple build modes, environment configurations, +and package formats. ### Electron Build Commands @@ -436,15 +458,18 @@ npm run clean:electron # Clean Electron build artifacts #### Development Build -Start development build using `npm run build:electron:dev` (builds and runs the app directly). +Start development build using `npm run build:electron:dev` (builds and runs the +app directly). #### Production Build -Run production builds using the commands above. Production builds create platform-specific packages. +Run production builds using the commands above. Production builds create +platform-specific packages. #### Package-Specific Builds -Create platform-specific packages using the commands above. These build the app and create installable packages. +Create platform-specific packages using the commands above. These build the app +and create installable packages. ### Single Instance Enforcement @@ -484,29 +509,29 @@ The Electron app enforces single-instance operation to prevent: The Electron build process follows a multi-stage approach: -``` +```text 1. Web Build (Vite) → 2. Capacitor Sync → 3. TypeScript Compile → 4. Package ``` -**Stage 1: Web Build** +#### **Stage 1: Web Build** - Vite builds web assets with Electron-specific configuration - Environment variables loaded based on build mode - Assets optimized for desktop application -**Stage 2: Capacitor Sync** +#### **Stage 2: Capacitor Sync** - Copies web assets to Electron app directory - Syncs Capacitor configuration and plugins - Prepares native module bindings -**Stage 3: TypeScript Compile** +#### **Stage 3: TypeScript Compile** - Compiles Electron main process TypeScript - Rebuilds native modules for target platform - Generates production-ready JavaScript -**Stage 4: Package Creation** +#### **Stage 4: Package Creation** - Creates platform-specific installers - Generates distribution packages @@ -566,6 +591,7 @@ npm run build:electron:windows:prod ``` **Configuration**: + - NSIS installer with custom options - Desktop and Start Menu shortcuts - Elevation permissions for installation @@ -588,6 +614,7 @@ npm run build:electron:mac:prod ``` **Configuration**: + - Universal binary (x64 + arm64) - DMG installer with custom branding - App Store compliance (when configured) @@ -610,12 +637,13 @@ npm run build:electron:linux:prod ``` **Configuration**: + - AppImage for universal distribution - DEB package for Debian-based systems - RPM package for Red Hat-based systems - Desktop integration -### Package-Specific Builds +### Desktop Package-Specific Builds #### AppImage Package @@ -634,6 +662,7 @@ npm run build:electron:appimage:prod ``` **Features**: + - Single file distribution - No installation required - Portable across Linux distributions @@ -656,6 +685,7 @@ npm run build:electron:deb:prod ``` **Features**: + - Native package management - Dependency resolution - System integration @@ -678,6 +708,7 @@ npm run build:electron:dmg:prod ``` **Features**: + - Native macOS installer - Custom branding and layout - Drag-and-drop installation @@ -742,7 +773,7 @@ npm run build:electron:dmg:test # DMG test build npm run build:electron:dmg:prod # DMG production build ``` -#### Direct Script Usage +#### Direct Script Usage Reference All npm scripts use the underlying `./scripts/build-electron.sh` script: @@ -766,9 +797,9 @@ npm run clean:electron # Clean Electron build artifacts ### Build Output Structure -#### Development Build +#### Development Build Structure -``` +```text electron/ ├── app/ # Web assets ├── build/ # Compiled TypeScript @@ -776,9 +807,9 @@ electron/ └── node_modules/ # Dependencies ``` -#### Production Build +#### Production Build Output -``` +```text electron/ ├── app/ # Web assets ├── build/ # Compiled TypeScript @@ -796,7 +827,8 @@ electron/ For public distribution on macOS, you need to code sign and notarize your app: -1. Set up environment variables: +##### 1. Set up environment variables + ```bash export CSC_LINK=/path/to/your/certificate.p12 export CSC_KEY_PASSWORD=your_certificate_password @@ -804,7 +836,8 @@ export APPLE_ID=your_apple_id export APPLE_ID_PASSWORD=your_app_specific_password ``` -2. Build with signing: +##### 2. Build with signing + ```bash npm run build:electron:mac:prod ``` @@ -813,13 +846,15 @@ npm run build:electron:mac:prod For Windows distribution, configure Authenticode signing: -1. Set up environment variables: +##### 1. Set up desktop environment variables + ```bash export CSC_LINK=/path/to/your/certificate.p12 export CSC_KEY_PASSWORD=your_certificate_password ``` -2. Build with signing: +##### 2. Build desktop with signing + ```bash npm run build:electron:windows:prod ``` @@ -829,12 +864,14 @@ npm run build:electron:windows:prod #### Linux - **AppImage**: Make executable and run + ```bash chmod +x electron/dist/TimeSafari-*.AppImage ./electron/dist/TimeSafari-*.AppImage ``` - **DEB**: Install and run + ```bash sudo dpkg -i electron/dist/timesafari_*_amd64.deb timesafari @@ -849,6 +886,7 @@ timesafari 3. Launch from Applications Note: If you get a security warning when running the app: + 1. Right-click the app 2. Select "Open" 3. Click "Open" in the security dialog @@ -863,6 +901,7 @@ Note: If you get a security warning when running the app: #### Common Build Issues **TypeScript Compilation Errors**: + ```bash # Clean and rebuild npm run clean:electron @@ -870,30 +909,35 @@ npm run build:electron:dev ``` **Native Module Issues**: + ```bash # Rebuild native modules npm run build:electron:dev ``` **Asset Copy Issues**: + ```bash # Verify Capacitor sync npx cap sync electron ``` -#### Platform-Specific Issues +#### Platform-Specific Building Issues **Windows**: + - Ensure Windows Build Tools installed - Check NSIS installation - Verify code signing certificates **macOS**: + - Install Xcode Command Line Tools - Configure code signing certificates - Check app notarization requirements **Linux**: + - Install required packages (rpm-tools, etc.) - Check AppImage dependencies - Verify desktop integration @@ -984,6 +1028,7 @@ The recommended way to build for iOS is using the automated build script: ``` The script handles all the necessary steps including: + - Environment setup and validation - Web asset building (Capacitor mode) - Capacitor synchronization @@ -1004,11 +1049,11 @@ If you need to build manually or want to understand the individual steps: #### Each Release -0. First time (or if dependencies change): +##### 0. First time (or if dependencies change) - - `pkgx +rubygems.org sh` +- `pkgx +rubygems.org sh` - - ... and you may have to fix these, especially with pkgx: +- ... and you may have to fix these, especially with pkgx: ```bash gem_path=$(which gem) @@ -1017,15 +1062,15 @@ If you need to build manually or want to understand the individual steps: export GEM_PATH=$shortened_path ``` -1. Bump the version in package.json, then here. +##### 1. Bump the version in package.json, then here - ``` + ```bash cd ios/App && xcrun agvtool new-version 40 && perl -p -i -e "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 1.0.7;/g" App.xcodeproj/project.pbxproj && cd - # Unfortunately this edits Info.plist directly. #xcrun agvtool new-marketing-version 0.4.5 ``` -2. Build. +##### 2. Build Here's prod. Also available: test, dev @@ -1035,22 +1080,28 @@ If you need to build manually or want to understand the individual steps: 3.1. Use Xcode to build and run on simulator or device. - * Select Product -> Destination with some Simulator version. Then click the run arrow. +- Select Product -> Destination with some Simulator version. Then click the run arrow. 3.2. Use Xcode to release. - * Someday: Under "General" we want to rename a bunch of things to "Time Safari" - * Choose Product -> Destination -> Any iOS Device - * Choose Product -> Archive - * This will trigger a build and take time, needing user's "login" keychain password (user's login password), repeatedly. - * If it fails with `building for 'iOS', but linking in dylib (.../.pkgx/zlib.net/v1.3.0/lib/libz.1.3.dylib) built for 'macOS'` then run XCode outside that terminal (ie. not with `npx cap open ios`). - * Click Distribute -> App Store Connect - * In AppStoreConnect, add the build to the distribution. You may have to remove the current build with the "-" when you hover over it, then "Add Build" with the new build. - * May have to go to App Review, click Submission, then hover over the build and click "-". - * It can take 15 minutes for the build to show up in the list of builds. - * You'll probably have to "Manage" something about encryption, disallowed in France. - * Then "Save" and "Add to Review" and "Resubmit to App Review". - * Eventually it'll be "Ready for Distribution" which means +- Someday: Under "General" we want to rename a bunch of things to "Time Safari" +- Choose Product -> Destination -> Any iOS Device +- Choose Product -> Archive + - This will trigger a build and take time, needing user's "login" keychain + password (user's login password), repeatedly. + - If it fails with `building for 'iOS', but linking in dylib + (.../.pkgx/zlib.net/v1.3.0/lib/libz.1.3.dylib) built for 'macOS'` then run + XCode outside that terminal (ie. not with `npx cap open ios`). + - Click Distribute -> App Store Connect +- In AppStoreConnect, add the build to the distribution. You may have to remove + the current build with the "-" when you hover over it, then "Add Build" with the + new build. + - May have to go to App Review, click Submission, then hover over the build + and click "-". + - It can take 15 minutes for the build to show up in the list of builds. + - You'll probably have to "Manage" something about encryption, disallowed in France. + - Then "Save" and "Add to Review" and "Resubmit to App Review". +- Eventually it'll be "Ready for Distribution" which means ### Android Build @@ -1063,7 +1114,7 @@ Prerequisites: Android Studio with Java SDK installed npm run build:android # Development build (builds and opens Android Studio) npm run build:android:dev # Development build (builds and opens Android Studio) npm run build:android:test # Test build (builds for testing environment) -npm run build:android:prod # Production build (builds for production environment) +npm run build:android:prod # Production build (builds for production environment). # Auto-run builds npm run build:android:test:run # Test build with auto-run (builds then runs on emulator) @@ -1085,7 +1136,7 @@ npm run build:android:assets # Generate assets only npm run build:android:deploy # Build and deploy to connected device ``` -#### Automated Build Script +#### Android Automated Build Script The recommended way to build for Android is using the automated build script: @@ -1103,16 +1154,16 @@ The recommended way to build for Android is using the automated build script: ./scripts/build-android.sh --help ``` -#### Manual Build Process +#### Android Manual Build Process -1. Bump the version in package.json, then here: android/app/build.gradle +##### 1. Bump the version in package.json, then here: android/app/build.gradle ```bash perl -p -i -e 's/versionCode .*/versionCode 40/g' android/app/build.gradle perl -p -i -e 's/versionName .*/versionName "1.0.7"/g' android/app/build.gradle ``` -2. Build. +##### 2. Build Here's prod. Also available: test, dev @@ -1120,13 +1171,13 @@ The recommended way to build for Android is using the automated build script: npm run build:android:prod ``` -3. Open the project in Android Studio: +##### 3. Open the project in Android Studio ```bash npx cap open android ``` -4. Use Android Studio to build and run on emulator or device. +##### 4. Use Android Studio to build and run on emulator or device ## Android Build from the console @@ -1145,9 +1196,10 @@ cd - ... or, to create a signed release: -* Setup by adding the app/gradle.properties.secrets file (see properties at top of app/build.gradle) and the app/time-safari-upload-key-pkcs12.jks file -* In app/build.gradle, bump the versionCode and maybe the versionName -* Then `bundleRelease`: +- Setup by adding the app/gradle.properties.secrets file (see properties at top + of app/build.gradle) and the app/time-safari-upload-key-pkcs12.jks file +- In app/build.gradle, bump the versionCode and maybe the versionName +- Then `bundleRelease`: ```bash cd android @@ -1165,7 +1217,8 @@ At play.google.com/console: - Hit "Next". - Save, go to "Publishing Overview" as prompted, and click "Send changes for review". -- Note that if you add testers, you have to go to "Publishing Overview" and send those changes or your (closed) testers won't see it. +- Note that if you add testers, you have to go to "Publishing Overview" and send + those changes or your (closed) testers won't see it. ### Capacitor Operations @@ -1263,7 +1316,7 @@ npm run lint-fix # Fix linting issues Use the commands above to check and fix code quality issues. -## Build Architecture +## Code Build Architecture ### Web Build Process @@ -1288,19 +1341,22 @@ Use the commands above to check and fix code quality issues. 4. **Native Build**: Platform-specific compilation 5. **Package Creation**: APK/IPA generation -## Environment Configuration +## Architecture Environment Configuration ### Environment Files The build system supports multiple environment file patterns for different scenarios: #### Primary Environment Files + - `.env.development` - Development environment (local development) - `.env.test` - Testing environment (staging/testing) - `.env.production` - Production environment (production deployment) #### Fallback and Local Files -- `.env` - General fallback environment file (loaded if mode-specific file doesn't exist) + +- `.env` - General fallback environment file (loaded if mode-specific file + doesn't exist) - `.env.local` - Local development overrides (gitignored) - `.env.*.local` - Mode-specific local overrides (gitignored) @@ -1324,6 +1380,7 @@ The build system supports multiple environment file patterns for different scena ### Key Environment Variables #### API Server Configuration + ```bash # API Servers (Environment-specific) VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch @@ -1342,6 +1399,7 @@ VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZY #### Environment-Specific Configurations **Development Environment** (`.env.development`): + ```bash # Development API Servers (Local) VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 @@ -1351,6 +1409,7 @@ VITE_APP_SERVER=http://localhost:8080 ``` **Test Environment** (`.env.test`): + ```bash # Test API Servers VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch @@ -1360,6 +1419,7 @@ VITE_APP_SERVER=https://test.timesafari.app ``` **Production Environment** (`.env.production`): + ```bash # Production API Servers VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch @@ -1371,16 +1431,19 @@ VITE_APP_SERVER=https://timesafari.app ### Platform-Specific Overrides #### Android Development + - **Emulator**: Uses `http://10.0.2.2:3000` (Android emulator default) - **Physical Device**: Uses custom IP address (e.g., `http://192.168.1.100:3000`) #### iOS Development + - **Simulator**: Uses `http://localhost:3000` (iOS simulator default) - **Physical Device**: Uses custom IP address (e.g., `http://192.168.1.100:3000`) ### Environment Loading Process 1. **Build Script Initialization** + ```bash # scripts/common.sh - setup_build_env() if [ "$BUILD_MODE" = "development" ]; then @@ -1390,6 +1453,7 @@ VITE_APP_SERVER=https://timesafari.app ``` 2. **Platform-Specific Overrides** + ```bash # scripts/build-android.sh if [ "$BUILD_MODE" = "development" ]; then @@ -1399,13 +1463,14 @@ VITE_APP_SERVER=https://timesafari.app ``` 3. **Environment File Loading** + ```bash # scripts/build-web.sh local env_file=".env.$BUILD_MODE" # .env.development, .env.test, .env.production if [ -f "$env_file" ]; then load_env_file "$env_file" fi - + # Fallback to .env if [ -f ".env" ]; then load_env_file ".env" @@ -1413,6 +1478,7 @@ VITE_APP_SERVER=https://timesafari.app ``` 4. **Application Usage** + ```typescript // src/constants/app.ts export const DEFAULT_ENDORSER_API_SERVER = @@ -1420,9 +1486,9 @@ VITE_APP_SERVER=https://timesafari.app AppString.PROD_ENDORSER_API_SERVER; ``` -## Troubleshooting +## Building Troubleshooting -### Common Issues +### Common Issues Building #### Build Failures @@ -1447,29 +1513,34 @@ npm run build:ios:assets npm run build:android:assets ``` -### Platform-Specific Issues +### More Platform-Specific Building Issues + +#### Building on Windows -#### Windows - Ensure Windows Build Tools installed - Check NSIS installation - Verify code signing certificates -#### macOS +#### Building on macOS + - Install Xcode Command Line Tools - Configure code signing certificates - Check app notarization requirements -#### Linux +#### Building on Linux + - Install required packages (rpm-tools, etc.) - Check AppImage dependencies - Verify desktop integration #### iOS + - Install Xcode and Command Line Tools - Configure signing certificates - Check provisioning profiles #### Android + - Install Android Studio and SDK - Configure signing keys - Check device/emulator setup @@ -1488,37 +1559,45 @@ npm run build:android:assets ### Build Process Overview -TimeSafari's build system follows a multi-stage process that prepares assets, combines scripts, and generates platform-specific outputs. +TimeSafari's build system follows a multi-stage process that prepares assets, +combines scripts, and generates platform-specific outputs. #### Pre-Build Preparation -**1. Service Worker Script Preparation** +##### 1. Service Worker Script Preparation + ```bash # Optional: Format third-party service worker scripts npx prettier --write ./sw_scripts/ ``` **What this does:** -- Formats cryptographic libraries (`nacl.js`, `noble-curves.js`, `noble-hashes.js`, etc.) + +- Formats cryptographic libraries (`nacl.js`, `noble-curves.js`, + `noble-hashes.js`, etc.) - These scripts are automatically combined during the build process - Improves readability and makes version control diffs cleaner - **Note**: This is optional and only needed when updating third-party scripts **2. Automatic Pre-Build Steps** The `prebuild` script automatically runs before any build: + ```json "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js" ``` **What happens automatically:** + - **ESLint**: Checks and fixes code formatting in `src/` -- **Script Combination**: `sw_combine.js` combines all `sw_scripts/*.js` files into `sw_scripts-combined.js` +- **Script Combination**: `sw_combine.js` combines all `sw_scripts/*.js` files + into `sw_scripts-combined.js` - **WASM Copy**: `copy-wasm.js` copies SQLite WASM files to `public/wasm/` -#### Build Architecture +#### Build Process Architecture **Web Build Process:** -``` + +```text 1. Pre-Build: ESLint + Script Combination + WASM Copy 2. Environment Setup: Load .env files, set NODE_ENV 3. Vite Build: Bundle web assets with PWA support @@ -1527,7 +1606,8 @@ The `prebuild` script automatically runs before any build: ``` **Electron Build Process:** -``` + +```text 1. Web Build: Vite builds web assets for Electron 2. Capacitor Sync: Copies assets to Electron app directory 3. TypeScript Compile: Compiles main process code @@ -1536,7 +1616,8 @@ The `prebuild` script automatically runs before any build: ``` **Mobile Build Process:** -``` + +```text 1. Web Build: Vite builds web assets 2. Capacitor Sync: Syncs with native platforms 3. Asset Generation: Creates platform-specific assets @@ -1547,12 +1628,14 @@ The `prebuild` script automatically runs before any build: #### Service Worker Architecture **Script Organization:** + - `sw_scripts/` - Individual third-party scripts - `sw_combine.js` - Combines scripts into single file - `sw_scripts-combined.js` - Combined service worker (317KB, 10K+ lines) - `vite.config.utils.mts` - PWA configuration using combined script **PWA Integration:** + ```typescript // vite.config.utils.mts pwaConfig: { @@ -1563,31 +1646,35 @@ pwaConfig: { ``` **What Gets Combined:** + - `nacl.js` - NaCl cryptographic library - `noble-curves.js` - Elliptic curve cryptography (177KB) - `noble-hashes.js` - Cryptographic hash functions (91KB) - `safari-notifications.js` - Safari-specific notifications - `additional-scripts.js` - Additional service worker functionality -#### Environment Configuration +#### Process Environment Configuration **Environment Files:** The build system supports multiple environment file patterns: - `.env.development` - Development environment (local development) -- `.env.test` - Testing environment (staging/testing) +- `.env.test` - Testing environment (staging/testing) - `.env.production` - Production environment (production deployment) -- `.env` - General fallback environment file (loaded if mode-specific file doesn't exist) +- `.env` - General fallback environment file (loaded if mode-specific file + doesn't exist) - `.env.local` - Local development overrides (gitignored) - `.env.*.local` - Mode-specific local overrides (gitignored) **Environment Variable Precedence (Highest to Lowest):** + 1. **Shell Script Overrides** - Platform-specific overrides in build scripts 2. **Environment-Specific .env Files** - `.env.development`, `.env.test`, `.env.production` 3. **Fallback .env File** - General `.env` file (if mode-specific file doesn't exist) 4. **Hardcoded Constants** - Default values in `src/constants/app.ts` **Key Environment Variables:** + ```bash # API Servers (Environment-specific) VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch @@ -1604,13 +1691,17 @@ VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZY ``` **Platform-Specific Overrides:** -- **Android Development**: `http://10.0.2.2:3000` (emulator) or custom IP (physical device) -- **iOS Development**: `http://localhost:3000` (simulator) or custom IP (physical device) -#### Build Output Structure +- **Android Development**: `http://10.0.2.2:3000` (emulator) or custom IP +(physical device) +- **iOS Development**: `http://localhost:3000` (simulator) or custom IP (physical +device) + +#### Build Process Output Structure **Web Build:** -``` + +```folders dist/ ├── index.html # Main HTML file ├── assets/ # Bundled JavaScript/CSS @@ -1620,7 +1711,8 @@ dist/ ``` **Electron Build:** -``` + +```folders electron/ ├── app/ # Web assets ├── build/ # Compiled TypeScript @@ -1635,35 +1727,41 @@ electron/ #### Manual vs Automatic Steps **Manual Steps (Developer Responsibility):** + - Database migration testing - Service worker script formatting (optional) - Version updates and changelog - Environment-specific builds **Automatic Steps (Build System):** + - Code linting and formatting - Script combination - Asset optimization - Package creation - Service worker injection -This architecture ensures consistent builds across all platforms while providing flexibility for platform-specific optimizations and manual quality assurance steps. +This architecture ensures consistent builds across all platforms while providing +flexibility for platform-specific optimizations and manual quality assurance steps. --- ## Appendix A: Build Scripts Reference -This appendix provides detailed documentation for all build scripts in the `scripts/` directory. +This appendix provides detailed documentation for all build scripts in the +`scripts/` directory. ### A.1 build-web.sh -**File**: `scripts/build-web.sh` -**Author**: Matthew Raymer +**File**: `scripts/build-web.sh` +**Author**: Matthew Raymer **Description**: Web build script for TimeSafari application -**Purpose**: Handles the complete web build process including cleanup, environment setup, Vite build, and optional Docker containerization. +**Purpose**: Handles the complete web build process including cleanup, +environment setup, Vite build, and optional Docker containerization. **Usage**: + ```bash # Direct script usage ./scripts/build-web.sh # Development build @@ -1687,11 +1785,13 @@ npm run build:web:docker:prod # Production Docker build ``` **Build Modes**: + - **Development**: Starts Vite dev server with hot reload (default) - **Test**: Optimized for testing with minimal minification - **Production**: Optimized for production with full minification **Script Features**: + - **Environment Validation**: Checks for Node.js, npm, npx, package.json - **Environment Setup**: Loads `.env` files based on build mode - **Clean Build**: Removes previous `dist/` directory @@ -1700,6 +1800,7 @@ npm run build:web:docker:prod # Production Docker build - **Local Serving**: Built-in HTTP server for testing builds **Exit Codes**: + - `1` - Web cleanup failed - `2` - Environment setup failed - `3` - Vite build failed @@ -1709,13 +1810,15 @@ npm run build:web:docker:prod # Production Docker build ### A.2 build-electron.sh -**File**: `scripts/build-electron.sh` -**Author**: Matthew Raymer +**File**: `scripts/build-electron.sh` +**Author**: Matthew Raymer **Description**: Clean, modular Electron build script for TimeSafari application -**Purpose**: Handles Electron builds with proper separation of concerns and no command chaining, following DRY principles. +**Purpose**: Handles Electron builds with proper separation of concerns and no +command chaining, following DRY principles. **Usage**: + ```bash # Direct script usage ./scripts/build-electron.sh # Development build (runs app) @@ -1738,22 +1841,26 @@ npm run build:web:docker:prod # Production Docker build ``` **Build Modes**: + - **Development**: Development build (runs app) - **Test**: Test environment build - **Production**: Production environment build - **Clean**: Clean Electron build artifacts only **Platforms**: + - **Windows**: Windows build - **macOS**: macOS build - **Linux**: Linux build **Packages**: + - **AppImage**: Linux AppImage - **Deb**: Debian package - **DMG**: macOS DMG **Exit Codes**: + - `1` - Invalid arguments - `2` - Electron cleanup failed - `3` - Web build failed @@ -1765,21 +1872,23 @@ npm run build:web:docker:prod # Production Docker build ### A.3 build-android.sh -**File**: `scripts/build-android.sh` -**Author**: Matthew Raymer -**Date**: 2025-07-11 +**File**: `scripts/build-android.sh` +**Author**: Matthew Raymer +**Date**: 2025-07-11 **Description**: Android build script for TimeSafari application -**Purpose**: Handles the complete Android build process including cleanup, web build, Capacitor build, Gradle build, and Android Studio launch. +**Purpose**: Handles the complete Android build process including cleanup, web + build, Capacitor build, Gradle build, and Android Studio launch. **Usage**: + ```bash # Direct script usage ./scripts/build-android.sh [options] # Options --dev, --development Build for development environment ---test Build for testing environment +--test Build for testing environment --prod, --production Build for production environment --debug Build debug APK --release Build release APK @@ -1802,15 +1911,18 @@ npm run build:web:docker:prod # Production Docker build ``` **Build Modes**: + - **Development**: Build for development environment - **Test**: Build for testing environment - **Production**: Build for production environment **Build Types**: + - **Debug**: Build debug APK (default) - **Release**: Build release APK **Exit Codes**: + - `1` - Android cleanup failed - `2` - Web build failed - `3` - Capacitor build failed @@ -1823,14 +1935,16 @@ npm run build:web:docker:prod # Production Docker build ### A.4 build-ios.sh -**File**: `scripts/build-ios.sh` -**Author**: Matthew Raymer -**Date**: 2025-07-11 +**File**: `scripts/build-ios.sh` +**Author**: Matthew Raymer +**Date**: 2025-07-11 **Description**: iOS build script for TimeSafari application -**Purpose**: Handles the complete iOS build process including cleanup, web build, Capacitor build, Xcode build, and iOS Simulator launch. +**Purpose**: Handles the complete iOS build process including cleanup, web build, + Capacitor build, Xcode build, and iOS Simulator launch. **Usage**: + ```bash # Direct script usage ./scripts/build-ios.sh [options] @@ -1861,15 +1975,18 @@ npm run build:web:docker:prod # Production Docker build ``` **Build Modes**: + - **Development**: Build for development environment - **Test**: Build for testing environment - **Production**: Build for production environment **Build Types**: + - **Debug**: Build debug app (default) - **Release**: Build release app **Key Features**: + - **Environment Validation**: Checks for Xcode, iOS Simulator, Capacitor - **Resource Checking**: Validates app icons, splash screens, Info.plist - **Clean Build**: Removes Xcode build artifacts and DerivedData @@ -1878,15 +1995,17 @@ npm run build:web:docker:prod # Production Docker build ### A.5 common.sh -**File**: `scripts/common.sh` -**Author**: Matthew Raymer +**File**: `scripts/common.sh` +**Author**: Matthew Raymer **Description**: Common utilities and functions for build scripts -**Purpose**: Provides shared functionality, logging, environment setup, and utility functions used by all build scripts. +**Purpose**: Provides shared functionality, logging, environment setup, and +utility functions used by all build scripts. **Key Functions**: **Logging Functions**: + ```bash log_info "message" # Info level logging log_success "message" # Success level logging @@ -1896,6 +2015,7 @@ log_debug "message" # Debug level logging ``` **Environment Functions**: + ```bash setup_build_env "platform" # Setup build environment for platform load_env_file "filename" # Load environment variables from file @@ -1903,6 +2023,7 @@ print_env_vars "prefix" # Print environment variables with prefix ``` **Utility Functions**: + ```bash check_command "command" # Check if command is available check_file "filename" # Check if file exists @@ -1911,6 +2032,7 @@ clean_build_artifacts "dir" # Clean build artifacts directory ``` **Validation Functions**: + ```bash validate_build_environment # Validate common build environment setup_app_directories # Setup application directories @@ -1919,13 +2041,15 @@ print_header "title" # Print formatted header ### A.6 Cleaning Commands -**File**: `package.json` scripts -**Author**: Matthew Raymer +**File**: `package.json` scripts +**Author**: Matthew Raymer **Description**: Platform-specific and comprehensive cleaning commands -**Purpose**: Provides commands to clean build artifacts for individual platforms or all platforms at once. +**Purpose**: Provides commands to clean build artifacts for individual platforms +or all platforms at once. **Available Commands**: + ```bash # Platform-specific cleaning npm run clean:ios # Clean iOS build artifacts @@ -1944,26 +2068,31 @@ npm run build:electron:clean # Clean Electron build artifacts (via build scrip **Command Details**: **clean:ios**: + - Removes iOS build directories (`ios/App/build`, `ios/App/Pods`, etc.) - Cleans DerivedData and Capacitor artifacts - Safe to run multiple times **clean:android**: + - Uninstalls app from connected devices - Cleans Android build artifacts - Safe to run multiple times **clean:electron**: + - Cleans Electron build artifacts (`electron/build`, `electron/dist`, `electron/app`) - Removes TypeScript compilation artifacts - Safe to run multiple times **clean:all**: + - Executes all platform-specific clean commands in sequence - Stops on first failure (uses `&&` operator) - Most convenient for complete cleanup **Usage Examples**: + ```bash # Clean everything before a fresh build npm run clean:all @@ -1981,17 +2110,20 @@ npm run build:web:dev ## Appendix B: Vite Configuration Files Reference -This appendix provides detailed documentation for all Vite configuration files used in the TimeSafari build system. +This appendix provides detailed documentation for all Vite configuration files used +in the TimeSafari build system. ### B.1 vite.config.common.mts -**File**: `vite.config.common.mts` -**Author**: Matthew Raymer +**File**: `vite.config.common.mts` +**Author**: Matthew Raymer **Description**: Common Vite configuration shared across all platforms -**Purpose**: Provides base configuration that is extended by platform-specific configs with unified environment handling and platform detection. +**Purpose**: Provides base configuration that is extended by platform-specific +configs with unified environment handling and platform detection. **Key Features**: + - **Platform Detection**: Automatically detects and configures for web/capacitor/electron - **Environment Setup**: Loads environment variables and sets platform flags - **Path Aliases**: Configures TypeScript path resolution and module aliases @@ -1999,6 +2131,7 @@ This appendix provides detailed documentation for all Vite configuration files u - **Dependency Management**: Handles platform-specific dependencies **Configuration Structure**: + ```typescript export async function createBuildConfig(platform: string): Promise { const appConfig = await loadAppConfig(); @@ -2066,25 +2199,29 @@ export async function createBuildConfig(platform: string): Promise { ``` **Environment Variables**: + - `VITE_PLATFORM`: Set to platform name (web/capacitor/electron) - `__IS_MOBILE__`: Boolean flag for mobile platforms - `__IS_ELECTRON__`: Boolean flag for Electron platform - `__USE_QR_READER__`: Boolean flag for QR reader availability **Path Aliases**: + - `@`: Points to `src/` directory - `@nostr/tools`: Nostr tools library - `path`, `fs`, `crypto`: Node.js polyfills for browser ### B.2 vite.config.web.mts -**File**: `vite.config.web.mts` -**Author**: Matthew Raymer +**File**: `vite.config.web.mts` +**Author**: Matthew Raymer **Description**: Vite configuration for web platform with PWA support -**Purpose**: Configures Vite for web builds with environment-specific optimizations and PWA features. +**Purpose**: Configures Vite for web builds with environment-specific +optimizations and PWA features. **Key Features**: + - **Environment-Specific Configuration**: Different settings for dev/test/prod - **PWA Integration**: Progressive Web App support with service worker - **Build Optimization**: Manual chunk splitting for better caching @@ -2094,6 +2231,7 @@ export async function createBuildConfig(platform: string): Promise { **Environment Configurations**: **Development Mode**: + ```typescript { build: { @@ -2110,6 +2248,7 @@ export async function createBuildConfig(platform: string): Promise { ``` **Test Mode**: + ```typescript { build: { @@ -2126,6 +2265,7 @@ export async function createBuildConfig(platform: string): Promise { ``` **Production Mode**: + ```typescript { build: { @@ -2151,6 +2291,7 @@ export async function createBuildConfig(platform: string): Promise { ``` **PWA Configuration**: + ```typescript VitePWA({ registerType: 'autoUpdate', @@ -2169,13 +2310,15 @@ VitePWA({ ### B.3 vite.config.electron.mts -**File**: `vite.config.electron.mts` -**Author**: Matthew Raymer +**File**: `vite.config.electron.mts` +**Author**: Matthew Raymer **Description**: Vite configuration for Electron desktop platform -**Purpose**: Configures Vite for Electron builds with desktop-specific optimizations and native module support. +**Purpose**: Configures Vite for Electron builds with desktop-specific optimizations + and native module support. **Key Features**: + - **Electron-Specific Entry Point**: Uses `main.electron.ts` instead of `main.web.ts` - **Native Module Support**: Handles Electron-specific dependencies - **Desktop Optimizations**: Larger chunk sizes and desktop-specific settings @@ -2183,10 +2326,11 @@ VitePWA({ - **External Dependencies**: Properly handles Electron and native modules **Configuration Structure**: + ```typescript export default defineConfig(async () => { const baseConfig = await createBuildConfig("electron"); - + return { ...baseConfig, plugins: [ @@ -2220,24 +2364,28 @@ export default defineConfig(async () => { ``` **Plugins**: + - **electron-entry-point**: Replaces main entry point for Electron - **electron-config**: Handles Electron-specific configurations - **suppress-source-maps**: Suppresses source map loading errors **External Dependencies**: + - `electron`: Electron runtime - `@capacitor-community/electron`: Capacitor Electron plugin - `better-sqlite3-multiple-ciphers`: Native SQLite module ### B.4 vite.config.capacitor.mts -**File**: `vite.config.capacitor.mts` -**Author**: Matthew Raymer +**File**: `vite.config.capacitor.mts` +**Author**: Matthew Raymer **Description**: Vite configuration for Capacitor mobile platform -**Purpose**: Provides minimal configuration for Capacitor builds, inheriting from common config. +**Purpose**: Provides minimal configuration for Capacitor builds, inheriting from +common config. **Configuration**: + ```typescript import { defineConfig } from "vite"; import { createBuildConfig } from "./vite.config.common.mts"; @@ -2246,6 +2394,7 @@ export default defineConfig(async () => createBuildConfig('capacitor')); ``` **Key Features**: + - **Minimal Configuration**: Inherits all settings from common config - **Mobile Platform**: Automatically configures for mobile-specific settings - **PWA Disabled**: Progressive Web App features disabled for native apps @@ -2253,8 +2402,8 @@ export default defineConfig(async () => createBuildConfig('capacitor')); ### B.5 vite.config.utils.mts -**File**: `vite.config.utils.mts` -**Author**: Matthew Raymer +**File**: `vite.config.utils.mts` +**Author**: Matthew Raymer **Description**: Utility functions for Vite configuration **Purpose**: Provides shared configuration loading and PWA manifest generation. @@ -2266,6 +2415,7 @@ export default defineConfig(async () => createBuildConfig('capacitor')); **loadAppConfig()**: Loads complete application configuration including PWA settings **PWA Configuration**: + ```typescript interface PWAConfig { registerType: string; @@ -2284,11 +2434,13 @@ interface PWAConfig { ``` **Manifest Icons**: + - Android Chrome 192x192 PNG - Android Chrome 512x512 PNG - Maskable icons for adaptive UI **Share Target Configuration**: + ```typescript share_target: { action: "/share-target", @@ -2301,6 +2453,7 @@ share_target: { ``` **Alias Configuration**: + - `@`: Source directory alias - `buffer`: Buffer polyfill - `dexie-export-import`: Database import/export utilities @@ -2335,23 +2488,27 @@ source "$(dirname "$0")/common.sh" ### C.3 Build Process Flow **Web Build**: -``` + +```text build-web.sh → vite.config.web.mts → dist/ ``` **Electron Build**: -``` + +```text build-electron.sh → vite.config.electron.mts → electron/app/ ``` **Mobile Build**: -``` + +```text build-android.sh/build-ios.sh → vite.config.capacitor.mts → android/ios/ ``` ### C.4 Error Handling All scripts use consistent error handling: + - Exit codes for different failure types - Verbose logging with `--verbose` flag - Safe command execution with `safe_execute()` @@ -2360,20 +2517,25 @@ All scripts use consistent error handling: ### C.5 Platform-Specific Considerations **Web Platform**: + - PWA features enabled - Service worker injection - Browser-specific optimizations **Electron Platform**: + - Native module support - Desktop-specific entry points - Source map suppression **Mobile Platform**: + - Capacitor integration - Native asset generation - Platform-specific builds --- -**Note**: This documentation is maintained alongside the build system. For the most up-to-date information, refer to the actual script files and Vite configuration files in the repository. +**Note**: This documentation is maintained alongside the build system. For the +most up-to-date information, refer to the actual script files and Vite +configuration files in the repository. diff --git a/CHANGELOG.md b/CHANGELOG.md index 19209fb6..641ff920 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,69 +6,88 @@ 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.7] - 2025.08.18 + ### Fixed -- Deep link for onboard-meeting-members +- Deep link for onboard-meeting-members ## [1.0.6] - 2025.08.09 + ### Fixed -- Deep link errors where none would validate +- Deep link errors where none would validate ## [1.0.5] - 2025.07.24 + ### Fixed -- Export & import of contacts corrupted contact methods +- Export & import of contacts corrupted contact methods ## [1.0.4] - 2025.07.20 - 002f2407208d56cc59c0aa7c880535ae4cbace8b + ### Fixed -- Deep link for invite-one-accept +- Deep link for invite-one-accept ## [1.0.3] - 2025.07.12 - a9a8ba217cd6015321911e98e6843e988dc2c4ae + ### Changed + - Photo is pinned to profile mode + ### Fixed + - Deep link URLs (and other prod settings) - Error in BVC begin view - ## [1.0.2] - 2025.06.20 - 276e0a741bc327de3380c4e508cccb7fee58c06d + ### Added -- Version on feed title +- Version on feed title ## [1.0.1] - 2025.06.20 + ### Added -- Allow a user to block someone else's content from view +- 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 +- 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 +- IndexedDB -> SQLite ## [0.4.5] - 2025.02.23 + ### Added + - Total amounts of gives on project page + ### Changed in DB or environment -- Requires Endorser.ch version 4.2.6+ +- Requires Endorser.ch version 4.2.6+ ## [0.4.4] - 2025.02.17 diff --git a/TASK_storage.md b/TASK_storage.md index a33cbb87..52b52b76 100644 --- a/TASK_storage.md +++ b/TASK_storage.md @@ -1,7 +1,6 @@ # What to do about storage for native apps? - ## Problem We can't trust iOS IndexedDB to persist. I want to start delivering an app to people now, in preparation for presentations mid-June: Rotary on June 12 and Porcfest on June 17. @@ -14,7 +13,6 @@ We can't trust iOS IndexedDB to persist. I want to start delivering an app to pe Also, with sensitive data, the accounts info should be encrypted. - # Options * There is a community [SQLite plugin for Capacitor](https://github.com/capacitor-community/sqlite) with encryption by [SQLCipher](https://github.com/sqlcipher/sqlcipher). @@ -29,16 +27,12 @@ Also, with sensitive data, the accounts info should be encrypted. * Not an option yet: Dexie may support SQLite in [a future version](https://dexie.org/roadmap/dexie5.0). - - # Current Plan * Implement SQLite for Capacitor & web, with encryption. That will allow us to test quickly and keep the same interface for native & web, but we don't deal with migrations for current web users. * After that is delivered, write a migration for current web users from IndexedDB to SQLite. - - # Current method calls ... which is not 100% complete because the AI that generated thus claimed no usage of 'temp' DB. @@ -80,5 +74,3 @@ Logs operations: db.logs.get(todayKey) - Gets logs for a specific day db.logs.update(todayKey, { message: fullMessage }) - Updates logs db.logs.clear() - Clears all logs - - diff --git a/doc/DEEP_LINKS.md b/doc/DEEP_LINKS.md index a6bf9f6b..8638074b 100644 --- a/doc/DEEP_LINKS.md +++ b/doc/DEEP_LINKS.md @@ -47,6 +47,7 @@ type ClaimParams = z.infer; ### Type Safety Layers 1. **Schema Definition** + ```typescript // src/interfaces/deepLinks.ts export const deepLinkSchemas = { @@ -59,6 +60,7 @@ type ClaimParams = z.infer; ``` 2. **Type Generation** + ```typescript // Types are automatically generated from schemas export type DeepLinkParams = { @@ -67,6 +69,7 @@ type ClaimParams = z.infer; ``` 3. **Runtime Validation** + ```typescript // In DeepLinkHandler const result = deepLinkSchemas.claim.safeParse(params); diff --git a/doc/README.md b/doc/README.md index 45e98fc4..3e876ca0 100644 --- a/doc/README.md +++ b/doc/README.md @@ -6,7 +6,7 @@ This uses Pandoc and BasicTex (LaTeX) Installed through Homebrew. ### Set Up -```bash +```bash brew install pandoc brew install basictex @@ -54,7 +54,7 @@ sudo tlmgr install sourceserifpro The following guide was adapted to this project except that we install with Brew and have a few more packages. -Guide: https://daniel.feldroy.com/posts/setting-up-latex-on-mac-os-x +Guide: ### Usage @@ -71,6 +71,7 @@ open usage-guide.pdf ``` Or use this one-liner + ```bash pandoc usage-guide.md -o usage-guide.pdf && open usage-guide.pdf ``` diff --git a/doc/architecture-decisions.md b/doc/architecture-decisions.md index 40fa3d3f..11861b8f 100644 --- a/doc/architecture-decisions.md +++ b/doc/architecture-decisions.md @@ -122,4 +122,4 @@ export default class HomeView extends Vue { --- -*This decision was made based on the current codebase architecture and team expertise. The mixin approach provides the best balance of performance, developer experience, and architectural consistency for the TimeSafari application.* \ No newline at end of file +*This decision was made based on the current codebase architecture and team expertise. The mixin approach provides the best balance of performance, developer experience, and architectural consistency for the TimeSafari application.* diff --git a/doc/asset-migration-plan.md b/doc/asset-migration-plan.md index 3a05353c..86c0954e 100644 --- a/doc/asset-migration-plan.md +++ b/doc/asset-migration-plan.md @@ -103,6 +103,7 @@ scripts/ ### Configuration Schema The schema enforces: + - Source files must be in `resources/` directory - Required fields for icon and splash sections - Android adaptive icon support (foreground/background/monochrome) diff --git a/doc/build-modernization-context.md b/doc/build-modernization-context.md index 133c2ad6..4f2ae09e 100644 --- a/doc/build-modernization-context.md +++ b/doc/build-modernization-context.md @@ -3,11 +3,13 @@ **Author:** Matthew Raymer ## Motivation + - Eliminate manual hacks and post-build scripts for Electron builds - Ensure maintainability, reproducibility, and security of build outputs - Unify build, test, and deployment scripts for developer experience and CI/CD ## Key Technical Decisions + - **Vite is the single source of truth for build output** - All Electron build output (main process, preload, renderer HTML/CSS/JS) is managed by `vite.config.electron.mts` - **CSS injection for Electron is handled by a Vite plugin** @@ -21,6 +23,7 @@ - Renderer assets: `dist-electron/www/` (HTML, CSS, JS) ## Security & Maintenance Checklist + - [x] All scripts and configs are committed and documented - [x] No manual file hacks remain - [x] All build output is deterministic and reproducible @@ -28,24 +31,29 @@ - [x] Documentation (`BUILDING.md`) is up to date ## How to Build Electron + 1. Run: + ```bash ./scripts/build-electron.sh ``` + 2. Output will be in `dist-electron/`: - `main.js`, `preload.js` in root - `www/` contains all renderer assets 3. No manual post-processing is required ## Customization + - **Vite config:** All build output and asset handling is controlled in `vite.config.electron.mts` - **CSS/HTML injection:** Use Vite plugins (see `electron-css-injection` in the config) for further customization - **Build scripts:** All orchestration is in `scripts/` and documented in `BUILDING.md` ## For Future Developers + - Always use Vite plugins/config for build output changes - Never manually edit built files or inject assets post-build - Keep documentation and scripts in sync with the build process --- -This file documents the context and rationale for the build modernization and should be included in the repository for onboarding and future reference. \ No newline at end of file +This file documents the context and rationale for the build modernization and should be included in the repository for onboarding and future reference. diff --git a/doc/circular-dependency-analysis.md b/doc/circular-dependency-analysis.md index 0ae322dc..a6530e62 100644 --- a/doc/circular-dependency-analysis.md +++ b/doc/circular-dependency-analysis.md @@ -13,27 +13,31 @@ The codebase currently has **no active circular dependencies** that are causing ### 🔍 **Resolved Dependency Patterns** #### 1. **Logger → PlatformServiceFactory → Logger** (RESOLVED) + - **Status**: ✅ **RESOLVED** - **Previous Issue**: Logger imported `logToDb` from databaseUtil, which imported logger - **Solution**: Logger now uses direct database access via PlatformServiceFactory - **Implementation**: Self-contained `logToDatabase()` function in logger.ts #### 2. **PlatformServiceMixin → databaseUtil → logger → PlatformServiceMixin** (RESOLVED) + - **Status**: ✅ **RESOLVED** - **Previous Issue**: PlatformServiceMixin imported `memoryLogs` from databaseUtil - **Solution**: Created self-contained `_memoryLogs` array in PlatformServiceMixin - **Implementation**: Self-contained memory logs implementation #### 3. **databaseUtil → logger → PlatformServiceFactory → databaseUtil** (RESOLVED) + - **Status**: ✅ **RESOLVED** - **Previous Issue**: databaseUtil imported logger, which could create loops - **Solution**: Logger is now self-contained and doesn't import from databaseUtil #### 4. **Utility Files → databaseUtil → PlatformServiceMixin** (RESOLVED) + - **Status**: ✅ **RESOLVED** - **Previous Issue**: `src/libs/util.ts` and `src/services/deepLinks.ts` imported from databaseUtil - **Solution**: Replaced with self-contained implementations and PlatformServiceFactory usage -- **Implementation**: +- **Implementation**: - Self-contained `parseJsonField()` and `mapQueryResultToValues()` functions - Direct PlatformServiceFactory usage for database operations - Console logging instead of databaseUtil logging functions @@ -43,18 +47,21 @@ The codebase currently has **no active circular dependencies** that are causing ### ✅ **All Critical Dependencies Resolved** #### PlatformServiceMixin Independence + - **Status**: ✅ **COMPLETE** - **Achievement**: PlatformServiceMixin has no external dependencies on databaseUtil - **Implementation**: Self-contained memory logs and utility functions - **Impact**: Enables complete migration of databaseUtil functions to PlatformServiceMixin #### Logger Independence + - **Status**: ✅ **COMPLETE** - **Achievement**: Logger is completely self-contained - **Implementation**: Direct database access via PlatformServiceFactory - **Impact**: Eliminates all circular dependency risks #### Utility Files Independence + - **Status**: ✅ **COMPLETE** - **Achievement**: All utility files no longer depend on databaseUtil - **Implementation**: Self-contained functions and direct platform service access @@ -63,6 +70,7 @@ The codebase currently has **no active circular dependencies** that are causing ### 🎯 **Migration Readiness Status** #### Files Ready for Migration (52 files) + 1. **Components** (15 files): - `PhotoDialog.vue` - `FeedFilters.vue` @@ -98,6 +106,7 @@ The codebase currently has **no active circular dependencies** that are causing ### 🟢 **Healthy Dependencies** #### Logger Usage (80+ files) + - **Status**: ✅ **HEALTHY** - **Pattern**: All files import logger from `@/utils/logger` - **Impact**: No circular dependencies, logger is self-contained @@ -106,21 +115,25 @@ The codebase currently has **no active circular dependencies** that are causing ## Resolution Strategy - COMPLETED ### ✅ **Phase 1: Complete PlatformServiceMixin Independence (COMPLETE)** + 1. **Removed memoryLogs import** from PlatformServiceMixin ✅ 2. **Created self-contained memoryLogs** implementation ✅ 3. **Added missing utility methods** to PlatformServiceMixin ✅ ### ✅ **Phase 2: Utility Files Migration (COMPLETE)** + 1. **Migrated deepLinks.ts** - Replaced databaseUtil logging with console logging ✅ 2. **Migrated util.ts** - Replaced databaseUtil functions with self-contained implementations ✅ 3. **Updated all PlatformServiceFactory calls** to use async pattern ✅ ### 🎯 **Phase 3: File-by-File Migration (READY TO START)** + 1. **High-usage files first** (views, core components) 2. **Replace databaseUtil imports** with PlatformServiceMixin 3. **Update function calls** to use mixin methods ### 🎯 **Phase 4: Cleanup (FUTURE)** + 1. **Remove unused databaseUtil functions** 2. **Update TypeScript interfaces** 3. **Remove databaseUtil imports** from all files @@ -128,6 +141,7 @@ The codebase currently has **no active circular dependencies** that are causing ## Current Status Summary ### ✅ **Resolved Issues** + 1. **Logger circular dependency** - Fixed with self-contained implementation 2. **PlatformServiceMixin circular dependency** - Fixed with self-contained memoryLogs 3. **Utility files circular dependency** - Fixed with self-contained implementations @@ -135,6 +149,7 @@ The codebase currently has **no active circular dependencies** that are causing 5. **Runtime stability** - No circular dependency crashes ### 🎯 **Ready for Next Phase** + 1. **52 files** ready for databaseUtil migration 2. **PlatformServiceMixin** fully independent and functional 3. **Clear migration path** - Well-defined targets and strategy @@ -142,6 +157,7 @@ The codebase currently has **no active circular dependencies** that are causing ## Benefits of Current State ### ✅ **Achieved** + 1. **No runtime circular dependencies** - Application runs without crashes 2. **Self-contained logger** - No more logger/databaseUtil loops 3. **PlatformServiceMixin ready** - All methods implemented and independent @@ -149,6 +165,7 @@ The codebase currently has **no active circular dependencies** that are causing 5. **Clear migration path** - Well-defined targets and strategy ### 🎯 **Expected After Migration** + 1. **Complete databaseUtil migration** - Single source of truth 2. **Eliminated circular dependencies** - Clean architecture 3. **Improved performance** - Caching and optimization @@ -160,4 +177,4 @@ The codebase currently has **no active circular dependencies** that are causing **Created**: 2025-07-05 **Status**: ✅ **COMPLETE - All Circular Dependencies Resolved** **Last Updated**: 2025-01-06 -**Note**: PlatformServiceMixin circular dependency completely resolved. Ready for Phase 2: File-by-File Migration \ No newline at end of file +**Note**: PlatformServiceMixin circular dependency completely resolved. Ready for Phase 2: File-by-File Migration diff --git a/doc/component-communication-guide.md b/doc/component-communication-guide.md index 1fad5968..797e5740 100644 --- a/doc/component-communication-guide.md +++ b/doc/component-communication-guide.md @@ -93,6 +93,7 @@ export default class FormComponent extends Vue { When generating component templates, follow these patterns: #### Function Props Template + ```vue