docs: comprehensive build system documentation overhaul
- Expand BUILDING.md with detailed platform-specific build commands and workflows - Add comprehensive web build script documentation with environment modes and Docker support - Include complete iOS/Android build command reference with auto-run capabilities - Document Electron build patterns with code signing and packaging instructions - Add troubleshooting sections for common build issues across platforms - Streamline README.md by removing redundant build system details - Include build architecture overview with service worker and environment configuration - Add comprehensive npm script reference for all build operations - Document auto-run system and platform-specific testing workflows - Include security considerations and code signing procedures for distribution Improves developer experience with complete build system documentation and reduces onboarding friction for new contributors.
This commit is contained in:
736
BUILDING.md
736
BUILDING.md
@@ -1,24 +1,22 @@
|
|||||||
# Building TimeSafari
|
# Building TimeSafari
|
||||||
|
|
||||||
This guide explains how to build TimeSafari for different platforms.
|
This guide explains how to build TimeSafari for different platforms using the comprehensive build system.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
For a quick dev environment setup, use [pkgx](https://pkgx.dev).
|
- Node.js 18+ and npm
|
||||||
|
|
||||||
- Node.js (LTS version recommended)
|
|
||||||
- npm (comes with Node.js)
|
|
||||||
- Git
|
- Git
|
||||||
|
- For mobile builds: Xcode (macOS) or Android Studio
|
||||||
- For desktop builds: Additional build tools based on your OS
|
- For desktop builds: Additional build tools based on your OS
|
||||||
|
|
||||||
## Forks
|
## Forks
|
||||||
|
|
||||||
If you have forked this to make your own app, you'll want to customize the iOS & Android files. You can either edit existing ones, or you can remove the `ios` and `android` directories and regenerate them before the `npx cap sync` step in each setup.
|
If you have forked this to make your own app, you'll want to customize the iOS & Android files. You can either edit existing ones, or you can remove the `ios` and `android` directories and regenerate them before the `npx cap sync` step in each setup.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx cap add android
|
npx cap add android
|
||||||
npx cap add ios
|
npx cap add ios
|
||||||
```
|
```
|
||||||
|
|
||||||
You'll also want to edit the deep link configuration (see below).
|
You'll also want to edit the deep link configuration (see below).
|
||||||
|
|
||||||
@@ -26,41 +24,104 @@ You'll also want to edit the deep link configuration (see below).
|
|||||||
|
|
||||||
Install dependencies:
|
Install dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
## Web Dev Locally
|
## Web Development
|
||||||
|
|
||||||
```bash
|
### Local Development
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
## Web Build for Server
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Web Build for Server
|
||||||
|
|
||||||
1. Run the production build:
|
1. Run the production build:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
rm -rf dist
|
rm -rf dist
|
||||||
npm run build:web
|
npm run build:web
|
||||||
```
|
```
|
||||||
|
|
||||||
The built files will be in the `dist` directory.
|
The built files will be in the `dist` directory.
|
||||||
|
|
||||||
2. To test the production build locally:
|
2. To test the production build locally:
|
||||||
|
|
||||||
You'll likely want to use test locations for the Endorser & image & partner servers; see "DEFAULT_ENDORSER_API_SERVER" & "DEFAULT_IMAGE_API_SERVER" & "DEFAULT_PARTNER_API_SERVER" below.
|
You'll likely want to use test locations for the Endorser & image & partner servers; see "DEFAULT_ENDORSER_API_SERVER" & "DEFAULT_IMAGE_API_SERVER" & "DEFAULT_PARTNER_API_SERVER" below.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run serve
|
npm run serve
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Web Build Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Development builds
|
||||||
|
npm run build:web:dev # Development build with hot reload
|
||||||
|
npm run build:web:test # Test environment build
|
||||||
|
npm run build:web:prod # Production build
|
||||||
|
npm run build:web:serve # Production build with serve
|
||||||
|
|
||||||
|
# Docker builds
|
||||||
|
npm run build:web:docker # Docker development build
|
||||||
|
npm run build:web:docker:test # Docker test build
|
||||||
|
npm run build:web:docker:prod # Docker production build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Web Build Script Details
|
||||||
|
|
||||||
|
All web build commands use the `./scripts/build-web.sh` script, which provides:
|
||||||
|
|
||||||
|
**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
|
||||||
|
- **Vite Build**: Executes `npx vite build --config vite.config.web.mts`
|
||||||
|
- **Docker Support**: Optional Docker containerization
|
||||||
|
- **Local Serving**: Built-in HTTP server for testing builds
|
||||||
|
|
||||||
|
**Direct Script Usage:**
|
||||||
|
```bash
|
||||||
|
# Direct script usage (no npm chaining)
|
||||||
|
./scripts/build-web.sh # Development build
|
||||||
|
./scripts/build-web.sh --dev # Development build (explicit)
|
||||||
|
./scripts/build-web.sh --test # Test environment build
|
||||||
|
./scripts/build-web.sh --prod # Production environment build
|
||||||
|
./scripts/build-web.sh --docker # Build with Docker containerization
|
||||||
|
./scripts/build-web.sh --docker:test # Test environment + Docker
|
||||||
|
./scripts/build-web.sh --docker:prod # Production environment + Docker
|
||||||
|
./scripts/build-web.sh --serve # Build and serve locally
|
||||||
|
./scripts/build-web.sh --help # Show help
|
||||||
|
./scripts/build-web.sh --verbose # Enable verbose logging
|
||||||
|
```
|
||||||
|
|
||||||
|
**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
|
||||||
|
4. **Vite Build**: Execute Vite with appropriate configuration
|
||||||
|
5. **Optional Docker**: Build Docker container if requested
|
||||||
|
6. **Optional Serve**: Start local HTTP server if requested
|
||||||
|
|
||||||
|
**Exit Codes:**
|
||||||
|
- `1` - Web cleanup failed
|
||||||
|
- `2` - Environment setup failed
|
||||||
|
- `3` - Vite build failed
|
||||||
|
- `4` - Docker build failed
|
||||||
|
- `5` - Serve command failed
|
||||||
|
- `6` - Invalid build mode
|
||||||
|
|
||||||
### Compile and minify for test & production
|
### 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.
|
||||||
|
|
||||||
* `npx prettier --write ./sw_scripts/`
|
|
||||||
|
|
||||||
* 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`
|
* Run a build to make sure package-lock version is updated, linting works, etc: `npm install && npm run build`
|
||||||
@@ -74,14 +135,21 @@ Install dependencies:
|
|||||||
* 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
|
```bash
|
||||||
TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch VITE_DEFAULT_PUSH_SERVER=https://test.timesafari.app VITE_PASSKEYS_ENABLED=true npm run build:web
|
TIME_SAFARI_APP_TITLE="TimeSafari_Test" \
|
||||||
|
VITE_APP_SERVER=https://test.timesafari.app \
|
||||||
|
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F \
|
||||||
|
VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch \
|
||||||
|
VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app \
|
||||||
|
VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch \
|
||||||
|
VITE_DEFAULT_PUSH_SERVER=https://test.timesafari.app \
|
||||||
|
VITE_PASSKEYS_ENABLED=true npm run build:web
|
||||||
```
|
```
|
||||||
|
|
||||||
... and transfer to the test server:
|
... and transfer to the test server:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari
|
rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari
|
||||||
```
|
```
|
||||||
|
|
||||||
(Let's replace that with a .env.development or .env.test file.)
|
(Let's replace that with a .env.development or .env.test file.)
|
||||||
|
|
||||||
@@ -89,13 +157,13 @@ TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.
|
|||||||
|
|
||||||
* 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:
|
... 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 && cd -`
|
* `cd crowd-funder-for-time-pwa && git checkout master && git pull && git checkout 1.0.2 && npm install && npm run build:web && cd -`
|
||||||
|
|
||||||
(The plain `npm run build:web` uses the .env.production file.)
|
(The plain `npm run build:web` 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/`
|
||||||
|
|
||||||
@@ -114,29 +182,29 @@ The application can be containerized using Docker for consistent deployment acro
|
|||||||
|
|
||||||
1. Build the Docker image:
|
1. Build the Docker image:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t timesafari:latest .
|
docker build -t timesafari:latest .
|
||||||
```
|
```
|
||||||
|
|
||||||
2. For development builds with specific environment variables:
|
2. For development builds with specific environment variables:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build --build-arg NODE_ENV=development -t timesafari:dev .
|
docker build --build-arg NODE_ENV=development -t timesafari:dev .
|
||||||
```
|
```
|
||||||
|
|
||||||
### Running the Container
|
### Running the Container
|
||||||
|
|
||||||
1. Run the container:
|
1. Run the container:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d -p 80:80 timesafari:latest
|
docker run -d -p 80:80 timesafari:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
2. For development with hot-reloading:
|
2. For development with hot-reloading:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d -p 80:80 -v $(pwd):/app timesafari:dev
|
docker run -d -p 80:80 -v $(pwd):/app timesafari:dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using Docker Compose
|
### Using Docker Compose
|
||||||
|
|
||||||
@@ -160,6 +228,17 @@ Run with Docker Compose:
|
|||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Docker Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Docker operations
|
||||||
|
npm run docker:up # Start Docker services
|
||||||
|
npm run docker:up:test # Start test environment
|
||||||
|
npm run docker:up:prod # Start production environment
|
||||||
|
npm run docker:down # Stop Docker services
|
||||||
|
npm run docker:logs # View logs
|
||||||
|
```
|
||||||
|
|
||||||
### Production Deployment
|
### Production Deployment
|
||||||
|
|
||||||
For production deployment, consider the following:
|
For production deployment, consider the following:
|
||||||
@@ -204,10 +283,7 @@ docker run -d \
|
|||||||
|
|
||||||
## Desktop Build (Electron)
|
## Desktop Build (Electron)
|
||||||
|
|
||||||
TimeSafari's Electron build system provides comprehensive desktop application
|
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.
|
||||||
packaging and distribution capabilities across Windows, macOS, and Linux
|
|
||||||
platforms. The system supports multiple build modes, environment
|
|
||||||
configurations, and package formats.
|
|
||||||
|
|
||||||
### Quick Start
|
### Quick Start
|
||||||
|
|
||||||
@@ -593,48 +669,48 @@ electron/
|
|||||||
For public distribution on macOS, you need to code sign and notarize your app:
|
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
|
```bash
|
||||||
export CSC_LINK=/path/to/your/certificate.p12
|
export CSC_LINK=/path/to/your/certificate.p12
|
||||||
export CSC_KEY_PASSWORD=your_certificate_password
|
export CSC_KEY_PASSWORD=your_certificate_password
|
||||||
export APPLE_ID=your_apple_id
|
export APPLE_ID=your_apple_id
|
||||||
export APPLE_ID_PASSWORD=your_app_specific_password
|
export APPLE_ID_PASSWORD=your_app_specific_password
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Build with signing:
|
2. Build with signing:
|
||||||
```bash
|
```bash
|
||||||
npm run build:electron:mac:prod
|
npm run build:electron:mac:prod
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Windows Code Signing
|
#### Windows Code Signing
|
||||||
|
|
||||||
For Windows distribution, configure Authenticode signing:
|
For Windows distribution, configure Authenticode signing:
|
||||||
|
|
||||||
1. Set up environment variables:
|
1. Set up environment variables:
|
||||||
```bash
|
```bash
|
||||||
export CSC_LINK=/path/to/your/certificate.p12
|
export CSC_LINK=/path/to/your/certificate.p12
|
||||||
export CSC_KEY_PASSWORD=your_certificate_password
|
export CSC_KEY_PASSWORD=your_certificate_password
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Build with signing:
|
2. Build with signing:
|
||||||
```bash
|
```bash
|
||||||
npm run build:electron:windows:prod
|
npm run build:electron:windows:prod
|
||||||
```
|
```
|
||||||
|
|
||||||
### Running the Packaged App
|
### Running the Packaged App
|
||||||
|
|
||||||
#### Linux
|
#### Linux
|
||||||
|
|
||||||
- **AppImage**: Make executable and run
|
- **AppImage**: Make executable and run
|
||||||
```bash
|
```bash
|
||||||
chmod +x electron/dist/TimeSafari-*.AppImage
|
chmod +x electron/dist/TimeSafari-*.AppImage
|
||||||
./electron/dist/TimeSafari-*.AppImage
|
./electron/dist/TimeSafari-*.AppImage
|
||||||
```
|
```
|
||||||
|
|
||||||
- **DEB**: Install and run
|
- **DEB**: Install and run
|
||||||
```bash
|
```bash
|
||||||
sudo dpkg -i electron/dist/timesafari_*_amd64.deb
|
sudo dpkg -i electron/dist/timesafari_*_amd64.deb
|
||||||
timesafari
|
timesafari
|
||||||
```
|
```
|
||||||
|
|
||||||
#### macOS
|
#### macOS
|
||||||
|
|
||||||
@@ -759,6 +835,34 @@ The script handles all the necessary steps including:
|
|||||||
- Version number updates
|
- Version number updates
|
||||||
- Xcode project opening
|
- Xcode project opening
|
||||||
|
|
||||||
|
#### iOS Build Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Standard builds
|
||||||
|
npm run build:ios # Standard build and open Xcode
|
||||||
|
npm run build:ios:dev # Development build
|
||||||
|
npm run build:ios:test # Test build
|
||||||
|
npm run build:ios:prod # Production build
|
||||||
|
|
||||||
|
# Auto-run builds
|
||||||
|
npm run build:ios:test:run # Test build with auto-run
|
||||||
|
npm run build:ios:prod:run # Production build with auto-run
|
||||||
|
|
||||||
|
# Debug and release builds
|
||||||
|
npm run build:ios:debug # Debug build
|
||||||
|
npm run build:ios:debug:run # Debug build with auto-run
|
||||||
|
npm run build:ios:release # Release build
|
||||||
|
npm run build:ios:release:run # Release build with auto-run
|
||||||
|
|
||||||
|
# Additional operations
|
||||||
|
npm run build:ios:studio # Open in Xcode Studio
|
||||||
|
npm run build:ios:ipa # Generate IPA file
|
||||||
|
npm run build:ios:clean # Clean build artifacts
|
||||||
|
npm run build:ios:sync # Sync Capacitor
|
||||||
|
npm run build:ios:assets # Generate assets
|
||||||
|
npm run build:ios:deploy # Deploy to device/simulator
|
||||||
|
```
|
||||||
|
|
||||||
#### Manual Build Process
|
#### Manual Build Process
|
||||||
|
|
||||||
If you need to build manually or want to understand the individual steps:
|
If you need to build manually or want to understand the individual steps:
|
||||||
@@ -766,7 +870,6 @@ If you need to build manually or want to understand the individual steps:
|
|||||||
#### First-time iOS Configuration
|
#### First-time iOS Configuration
|
||||||
|
|
||||||
- Generate certificates inside XCode.
|
- Generate certificates inside XCode.
|
||||||
|
|
||||||
- Right-click on App and under Signing & Capabilities set the Team.
|
- Right-click on App and under Signing & Capabilities set the Team.
|
||||||
|
|
||||||
#### Each Release
|
#### Each Release
|
||||||
@@ -842,6 +945,55 @@ If you need to build manually or want to understand the individual steps:
|
|||||||
|
|
||||||
Prerequisites: Android Studio with Java SDK installed
|
Prerequisites: Android Studio with Java SDK installed
|
||||||
|
|
||||||
|
#### Automated Build Script
|
||||||
|
|
||||||
|
The recommended way to build for Android is using the automated build script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Standard build and open Android Studio
|
||||||
|
./scripts/build-android.sh
|
||||||
|
|
||||||
|
# Build with specific version numbers
|
||||||
|
./scripts/build-android.sh --version 1.0.3 --build-number 35
|
||||||
|
|
||||||
|
# Build without opening Android Studio (for CI/CD)
|
||||||
|
./scripts/build-android.sh --no-studio
|
||||||
|
|
||||||
|
# Show all available options
|
||||||
|
./scripts/build-android.sh --help
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Android Build Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Standard builds
|
||||||
|
npm run build:android # Standard build and open Android Studio
|
||||||
|
npm run build:android:dev # Development build
|
||||||
|
npm run build:android:test # Test build
|
||||||
|
npm run build:android:prod # Production build
|
||||||
|
|
||||||
|
# Auto-run builds
|
||||||
|
npm run build:android:test:run # Test build with auto-run
|
||||||
|
npm run build:android:prod:run # Production build with auto-run
|
||||||
|
|
||||||
|
# Debug and release builds
|
||||||
|
npm run build:android:debug # Debug build
|
||||||
|
npm run build:android:debug:run # Debug build with auto-run
|
||||||
|
npm run build:android:release # Release build
|
||||||
|
npm run build:android:release:run # Release build with auto-run
|
||||||
|
|
||||||
|
# Additional operations
|
||||||
|
npm run build:android:studio # Open in Android Studio
|
||||||
|
npm run build:android:apk # Generate APK
|
||||||
|
npm run build:android:aab # Generate AAB (App Bundle)
|
||||||
|
npm run build:android:clean # Clean build artifacts
|
||||||
|
npm run build:android:sync # Sync Capacitor
|
||||||
|
npm run build:android:assets # Generate assets
|
||||||
|
npm run build:android:deploy # Deploy to device/emulator
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Manual Build Process
|
||||||
|
|
||||||
1. Build the web assets:
|
1. Build the web assets:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -874,32 +1026,32 @@ Prerequisites: Android Studio with Java SDK installed
|
|||||||
|
|
||||||
## Android Build from the console
|
## Android Build from the console
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd android
|
cd android
|
||||||
./gradlew clean
|
./gradlew clean
|
||||||
./gradlew build -Dlint.baselines.continue=true
|
./gradlew build -Dlint.baselines.continue=true
|
||||||
cd -
|
cd -
|
||||||
```
|
```
|
||||||
|
|
||||||
... or, to create the `aab` file, `bundle` instead of `build`:
|
... or, to create the `aab` file, `bundle` instead of `build`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./gradlew bundleDebug -Dlint.baselines.continue=true
|
./gradlew bundleDebug -Dlint.baselines.continue=true
|
||||||
```
|
```
|
||||||
|
|
||||||
... or, to create a signed release:
|
... 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
|
* 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
|
* In app/build.gradle, bump the versionCode and maybe the versionName
|
||||||
* Then `bundleRelease`:
|
* Then `bundleRelease`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd android
|
cd android
|
||||||
./gradlew bundleRelease -Dlint.baselines.continue=true
|
./gradlew bundleRelease -Dlint.baselines.continue=true
|
||||||
cd -
|
cd -
|
||||||
```
|
```
|
||||||
|
|
||||||
... and find your `aab` file at app/build/outputs/bundle/release
|
... and find your `aab` file at app/build/outputs/bundle/release
|
||||||
|
|
||||||
At play.google.com/console:
|
At play.google.com/console:
|
||||||
|
|
||||||
@@ -911,18 +1063,394 @@ At play.google.com/console:
|
|||||||
|
|
||||||
- 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build Capacitor assets
|
||||||
|
npm run build:capacitor
|
||||||
|
|
||||||
|
# Sync Capacitor
|
||||||
|
npm run build:capacitor:sync
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Web Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run web tests
|
||||||
|
npm run test:web
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mobile Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run mobile tests
|
||||||
|
npm run test:mobile
|
||||||
|
|
||||||
|
# Android tests
|
||||||
|
npm run test:android
|
||||||
|
|
||||||
|
# iOS tests
|
||||||
|
npm run test:ios
|
||||||
|
```
|
||||||
|
|
||||||
|
### Device Checks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check Android device connection
|
||||||
|
npm run check:android-device
|
||||||
|
|
||||||
|
# Check iOS device/simulator
|
||||||
|
npm run check:ios-device
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Prerequisites
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test prerequisites
|
||||||
|
npm run test:prerequisites
|
||||||
|
```
|
||||||
|
|
||||||
|
## Auto-Run System
|
||||||
|
|
||||||
|
The auto-run system provides automated development workflows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Auto-run with default settings
|
||||||
|
npm run auto-run
|
||||||
|
|
||||||
|
# Auto-run test environment
|
||||||
|
npm run auto-run:test
|
||||||
|
|
||||||
|
# Auto-run production environment
|
||||||
|
npm run auto-run:prod
|
||||||
|
|
||||||
|
# Platform-specific auto-run
|
||||||
|
npm run auto-run:ios
|
||||||
|
npm run auto-run:android
|
||||||
|
npm run auto-run:electron
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cleaning
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clean Android
|
||||||
|
npm run clean:android
|
||||||
|
|
||||||
|
# Clean iOS
|
||||||
|
npm run clean:ios
|
||||||
|
|
||||||
|
# Clean Electron
|
||||||
|
npm run clean:electron
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fastlane Integration
|
||||||
|
|
||||||
|
### iOS Fastlane
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Beta release
|
||||||
|
npm run fastlane:ios:beta
|
||||||
|
|
||||||
|
# App Store release
|
||||||
|
npm run fastlane:ios:release
|
||||||
|
```
|
||||||
|
|
||||||
|
### Android Fastlane
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Beta release
|
||||||
|
npm run fastlane:android:beta
|
||||||
|
|
||||||
|
# Play Store release
|
||||||
|
npm run fastlane:android:release
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code Quality
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lint code
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# Fix linting issues
|
||||||
|
npm run lint-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build Architecture
|
||||||
|
|
||||||
|
### Web Build Process
|
||||||
|
|
||||||
|
1. **Environment Setup**: Load platform-specific environment variables
|
||||||
|
2. **Asset Building**: Vite builds optimized web assets
|
||||||
|
3. **PWA Generation**: Service worker and manifest creation
|
||||||
|
4. **Output**: Production-ready files in `dist/` directory
|
||||||
|
|
||||||
|
### Electron Build Process
|
||||||
|
|
||||||
|
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
|
||||||
|
4. **Native Module Rebuild**: Rebuilds native dependencies
|
||||||
|
5. **Package Creation**: Generates platform-specific installers
|
||||||
|
|
||||||
|
### Mobile Build Process
|
||||||
|
|
||||||
|
1. **Web Build**: Vite builds web assets
|
||||||
|
2. **Capacitor Sync**: Syncs with native platforms
|
||||||
|
3. **Asset Generation**: Creates platform-specific assets
|
||||||
|
4. **Native Build**: Platform-specific compilation
|
||||||
|
5. **Package Creation**: APK/IPA generation
|
||||||
|
|
||||||
|
## Environment Configuration
|
||||||
|
|
||||||
|
### Environment Files
|
||||||
|
|
||||||
|
- `.env.development` - Development environment
|
||||||
|
- `.env.test` - Testing environment
|
||||||
|
- `.env.production` - Production environment
|
||||||
|
|
||||||
|
### Key Environment Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# API Servers
|
||||||
|
VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch
|
||||||
|
VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app
|
||||||
|
VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch
|
||||||
|
|
||||||
|
# Platform Configuration
|
||||||
|
VITE_PLATFORM=web|electron|capacitor
|
||||||
|
VITE_APP_SERVER=https://timesafari.app
|
||||||
|
|
||||||
|
# Feature Flags
|
||||||
|
VITE_PASSKEYS_ENABLED=true
|
||||||
|
```
|
||||||
|
|
||||||
## Android Configuration for deep links
|
## Android Configuration for deep links
|
||||||
|
|
||||||
You must add the following intent filter to the `android/app/src/main/AndroidManifest.xml` file:
|
You must add the following intent filter to the `android/app/src/main/AndroidManifest.xml` file:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<intent-filter android:autoVerify="true">
|
<intent-filter android:autoVerify="true">
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<data android:scheme="timesafari" />
|
<data android:scheme="https" android:host="timesafari.app" />
|
||||||
</intent-filter>
|
<data android:scheme="http" android:host="timesafari.app" />
|
||||||
```
|
</intent-filter>
|
||||||
|
```
|
||||||
|
|
||||||
... though when we tried that most recently it failed to 'build' the APK with: http(s) scheme and host attribute are missing, but are required for Android App Links [AppLinkUrlError]
|
... though when we tried that most recently it failed to 'build' the APK with: http(s) scheme and host attribute are missing, but are required for Android App Links [AppLinkUrlError]
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
#### Build Failures
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clean and rebuild
|
||||||
|
npm run clean:electron
|
||||||
|
npm run build:electron:dev
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Native Module Issues
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rebuild native modules
|
||||||
|
cd electron && npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Asset Issues
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Regenerate assets
|
||||||
|
npm run build:ios:assets
|
||||||
|
npm run build:android:assets
|
||||||
|
```
|
||||||
|
|
||||||
|
### Platform-Specific 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
|
||||||
|
|
||||||
|
#### 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
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Electron Build Patterns](docs/electron-build-patterns.md)
|
||||||
|
- [iOS Build Scripts](docs/ios-build-scripts.md)
|
||||||
|
- [Android Build Scripts](docs/android-build-scripts.md)
|
||||||
|
- [Web Build Scripts](docs/web-build-scripts.md)
|
||||||
|
- [Build Troubleshooting](docs/build-troubleshooting.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix: Build System Organization
|
||||||
|
|
||||||
|
### Build Process Overview
|
||||||
|
|
||||||
|
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**
|
||||||
|
```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.)
|
||||||
|
- 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`
|
||||||
|
- **WASM Copy**: `copy-wasm.js` copies SQLite WASM files to `public/wasm/`
|
||||||
|
|
||||||
|
#### Build Architecture
|
||||||
|
|
||||||
|
**Web Build Process:**
|
||||||
|
```
|
||||||
|
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
|
||||||
|
4. Service Worker: Inject combined scripts into PWA
|
||||||
|
5. Output: Production-ready files in dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Electron Build Process:**
|
||||||
|
```
|
||||||
|
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
|
||||||
|
4. Native Module Rebuild: Rebuilds native dependencies
|
||||||
|
5. Package Creation: Generates platform-specific installers
|
||||||
|
```
|
||||||
|
|
||||||
|
**Mobile Build Process:**
|
||||||
|
```
|
||||||
|
1. Web Build: Vite builds web assets
|
||||||
|
2. Capacitor Sync: Syncs with native platforms
|
||||||
|
3. Asset Generation: Creates platform-specific assets
|
||||||
|
4. Native Build: Platform-specific compilation
|
||||||
|
5. Package Creation: APK/IPA generation
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 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: {
|
||||||
|
strategies: "injectManifest",
|
||||||
|
filename: "sw_scripts-combined.js", // Uses our combined script
|
||||||
|
// ... manifest configuration
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**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
|
||||||
|
|
||||||
|
**Environment Files:**
|
||||||
|
- `.env.development` - Development environment
|
||||||
|
- `.env.test` - Testing environment
|
||||||
|
- `.env.production` - Production environment
|
||||||
|
|
||||||
|
**Key Environment Variables:**
|
||||||
|
```bash
|
||||||
|
# API Servers
|
||||||
|
VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch
|
||||||
|
VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app
|
||||||
|
VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch
|
||||||
|
|
||||||
|
# Platform Configuration
|
||||||
|
VITE_PLATFORM=web|electron|capacitor
|
||||||
|
VITE_APP_SERVER=https://timesafari.app
|
||||||
|
|
||||||
|
# Feature Flags
|
||||||
|
VITE_PASSKEYS_ENABLED=true
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Build Output Structure
|
||||||
|
|
||||||
|
**Web Build:**
|
||||||
|
```
|
||||||
|
dist/
|
||||||
|
├── index.html # Main HTML file
|
||||||
|
├── assets/ # Bundled JavaScript/CSS
|
||||||
|
├── sw.js # Service worker (injected)
|
||||||
|
├── manifest.webmanifest # PWA manifest
|
||||||
|
└── wasm/ # SQLite WASM files
|
||||||
|
```
|
||||||
|
|
||||||
|
**Electron Build:**
|
||||||
|
```
|
||||||
|
electron/
|
||||||
|
├── app/ # Web assets
|
||||||
|
├── build/ # Compiled TypeScript
|
||||||
|
├── dist/ # Distribution packages
|
||||||
|
│ ├── TimeSafari.exe # Windows executable
|
||||||
|
│ ├── TimeSafari.dmg # macOS installer
|
||||||
|
│ ├── TimeSafari.AppImage # Linux AppImage
|
||||||
|
│ └── TimeSafari.deb # Debian package
|
||||||
|
└── node_modules/ # Dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 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.
|
||||||
|
|||||||
96
README.md
96
README.md
@@ -45,7 +45,7 @@ npm install
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
See [BUILDING.md](BUILDING.md) for more details.
|
See [BUILDING.md](BUILDING.md) for comprehensive build instructions for all platforms (Web, Electron, iOS, Android, Docker).
|
||||||
|
|
||||||
## Development Database Clearing
|
## Development Database Clearing
|
||||||
|
|
||||||
@@ -107,99 +107,6 @@ rm -rf ~/timesafari-dev-data
|
|||||||
|
|
||||||
See the script for complete platform-specific instructions.
|
See the script for complete platform-specific instructions.
|
||||||
|
|
||||||
## Build Systems
|
|
||||||
|
|
||||||
TimeSafari supports comprehensive build systems for all platforms with unified patterns and consistent tooling.
|
|
||||||
|
|
||||||
### **Quick Start Commands**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Web Development (starts dev server)
|
|
||||||
npm run build:web:dev
|
|
||||||
|
|
||||||
# Android Development (builds debug APK)
|
|
||||||
npm run build:android:dev
|
|
||||||
|
|
||||||
# iOS Development (builds debug app)
|
|
||||||
npm run build:ios:dev
|
|
||||||
|
|
||||||
# Electron Development (runs app directly)
|
|
||||||
npm run build:electron:dev
|
|
||||||
|
|
||||||
# Deploy Android to connected device
|
|
||||||
npm run build:android:deploy
|
|
||||||
|
|
||||||
# Deploy iOS to connected device
|
|
||||||
npm run build:ios:deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Platform-Specific Builds**
|
|
||||||
|
|
||||||
#### **Web Builds**
|
|
||||||
- **Development**: Hot reload server at http://localhost:8080
|
|
||||||
- **Production**: Optimized static files with PWA support
|
|
||||||
- **Docker**: Containerized deployment images
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build:web:dev # Development server
|
|
||||||
npm run build:web:prod # Production build
|
|
||||||
npm run build:web:docker:prod # Docker deployment
|
|
||||||
```
|
|
||||||
|
|
||||||
#### **Android Builds**
|
|
||||||
- **Development**: Debug APK with development optimizations
|
|
||||||
- **Production**: Release APK/AAB for app store distribution
|
|
||||||
- **Deployment**: Direct installation to connected devices
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build:android:dev # Development build
|
|
||||||
npm run build:android:prod # Production build
|
|
||||||
npm run build:android:deploy # Build and deploy to device
|
|
||||||
```
|
|
||||||
|
|
||||||
#### **iOS Builds**
|
|
||||||
- **Development**: Debug app with development optimizations
|
|
||||||
- **Production**: Release app/IPA for app store distribution
|
|
||||||
- **Deployment**: Direct installation to connected devices
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build:ios:dev # Development build
|
|
||||||
npm run build:ios:prod # Production build
|
|
||||||
npm run build:ios:deploy # Build and deploy to device
|
|
||||||
```
|
|
||||||
|
|
||||||
#### **Electron Builds**
|
|
||||||
- **Development**: Runs app directly for development
|
|
||||||
- **Packages**: Creates distributable executables
|
|
||||||
- **Cross-Platform**: Windows, macOS, Linux support
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build:electron:dev # Runs app directly
|
|
||||||
npm run build:electron:appimage:prod # Linux AppImage
|
|
||||||
npm run build:electron:dmg:prod # macOS DMG
|
|
||||||
npm run build:electron:deb:prod # Linux DEB
|
|
||||||
```
|
|
||||||
|
|
||||||
### **Build System Features**
|
|
||||||
|
|
||||||
- ✅ **Unified Environment Management**: Consistent dev/test/prod modes
|
|
||||||
- ✅ **PWA Support**: Progressive Web App functionality across platforms
|
|
||||||
- ✅ **Asset Generation**: Automatic icon and splash screen generation
|
|
||||||
- ✅ **Docker Integration**: Containerized deployment options
|
|
||||||
- ✅ **Performance Optimization**: Build-time and runtime optimizations
|
|
||||||
- ✅ **Error Handling**: Comprehensive error reporting and recovery
|
|
||||||
- ✅ **Legacy Compatibility**: Backward-compatible script aliases
|
|
||||||
|
|
||||||
### **Comprehensive Documentation**
|
|
||||||
|
|
||||||
- **[Build Systems Overview](docs/build-systems-overview.md)** - Complete guide to all build systems
|
|
||||||
- **[Web Build Scripts](docs/web-build-scripts.md)** - Web/PWA builds with Docker support
|
|
||||||
- **[Android Build Scripts](docs/android-build-scripts.md)** - Mobile builds with device deployment
|
|
||||||
- **[iOS Build Scripts](docs/ios-build-scripts.md)** - iOS builds with Xcode integration
|
|
||||||
- **[Electron Build Scripts](docs/electron-build-scripts.md)** - Desktop builds with package creation
|
|
||||||
- **[Database Clearing](docs/database-clearing.md)** - Development database management
|
|
||||||
- **[Build Troubleshooting](docs/build-troubleshooting.md)** - Comprehensive troubleshooting guide
|
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
See [TESTING.md](test-playwright/TESTING.md) for detailed test instructions.
|
See [TESTING.md](test-playwright/TESTING.md) for detailed test instructions.
|
||||||
@@ -252,7 +159,6 @@ The application uses a platform-agnostic database layer with Vue mixins for serv
|
|||||||
**Development Guidelines**:
|
**Development Guidelines**:
|
||||||
|
|
||||||
- Always use `PlatformServiceMixin` for database operations in components
|
- Always use `PlatformServiceMixin` for database operations in components
|
||||||
- Never import Dexie directly in application code
|
|
||||||
- Test with PlatformServiceMixin for new features
|
- Test with PlatformServiceMixin for new features
|
||||||
- Use migration tools for data transfer between systems
|
- Use migration tools for data transfer between systems
|
||||||
- Leverage mixin's ultra-concise methods: `$db()`, `$exec()`, `$one()`, `$contacts()`, `$settings()`
|
- Leverage mixin's ultra-concise methods: `$db()`, `$exec()`, `$one()`, `$contacts()`, `$settings()`
|
||||||
|
|||||||
Reference in New Issue
Block a user