diff --git a/.github/workflows/action_deploy_binaries.yml b/.github/workflows/action_deploy_binaries.yml
index 2a432158d..ed1ab0d00 100644
--- a/.github/workflows/action_deploy_binaries.yml
+++ b/.github/workflows/action_deploy_binaries.yml
@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
needs: [deploy-ios, deploy-maven]
steps:
- - uses: googleapis/release-please-action@v4
+ - uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1
if: ${{ !env.is_snapshot }}
with:
release-type: simple
@@ -27,11 +27,11 @@ jobs:
environment: production
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
@@ -53,11 +53,11 @@ jobs:
environment: production
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: '17'
@@ -76,8 +76,8 @@ jobs:
needs: [finalise]
if: ${{ github.ref_type != 'branch' }}
steps:
- - uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: '17'
@@ -89,7 +89,7 @@ jobs:
run: |
mv mockzilla/build/kotlin-webpack/js/developmentExecutable javascript_output
zip -r javascript_output.zip javascript_output
- - uses: svenstaro/upload-release-action@v2
+ - uses: svenstaro/upload-release-action@29e53e917877a24fad85510ded594ab3c9ca12de # v2.11.5
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: javascript_output.zip
diff --git a/.github/workflows/action_deploy_desktop_app.yml b/.github/workflows/action_deploy_desktop_app.yml
index 3d8d8953e..50b8be8e5 100644
--- a/.github/workflows/action_deploy_desktop_app.yml
+++ b/.github/workflows/action_deploy_desktop_app.yml
@@ -16,8 +16,8 @@ jobs:
environment: production
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
@@ -33,7 +33,7 @@ jobs:
- name: Build Jar
run: ./gradlew :mockzilla-management-ui:mockzilla-desktop:desktopJar
- name: Run Conveyor
- uses: hydraulic-software/conveyor/actions/build@v21.1
+ uses: hydraulic-software/conveyor/actions/build@fee92baf2a05a4539c3ef410eb04a82dca501797 # v21.1
env:
MAC_SIGNING_KEY_PASSWORD: ${{ secrets.MAC_SIGNING_KEY_PASSWORD }}
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
diff --git a/.github/workflows/action_deploy_docs.yml b/.github/workflows/action_deploy_docs.yml
index c47776be1..7a2c129bd 100644
--- a/.github/workflows/action_deploy_docs.yml
+++ b/.github/workflows/action_deploy_docs.yml
@@ -21,13 +21,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: ${{ github.event.workflow_run.head_branch }}
- - uses: actions/setup-python@v6
+ - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.x
- - uses: actions/setup-java@v5
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
@@ -36,10 +36,10 @@ jobs:
- run: bundle install
- run: bundle exec fastlane generate_docs
- name: Upload artifact
- uses: actions/upload-pages-artifact@v4
+ uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
with:
name: generated_docs
- path: './generated_docs'
+ path: './docs/site'
# Deployment job
deploy:
@@ -47,7 +47,7 @@ jobs:
runs-on: ubuntu-latest
needs: build
steps:
- - uses: actions/download-artifact@v7
+ - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
name: generated_docs
- name: Debug
run: |
@@ -55,7 +55,7 @@ jobs:
ls -l
tar -xf artifact.tar -C generated_docs
- name: Deploy
- uses: cloudflare/wrangler-action@v3
+ uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
diff --git a/.github/workflows/action_deploy_flutter.yml b/.github/workflows/action_deploy_flutter.yml
index 81be630c5..53911a8ac 100644
--- a/.github/workflows/action_deploy_flutter.yml
+++ b/.github/workflows/action_deploy_flutter.yml
@@ -11,7 +11,7 @@ jobs:
publish:
permissions:
id-token: write
- uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
+ uses: dart-lang/setup-dart/.github/workflows/publish.yml@65eb853c7ba17dde3be364c3d2858773e7144260 # v1.7.2
with:
working-directory: FlutterMockzilla/mockzilla
environment: production
\ No newline at end of file
diff --git a/.github/workflows/action_deploy_flutter_android.yml b/.github/workflows/action_deploy_flutter_android.yml
index 910b23541..6b884cbe3 100644
--- a/.github/workflows/action_deploy_flutter_android.yml
+++ b/.github/workflows/action_deploy_flutter_android.yml
@@ -11,7 +11,7 @@ jobs:
publish:
permissions:
id-token: write
- uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
+ uses: dart-lang/setup-dart/.github/workflows/publish.yml@65eb853c7ba17dde3be364c3d2858773e7144260 # v1.7.2
with:
working-directory: FlutterMockzilla/mockzilla_android
environment: production
\ No newline at end of file
diff --git a/.github/workflows/action_deploy_flutter_ios.yml b/.github/workflows/action_deploy_flutter_ios.yml
index 11111f762..f541464ad 100644
--- a/.github/workflows/action_deploy_flutter_ios.yml
+++ b/.github/workflows/action_deploy_flutter_ios.yml
@@ -11,7 +11,7 @@ jobs:
publish:
permissions:
id-token: write
- uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
+ uses: dart-lang/setup-dart/.github/workflows/publish.yml@65eb853c7ba17dde3be364c3d2858773e7144260 # v1.7.2
with:
working-directory: FlutterMockzilla/mockzilla_ios
environment: production
\ No newline at end of file
diff --git a/.github/workflows/action_deploy_flutter_platform_interface.yml b/.github/workflows/action_deploy_flutter_platform_interface.yml
index d009d0a08..08f6c5727 100644
--- a/.github/workflows/action_deploy_flutter_platform_interface.yml
+++ b/.github/workflows/action_deploy_flutter_platform_interface.yml
@@ -11,7 +11,7 @@ jobs:
publish:
permissions:
id-token: write
- uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
+ uses: dart-lang/setup-dart/.github/workflows/publish.yml@65eb853c7ba17dde3be364c3d2858773e7144260 # v1.7.2
with:
working-directory: FlutterMockzilla/mockzilla_platform_interface
environment: production
\ No newline at end of file
diff --git a/.github/workflows/action_deploy_flutter_web.yml b/.github/workflows/action_deploy_flutter_web.yml
index 29172ab97..c09339806 100644
--- a/.github/workflows/action_deploy_flutter_web.yml
+++ b/.github/workflows/action_deploy_flutter_web.yml
@@ -14,7 +14,7 @@ jobs:
id-token: write
environment: production
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Install dependencies
run: bundle install
- name: Download JS assets
@@ -23,8 +23,8 @@ jobs:
bundle exec fastlane download_mockzilla_js_assets
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- - uses: dart-lang/setup-dart@v1
- - uses: subosito/flutter-action@v2
+ - uses: dart-lang/setup-dart@65eb853c7ba17dde3be364c3d2858773e7144260 # v1.7.2
+ - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: '3.41.9'
channel: 'stable'
diff --git a/.github/workflows/action_deploy_mobile_ui_binaries.yml b/.github/workflows/action_deploy_mobile_ui_binaries.yml
index da56e24ca..ac46888d2 100644
--- a/.github/workflows/action_deploy_mobile_ui_binaries.yml
+++ b/.github/workflows/action_deploy_mobile_ui_binaries.yml
@@ -20,7 +20,7 @@ jobs:
permissions:
id-token: write
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Install dependencies
run: bundle install
- name: Download JS assets
@@ -29,8 +29,8 @@ jobs:
bundle exec fastlane download_mockzilla_ui_mobile_js_assets
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- - uses: dart-lang/setup-dart@v1
- - uses: subosito/flutter-action@v2
+ - uses: dart-lang/setup-dart@65eb853c7ba17dde3be364c3d2858773e7144260 # v1.7.2
+ - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: '3.41.9'
channel: 'stable'
@@ -41,7 +41,7 @@ jobs:
needs: [deploy-flutter]
runs-on: macos-26
steps:
- - uses: googleapis/release-please-action@v4
+ - uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1
with:
if: ${{ !env.is_snapshot }}
release-type: simple
@@ -49,11 +49,11 @@ jobs:
pre-deploy-checks:
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
@@ -70,11 +70,11 @@ jobs:
runs-on: macos-26
needs: [pre-deploy-checks]
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
@@ -92,11 +92,11 @@ jobs:
runs-on: macos-26
needs: [pre-deploy-checks]
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
@@ -119,8 +119,8 @@ jobs:
needs: [ deploy-kotlin, deploy-swift]
if: ${{ github.ref_type != 'branch' }}
steps:
- - uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: '17'
@@ -132,7 +132,7 @@ jobs:
run: |
mv mockzilla-management-ui/mockzilla-mobile-ui/build/kotlin-webpack/js/developmentExecutable javascript_output
zip -r javascript_output.zip javascript_output
- - uses: svenstaro/upload-release-action@v2
+ - uses: svenstaro/upload-release-action@29e53e917877a24fad85510ded594ab3c9ca12de # v2.11.5
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: javascript_output.zip
diff --git a/.github/workflows/action_pull_request.yml b/.github/workflows/action_pull_request.yml
index eb7c79eac..6fb5e788d 100644
--- a/.github/workflows/action_pull_request.yml
+++ b/.github/workflows/action_pull_request.yml
@@ -35,10 +35,10 @@ jobs:
sample-kmm: ${{ steps.filter.outputs.sample-kmm }}
swagger: ${{ steps.filter.outputs.swagger }}
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
- - uses: dorny/paths-filter@v3
+ - uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3.0.3
id: filter
with:
filters: |
@@ -46,7 +46,7 @@ jobs:
- fastlane/Appfile
- Gemfile
- Gemfile.lock
- - .github/workflows/**
+ - .github/workflows/action_pull_request.yml
common-kotlin: &common-kotlin
- *common-fastlane
- build-logic/**
@@ -94,11 +94,11 @@ jobs:
if: needs.filter.outputs.docs == 'true'
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v6
- - uses: actions/setup-python@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.x
- - uses: ruby/setup-ruby@v1
+ - uses: ruby/setup-ruby@12fd324f1d0b43274fdc8130f6980590a667c455 # v1.312.0
with:
ruby-version: 3.4
- name: Setup fastlane
@@ -116,11 +116,11 @@ jobs:
if: needs.filter.outputs.flutter == 'true'
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
- - uses: subosito/flutter-action@v2
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
with:
flutter-version: '3.41.9'
channel: 'stable'
@@ -136,11 +136,11 @@ jobs:
if: needs.filter.outputs.mockzilla-server == 'true'
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: '17'
@@ -158,10 +158,10 @@ jobs:
if: needs.filter.outputs.mockzilla-management == 'true'
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Setup fastlane
run: bundle install
- name: Build Management Library
@@ -172,10 +172,10 @@ jobs:
if: needs.filter.outputs.mockzilla-management-ui == 'true'
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Setup fastlane
run: bundle install
- name: Build Management UI
@@ -186,10 +186,10 @@ jobs:
if: needs.filter.outputs.swift-mockzilla == 'true'
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Setup fastlane
run: bundle install
- name: Build SwiftMockzilla
@@ -200,10 +200,10 @@ jobs:
if: needs.filter.outputs.sample-android == 'true'
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Setup fastlane
run: bundle install
- name: Build Sample Android
@@ -214,10 +214,10 @@ jobs:
if: needs.filter.outputs.sample-ios == 'true'
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Setup fastlane
run: bundle install
- name: Build Sample iOS
@@ -228,10 +228,10 @@ jobs:
if: needs.filter.outputs.sample-kmm == 'true'
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Setup fastlane
run: bundle install
- name: Build Sample KMM
@@ -242,10 +242,10 @@ jobs:
if: needs.filter.outputs.sample-kmm == 'true'
runs-on: macos-26
steps:
- - uses: maxim-lobanov/setup-xcode@v1
+ - uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.2.0'
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Setup fastlane
run: bundle install
- name: Build Sample KMM
@@ -257,9 +257,9 @@ jobs:
if: needs.filter.outputs.swagger == 'true'
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Validate Swagger
- uses: mbowman100/swagger-validator-action@2.0
+ uses: mbowman100/swagger-validator-action@9da850f22c24a4a9f0120e0d38518262b5a3afc6 # 2.0
with:
files: webapi.yaml
diff --git a/.github/workflows/action_release_please.yml b/.github/workflows/action_release_please.yml
index a8faee1f6..4a3d79360 100644
--- a/.github/workflows/action_release_please.yml
+++ b/.github/workflows/action_release_please.yml
@@ -14,7 +14,7 @@ jobs:
release-please:
runs-on: ubuntu-latest
steps:
- - uses: googleapis/release-please-action@v4
+ - uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1
id: release
with:
token: ${{ secrets.PAT_BS }}
\ No newline at end of file
diff --git a/.github/workflows/action_trigger_kmp_snapshot.yml b/.github/workflows/action_trigger_kmp_snapshot.yml
index 3a76587de..2f868f99d 100644
--- a/.github/workflows/action_trigger_kmp_snapshot.yml
+++ b/.github/workflows/action_trigger_kmp_snapshot.yml
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
name: Check if snapshot is needed
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: release-please--branches--develop--groups--Kmp-libs
- name: Decide if snapshot should fire
diff --git a/.gitignore b/.gitignore
index c9bf9ebc3..b8703f38f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@ generated_docs/*
.kotlin
docs/__pycache__/
docs/site
+docs/docs/overrides/homepage-content.html
**/.gradle/**
**/build/**
**/.idea/**
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index fac764f5c..324153fb4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,39 +1,73 @@
# Contributing
+Want to help? Great! 🙌 Work is driven by GitHub Issues, so that's the best place to start.
+
+## Tree Hygiene
+
+This project follows a **Gitflow** feature branching model. Please also use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) so others can scan the tree and understand changes at a glance. Pull requests for feature branches target the `develop` branch and once reviewed by a maintainer, will have their commits squashed for tidiness.
+
## Repo Structure
```
-|- fastlane. : Build scripts and configuration
-|- samples : Sample apps demonstrating usage of Mockzilla
-|- mockzilla : The directory forming the core Mockzilla KMM module
-|- mockzilla-common: Common utilities used by multiple other modules
-|- mockzilla-management: A kotlin wrapper around the http apis defined in `mockzilla`
-|- mockzilla-management-ui: Compose multiplatform app used to maniplulate mockzilla at runtime
-|- SwiftMockzilla : The directory forming the SPM package
-|- FlutterMockzilla: The directory containing the federated Flutter plugin
-
+|- fastlane : Build scripts and configuration
+|- samples : Sample apps demonstrating usage of Mockzilla
+|- mockzilla : The core Mockzilla KMP module
+|- mockzilla-common : Common utilities shared across modules
+|- mockzilla-management : Kotlin wrapper around the HTTP APIs defined in `mockzilla`
+|- mockzilla-management-ui : Compose Multiplatform management UI
+| |- mockzilla-desktop : Desktop app
+| |- mockzilla-mobile-ui : Mobile management UI (Android/iOS)
+| |- mockzilla-management-ui-common : Shared UI code
+|- SwiftMockzilla : The SPM package
+|- SwiftMockzillaMobileUi : Swift management UI for mobile
+|- FlutterMockzilla : The federated Flutter plugin
+|- js-scripts : Web/JS support scripts
```
## Issues
-All work is tracked using Github Issues. Before starting please ensure you create an Issue associated with your work if one does not exist.
+All work is tracked using GitHub Issues. Before diving in, make sure there's an issue linked to your work — create one if it doesn't exist yet.
[https://github.com/Apadmi-Engineering/Mockzilla/issues](https://github.com/Apadmi-Engineering/Mockzilla/issues)
## Write your code!
-For guidance on contributing to the Flutter packages, please checkout the [Flutter README](https://github.com/Apadmi-Engineering/Mockzilla/tree/develop/FlutterMockzilla).
+For guidance on contributing to the Flutter packages, please check out the [Flutter README](https://github.com/Apadmi-Engineering/Mockzilla/tree/develop/FlutterMockzilla).
-1. Checkout the tests. The library is setup with TDD in mind, we recommend writing your tests first!
+1. Check out the tests. The library is set up with TDD in mind — we recommend writing your tests first!
2. Implement your feature/bugfix!
-### Testing through the demo apps.
+### Testing through the demo apps
It's a good idea to sanity check your work by using the library through the demo apps.
-Open the root of this repo in Android Studio and run the `samples.demo-kmm.AndroidApp` or `samples.demo-android` targets. The KMM iOS app can also be run through XCode as normal.
+Open the root of this repo in Android Studio and run the `samples.demo-kmm.AndroidApp` or `samples.demo-android` targets. The KMM iOS app can also be run through Xcode as normal.
+
Note: Currently there's no way to test the Swift package locally without it first being deployed.
+## Internal API (`@InternalMockzillaApi`)
+
+Some types must be `public` because they are shared across library modules (e.g. DTOs used by both `mockzilla` and `mockzilla-management`), but they are **not intended for use by external consumers**.
+
+These are annotated with `@InternalMockzillaApi` (defined in `mockzilla-common`). The annotation is a `@RequiresOptIn` at the `ERROR` level, so consumers who accidentally reference an internal type will get a compile-time error.
+
+**When to apply it:** Any public declaration (class, interface, function, property) that lives in a `*.internal.*` package.
+
+**When NOT to apply it:**
+- Swift/Objective-C interop entry points (e.g. `AsyncUtils.kt`, `NestedClassBridgeGeneration.kt` on iOS) — Swift has no way to satisfy `@OptIn` requirements, so annotating these would break the Swift bridge.
+- `@JsExport` declarations in `jsinterface/JsInterface.kt` — these are intentionally public JS API even though they happen to live in an `internal` package.
+- Declarations that already have the Kotlin `internal` visibility modifier — the compiler already prevents access, so no annotation is needed (`private` and `internal` Kotlin modifiers should be preferred if they're possible).
+
+**How library modules opt in:** All modules in this repo are inside the internal-API boundary. Rather than adding `@file:OptIn` to every file, each module's `build.gradle.kts` opts in at the module level:
+
+```kotlin
+compilerOptions {
+ freeCompilerArgs.add("-opt-in=com.apadmi.mockzilla.lib.InternalMockzillaApi")
+}
+```
+
+**For `expect`/`actual` declarations:** The annotation must be present on both the `expect` declaration and **every** `actual` declaration across all platforms. Missing one platform will cause a compile error.
+
## Spotless
We use Spotless to reformat and organise all of our library code. It runs automatically on compilation so please ensure you've compiled your code before submitting a pull request.
@@ -47,6 +81,4 @@ Creating a pull request will check everything compiles and runs all your tests.
This section is specifically for Apadmi maintainers creating releases.
1. Releases are all managed automatically. To release a new version, merge the open release pull request as described here: [https://github.com/google-github-actions/release-please-action](https://github.com/google-github-actions/release-please-action).
-2. Deploy the release to maven central from [https://s01.oss.sonatype.org/#stagingRepositories](https://s01.oss.sonatype.org/#stagingRepositories).
-
-
+2. Deploy the release to Maven Central from [https://s01.oss.sonatype.org/#stagingRepositories](https://s01.oss.sonatype.org/#stagingRepositories).
diff --git a/Gemfile b/Gemfile
index 8cfaf04eb..855888fb4 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,6 @@
source "https://rubygems.org"
-gem "fastlane", '~> 2.234.0'
+gem "fastlane", '~> 2.236.1'
gem "fastlane-plugin-screenshotbot", '~> 1.0.0'
gem 'fastlane-plugin-apadmi_grout', '~> 3.0.2'
gem 'fastlane-plugin-flutter', '~> 0.8.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 9ae02f164..e70d35fb1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -30,8 +30,8 @@ GEM
auth-sanitizer (0.1.4)
version_gem (~> 1.1, >= 1.1.9)
aws-eventstream (1.4.0)
- aws-partitions (1.1247.0)
- aws-sdk-core (3.247.0)
+ aws-partitions (1.1260.0)
+ aws-sdk-core (3.252.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
@@ -39,11 +39,11 @@ GEM
bigdecimal
jmespath (~> 1, >= 1.6.1)
logger
- aws-sdk-kms (1.125.0)
- aws-sdk-core (~> 3, >= 3.247.0)
+ aws-sdk-kms (1.129.0)
+ aws-sdk-core (~> 3, >= 3.248.0)
aws-sigv4 (~> 1.5)
- aws-sdk-s3 (1.222.0)
- aws-sdk-core (~> 3, >= 3.247.0)
+ aws-sdk-s3 (1.225.1)
+ aws-sdk-core (~> 3, >= 3.248.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.12.1)
@@ -95,7 +95,7 @@ GEM
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
- concurrent-ruby (1.3.6)
+ concurrent-ruby (1.3.7)
connection_pool (3.0.2)
csv (3.3.5)
declarative (0.0.20)
@@ -139,7 +139,7 @@ GEM
faraday_middleware (1.2.1)
faraday (~> 1.0)
fastimage (2.4.1)
- fastlane (2.234.0)
+ fastlane (2.236.1)
CFPropertyList (>= 2.3, < 5.0.0)
abbrev (~> 0.1)
addressable (>= 2.8, < 3.0.0)
@@ -148,7 +148,7 @@ GEM
babosa (>= 1.0.3, < 2.0.0)
base64 (~> 0.2)
benchmark (>= 0.1.0)
- bundler (>= 1.17.3, < 5.0.0)
+ bundler (>= 2.4.0, < 5.0.0)
colored (~> 1.2)
commander (~> 4.6)
csv (~> 3.3)
@@ -163,14 +163,15 @@ GEM
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
- google-cloud-env (>= 1.6.0, <= 2.1.1)
+ google-cloud-env (>= 1.6.0, < 2.3.0)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
- jwt (>= 2.1.0, < 3)
+ jwt (>= 2.10.3, < 4)
logger (>= 1.6, < 2.0)
mini_magick (>= 4.9.4, < 5.0.0)
+ multi_json (~> 1.12)
multipart-post (>= 2.0.0, < 3.0.0)
mutex_m (~> 0.3)
naturally (~> 2.2)
@@ -209,7 +210,7 @@ GEM
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
- google-apis-androidpublisher_v3 (0.100.0)
+ google-apis-androidpublisher_v3 (0.102.0)
google-apis-core (>= 0.15.0, < 2.a)
google-apis-core (0.18.0)
addressable (~> 2.5, >= 2.5.1)
@@ -223,15 +224,16 @@ GEM
google-apis-core (>= 0.15.0, < 2.a)
google-apis-playcustomapp_v1 (0.17.0)
google-apis-core (>= 0.15.0, < 2.a)
- google-apis-storage_v1 (0.62.0)
+ google-apis-storage_v1 (0.63.0)
google-apis-core (>= 0.15.0, < 2.a)
- google-cloud-core (1.8.0)
+ google-cloud-core (1.9.0)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
- google-cloud-env (2.1.1)
+ google-cloud-env (2.2.2)
+ base64 (~> 0.2)
faraday (>= 1.0, < 3.a)
google-cloud-errors (1.6.0)
- google-cloud-storage (1.60.0)
+ google-cloud-storage (1.61.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-core (>= 0.18, < 2)
@@ -240,12 +242,14 @@ GEM
google-cloud-core (~> 1.6)
googleauth (~> 1.9)
mini_mime (~> 1.0)
- googleauth (1.11.2)
+ google-logging-utils (0.2.0)
+ googleauth (1.17.0)
faraday (>= 1.0, < 3.a)
- google-cloud-env (~> 2.1)
- jwt (>= 1.4, < 3.0)
- multi_json (~> 1.11)
+ google-cloud-env (~> 2.2)
+ google-logging-utils (~> 0.1)
+ jwt (>= 1.4, < 4.0)
os (>= 0.9, < 2.0)
+ pstore (~> 0.1)
signet (>= 0.16, < 2.a)
hashie (5.1.0)
logger
@@ -263,8 +267,8 @@ GEM
multipart-post
oauth (~> 1.0)
jmespath (1.6.2)
- json (2.19.5)
- jwt (2.10.3)
+ json (2.19.9)
+ jwt (3.2.0)
base64
logger (1.7.0)
mini_magick (4.13.2)
@@ -279,7 +283,7 @@ GEM
nap (1.1.0)
naturally (2.3.0)
netrc (0.11.0)
- nkf (0.2.0)
+ nkf (0.3.0)
oauth (1.1.5)
auth-sanitizer (~> 0.1, >= 0.1.3)
base64 (~> 0.1)
@@ -295,13 +299,14 @@ GEM
os (1.1.4)
ostruct (0.6.3)
plist (3.7.2)
+ pstore (0.2.1)
public_suffix (4.0.7)
rake (13.4.2)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
- retriable (3.4.1)
+ retriable (3.8.0)
rexml (3.4.4)
rouge (3.28.0)
ruby-macho (2.5.1)
@@ -310,11 +315,10 @@ GEM
securerandom (0.4.1)
security (0.1.5)
semantic (1.5.0)
- signet (0.21.0)
+ signet (0.22.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 4.0)
- multi_json (~> 1.10)
simctl (1.6.10)
CFPropertyList
naturally
@@ -364,7 +368,7 @@ PLATFORMS
DEPENDENCIES
cocoapods (~> 1.16.2)
- fastlane (~> 2.234.0)
+ fastlane (~> 2.236.1)
fastlane-plugin-apadmi_grout (~> 3.0.2)
fastlane-plugin-flutter (~> 0.8.0)
fastlane-plugin-screenshotbot (~> 1.0.0)
@@ -380,16 +384,16 @@ CHECKSUMS
atomos (0.1.3) sha256=7d43b22f2454a36bace5532d30785b06de3711399cb1c6bf932573eda536789f
auth-sanitizer (0.1.4) sha256=ded72221d4d3a7c91e34e8a87b21e6a42cbf7829697f140dcf49d542422faedc
aws-eventstream (1.4.0) sha256=116bf85c436200d1060811e6f5d2d40c88f65448f2125bc77ffce5121e6e183b
- aws-partitions (1.1247.0) sha256=0461b97f905e8cfc346bb6e57668e916c46b8f4b7c2eb5eedad005368403715f
- aws-sdk-core (3.247.0) sha256=789864594ce8cef05ee3d81fa8ed506099280bda6ea12a7612b8b7c5e5e62851
- aws-sdk-kms (1.125.0) sha256=23f81bc0838ae6ec2e8de3eae88af521d0e29d3a59b6c9dbb4b21343ba476bc8
- aws-sdk-s3 (1.222.0) sha256=bae4b06fccf0b81b8d77e7abfc56e5e2146590d43c4ab58db0cee3ff5bbfb7f1
+ aws-partitions (1.1260.0) sha256=045aff79be010126538f39e03141088e1fd2428d2d065e220e7fb3c3ba2b337a
+ aws-sdk-core (3.252.0) sha256=09c042cbfc2acf2239441cc9b982ebab2a999bed2ef6bdc51849e7b3d6e48a1c
+ aws-sdk-kms (1.129.0) sha256=363f548df321f4a4fcfd05523384e591060b400f8e65133ed7ef0793155a3343
+ aws-sdk-s3 (1.225.1) sha256=d4b23a8db9b0a5548766b52d382b184f47f7e126560acdb731dd46adb5e26512
aws-sigv4 (1.12.1) sha256=6973ff95cb0fd0dc58ba26e90e9510a2219525d07620c8babeb70ef831826c00
babosa (1.0.4) sha256=18dea450f595462ed7cb80595abd76b2e535db8c91b350f6c4b3d73986c5bc99
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
benchmark (0.5.0) sha256=465df122341aedcb81a2a24b4d3bd19b6c67c1530713fd533f3ff034e419236c
bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
- bundler (4.0.12) sha256=7f8b757d28dfb636e7b24fba2344ac6dd13b5b24f4b46d62573d483f211825ac
+ bundler (4.0.14) sha256=d09a0a965cf772266a7e49e83610be7c2f4e49e61134c42a56804bb383cc24b8
cgi (0.5.1) sha256=e93fcafc69b8a934fe1e6146121fa35430efa8b4a4047c4893764067036f18e9
claide (1.1.0) sha256=6d3c5c089dde904d96aa30e73306d0d4bd444b1accb9b3125ce14a3c0183f82e
cocoapods (1.16.2) sha256=0ff1c860f32df3db8b16df09b58da1a6bb2a12fe55f6d5e8be994a74fadd1e5e
@@ -403,7 +407,7 @@ CHECKSUMS
colored (1.2) sha256=9d82b47ac589ce7f6cab64b1f194a2009e9fd00c326a5357321f44afab2c1d2c
colored2 (3.1.2) sha256=b13c2bd7eeae2cf7356a62501d398e72fde78780bd26aec6a979578293c28b4a
commander (4.6.0) sha256=7d1ddc3fccae60cc906b4131b916107e2ef0108858f485fdda30610c0f2913d9
- concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
+ concurrent-ruby (1.3.7) sha256=4412caec3a5ea2e5fdc52076724c071a81f2c0593d83b2ac8cbb8ca63b3151b0
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
csv (3.3.5) sha256=6e5134ac3383ef728b7f02725d9872934f523cb40b961479f69cf3afa6c8e73f
declarative (0.0.20) sha256=8021dd6cb17ab2b61233c56903d3f5a259c5cf43c80ff332d447d395b17d9ff9
@@ -429,7 +433,7 @@ CHECKSUMS
faraday-retry (1.0.4) sha256=dc659233777fabf96c69c2ffe56c0a5d2c102af90321a42cc6c90157bcd716aa
faraday_middleware (1.2.1) sha256=d45b78c8ee864c4783fbc276f845243d4a7918a67301c052647bacabec0529e9
fastimage (2.4.1) sha256=c64bebd46b6fd8943ab70c1e6e85ff728f970f2e48f92ecd249b6bc3a540ad20
- fastlane (2.234.0) sha256=b74835681ad9a8e9c0931a5727dad1bab433895ac534c864a1ed5749625d26e9
+ fastlane (2.236.1) sha256=fb89e618e0f38636e487743622cf710ad722723f5d33a63f19e367f84d3770bc
fastlane-plugin-apadmi_grout (3.0.2) sha256=387bd36d01b2d0582fe7c41a368c0fb826c461a597681ffc659b0a38aa632576
fastlane-plugin-flutter (0.8.0) sha256=84c6196da06431b089c1f97c4dd4838ce03d89869e15849c51e9a51b567ed39e
fastlane-plugin-screenshotbot (1.0.0) sha256=fe5d6f9bd256bbb94de418c2ebdba0af4d861efb248c78219e0b6faa644c9c71
@@ -448,16 +452,17 @@ CHECKSUMS
fourflusher (2.3.1) sha256=1b3de61c7c791b6a4e64f31e3719eb25203d151746bb519a0292bff1065ccaa9
fuzzy_match (2.0.4) sha256=b5de4f95816589c5b5c3ad13770c0af539b75131c158135b3f3bbba75d0cfca5
gh_inspector (1.1.3) sha256=04cca7171b87164e053aa43147971d3b7f500fcb58177698886b48a9fc4a1939
- google-apis-androidpublisher_v3 (0.100.0) sha256=7a82935bee985190e8fe23bf5e53df3a27d65dd084114bb71b846b617de16489
+ google-apis-androidpublisher_v3 (0.102.0) sha256=562415c44bd7f81cc808abbea11845ede16cdc3696d95f95efcf50aaffb159cf
google-apis-core (0.18.0) sha256=96b057816feeeab448139ed5b5c78eab7fc2a9d8958f0fbc8217dedffad054ee
google-apis-iamcredentials_v1 (0.27.0) sha256=9289f29968610754ef11d98b9ec627f0153f3e2616fef839aef096de529f6d1e
google-apis-playcustomapp_v1 (0.17.0) sha256=d5bc90b705f3f862bab4998086449b0abe704ee1685a84821daa90ca7fa95a78
- google-apis-storage_v1 (0.62.0) sha256=f62467c36df53287fb0252ebb4da85f9e25d7b4c5809d045c2aab1fc307760c1
- google-cloud-core (1.8.0) sha256=e572edcbf189cfcab16590628a516cec3f4f63454b730e59f0b36575120281cf
- google-cloud-env (2.1.1) sha256=cf4bb8c7d517ee1ea692baedf06e0b56ce68007549d8d5a66481aa9f97f46999
+ google-apis-storage_v1 (0.63.0) sha256=7063a6c19c40f5ef96d5894df33c4f9ac915e3107e632b1870ba5247e3bb633f
+ google-cloud-core (1.9.0) sha256=ab55409f51488e8deefb6edcc1ce4771dfb5da2fe7b3bc075709a030c2b682a4
+ google-cloud-env (2.2.2) sha256=94bed40e05a67e9468ce1cb38389fba9a90aa8fc62fc9e173204c1dca59e21e7
google-cloud-errors (1.6.0) sha256=1da8476dd706ad04b9d32e3c4b90d07d3463b37d6407cb56d41342ea7647d0a1
- google-cloud-storage (1.60.0) sha256=b21b752d37945d678a4533be5ef4303f15d33a964d8bc709c7c41c3600f650db
- googleauth (1.11.2) sha256=7e6bacaeed7aea3dd66dcea985266839816af6633e9f5983c3c2e0e40a44731e
+ google-cloud-storage (1.61.0) sha256=a77f10f4a603289948b09e81c3e23d762a18733fd69d70a4c1399663fbd96002
+ google-logging-utils (0.2.0) sha256=675462b4ea5affa825a3442694ca2d75d0069455a1d0956127207498fca3df7b
+ googleauth (1.17.0) sha256=dbddcaa3b78469fa9392c0e784ab6d8f3f760a1e5f6c6dbbbaa44a612c4198b0
hashie (5.1.0) sha256=c266471896f323c446ea8207f8ffac985d2718df0a0ba98651a3057096ca3870
highline (2.0.3) sha256=2ddd5c127d4692721486f91737307236fe005352d12a4202e26c48614f719479
http-cookie (1.0.8) sha256=b14fe0445cf24bf9ae098633e9b8d42e4c07c3c1f700672b09fbfe32ffd41aa6
@@ -465,8 +470,8 @@ CHECKSUMS
i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5
jira-ruby (3.2.0) sha256=3da8fbb2e5ea9787a45bd8a27c455532a0371c808bc7ec1e5303ec3c1bf58ee9
jmespath (1.6.2) sha256=238d774a58723d6c090494c8879b5e9918c19485f7e840f2c1c7532cf84ebcb1
- json (2.19.5) sha256=218a18553e4801d579ca7e0f5bc72bafd776d7397238a1fb4e74db5b0a812c59
- jwt (2.10.3) sha256=e4d9352fbc7309b1a7448c7dd713dfe4d8c47077af80759cdbed8f878ea0b484
+ json (2.19.9) sha256=9b9025b7cdddafa38d316eca0b2358488e42d417045c1b90d216a9fefe46b79a
+ jwt (3.2.0) sha256=5419b1fe37b1da0982bd07051f573a8b8789ab724c2aa7e785e4784a3ed217d7
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
mini_magick (4.13.2) sha256=71d6258e0e8a3d04a9a0a09784d5d857b403a198a51dd4f882510435eb95ddd9
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
@@ -480,17 +485,18 @@ CHECKSUMS
nap (1.1.0) sha256=949691660f9d041d75be611bb2a8d2fd559c467537deac241f4097d9b5eea576
naturally (2.3.0) sha256=459923cf76c2e6613048301742363200c3c7e4904c324097d54a67401e179e01
netrc (0.11.0) sha256=de1ce33da8c99ab1d97871726cba75151113f117146becbe45aa85cb3dabee3f
- nkf (0.2.0) sha256=fbc151bda025451f627fafdfcb3f4f13d0b22ae11f58c6d3a2939c76c5f5f126
+ nkf (0.3.0) sha256=357a8dbeba38b727b75930f665146546076a394a1c243faf634ff176e3588895
oauth (1.1.5) sha256=0ec467908f5819a54d1659d33e8bb520e8475cc87a452d6ecfaa5db351999cca
oauth-tty (1.0.8) sha256=d9a63b67af17c22517f868c59f12178e4ee19a367536d1a6dcb74d9d07a41e07
optparse (0.8.1) sha256=42bea10d53907ccff4f080a69991441d611fbf8733b60ed1ce9ee365ce03bd1a
os (1.1.4) sha256=57816d6a334e7bd6aed048f4b0308226c5fb027433b67d90a9ab435f35108d3f
ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912
plist (3.7.2) sha256=d37a4527cc1116064393df4b40e1dbbc94c65fa9ca2eec52edf9a13616718a42
+ pstore (0.2.1) sha256=03904d0f2c66579e96d1e6704cdabc0c88df7ea8ed8782d9f3569f6f6c702c1a
public_suffix (4.0.7) sha256=8be161e2421f8d45b0098c042c06486789731ea93dc3a896d30554ee38b573b8
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
representable (3.2.0) sha256=cc29bf7eebc31653586849371a43ffe36c60b54b0a6365b5f7d95ec34d1ebace
- retriable (3.4.1) sha256=fb3f114b7d492121c158c01f3d5152b5a615c5b70d5877d0bc08c7ec3725c3bc
+ retriable (3.8.0) sha256=9f2f1b0207594c7817f17f671587b8ec7587387ac6cebda6c941a802bb98a8e5
rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142
rouge (3.28.0) sha256=0d6de482c7624000d92697772ab14e48dca35629f8ddf3f4b21c99183fd70e20
ruby-macho (2.5.1) sha256=9075e52e0f9270b552a90b24fcc6219ad149b0d15eae1bc364ecd0ac8984f5c9
@@ -499,7 +505,7 @@ CHECKSUMS
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
security (0.1.5) sha256=3a977a0eca7706e804c96db0dd9619e0a94969fe3aac9680fcfc2bf9b8a833b7
semantic (1.5.0) sha256=2e44c885bbf25d6f886358d519265f6aa316716a51a8949bbd7a7ed912db234f
- signet (0.21.0) sha256=d617e9fbf24928280d39dcfefba9a0372d1c38187ffffd0a9283957a10a8cd5b
+ signet (0.22.0) sha256=b76d495ccb07ad35dbc89f3e920665a9d8ed717141955034005d7843dcfe4780
simctl (1.6.10) sha256=b99077f4d13ad81eace9f86bf5ba4df1b0b893a4d1b368bd3ed59b5b27f9236b
snaky_hash (2.0.4) sha256=2b12758c57defa6796341a1620f84b1a23737421d8d7e2575d0550b53cc4fece
terminal-notifier (2.0.0) sha256=7a0d2b2212ab9835c07f4b2e22a94cff64149dba1eed203c04835f7991078cea
diff --git a/build-logic/src/main/kotlin/com/apadmi/mockzilla/MobileUiConfig.kt b/build-logic/src/main/kotlin/com/apadmi/mockzilla/MobileUiConfig.kt
index 602b225aa..f2df33c24 100644
--- a/build-logic/src/main/kotlin/com/apadmi/mockzilla/MobileUiConfig.kt
+++ b/build-logic/src/main/kotlin/com/apadmi/mockzilla/MobileUiConfig.kt
@@ -3,7 +3,7 @@ package com.apadmi.mockzilla
import org.gradle.api.Project
object MobileUiConfig {
- const val coreVersionForManagementUi = "3.0.0-alpha2"
+ const val coreVersionForManagementUi = "to be updated during release"
}
fun Project.isMobileUiDeployBuild() = properties["is_building_for_deployment"].toString().toBoolean()
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 000000000..19852566d
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,2 @@
+.venv
+homepage/dist-ssr
\ No newline at end of file
diff --git a/docs/docs/browser_stack.md b/docs/docs/browser_stack.md
index f48632ca9..710c78782 100644
--- a/docs/docs/browser_stack.md
+++ b/docs/docs/browser_stack.md
@@ -12,7 +12,6 @@ Browserstack seems to proxy local traffic by default. In your client app you'll
```kotlin
OkHttpClient.Builder()
.proxy(Proxy.NO_PROXY)
- .protocols(listOf(Protocol.HTTP_1_1)).build()
```
### Ktor Example:
diff --git a/docs/docs/documentation.md b/docs/docs/documentation.md
index 5bee95154..c59149082 100644
--- a/docs/docs/documentation.md
+++ b/docs/docs/documentation.md
@@ -1,17 +1,17 @@
-This documentation is primarily built using [MkDocs](https://www.mkdocs.org/)
-with the [Material theme](https://squidfunk.github.io/mkdocs-material/).
+This documentation is built using [Zensical](https://zensical.org/), a modern static site
+generator by the team behind Material for MkDocs.
-**Their documentation is brilliant so please check their docs if this is not sufficient.**
+**Their documentation is great so check it if this is not sufficient.**
## Working on the HomePage
-The homepage is a separate React site which is included in the MkDocs site.
+The homepage is a separate React site which is included in the Zensical site.
-In your IDE of choice open `docs/homepage` and treat it as regular standalone react site.
+In your IDE of choice open `docs/homepage` and treat it as a regular standalone React site.
Install dependencies with `npm install` and run it with `npm run dev`.
-Note: Run `npm run build` to get your updates to the homepage reflected in the mkdocs site locally.
+Note: Run `npm run build:fragment` (or `./serve.sh`) to get your updates to the homepage reflected in the docs site locally.
## Working on the rest of the documentation
@@ -31,7 +31,11 @@ Tested on python `v{{get_python_version()}}`
```bash
# Install all dependencies
+python3 -m venv .venv
+source .venv/bin/activate
+
pip install -r requirements.txt
+cd homepage && npm install
```
Run the following to start the server.
@@ -40,13 +44,13 @@ This supports hot reloading so updating the docs should
automatically reload the docs in your browser.
```bash
-mkdocs serve
+./serve.sh
```
## Macros
-The docs also uses the [mkdocs-macros](https://mkdocs-macros-plugin.readthedocs.io/en/latest/) plugin.
-This lets us call out to python code (and a load of other features) from within markdown.
+The docs use Zensical's built-in macro support, which is compatible with the `mkdocs-macros-plugin`
+API. This lets us call out to Python code from within Markdown.
See the `main.py` file which includes some useful macros.
diff --git a/docs/docs/endpoints.md b/docs/docs/endpoints.md
index 95e1a3d0c..e548f5b30 100644
--- a/docs/docs/endpoints.md
+++ b/docs/docs/endpoints.md
@@ -1,3 +1,7 @@
+---
+description: Learn how to configure Mockzilla endpoints — define custom handlers for your mock HTTP server.
+---
+
# Configuring Endpoints
## Simple Example
diff --git a/docs/docs/index.md b/docs/docs/index.md
index 487ccfec7..0849dd3bc 100644
--- a/docs/docs/index.md
+++ b/docs/docs/index.md
@@ -1,4 +1,5 @@
---
-title: Home
+title: Mockzilla
template: home.html
+description: A compile safe solution for running and configuring a local HTTP server for your mobile apps. Supports Android, iOS, Kotlin Multiplatform and Flutter.
---
diff --git a/docs/docs/overrides/home.html b/docs/docs/overrides/home.html
index d7b0564c4..e656c186e 100644
--- a/docs/docs/overrides/home.html
+++ b/docs/docs/overrides/home.html
@@ -1,18 +1 @@
-{% extends "main.html" %} {% block header %} {{ super() }} {% endblock %} {% block styles %} {{ super() }}
-
-{% endblock %} {% block footer %} {% endblock %} {% block tabs %} {% block content %}
-
-{% endblock %} {% endblock %}
+{% include "homepage-content.html" %}
diff --git a/docs/docs/overrides/main.html b/docs/docs/overrides/main.html
index e6744171a..5cb6467e6 100644
--- a/docs/docs/overrides/main.html
+++ b/docs/docs/overrides/main.html
@@ -1,44 +1,2 @@
-{% extends "base.html" %} {% block scripts %} {{ super() }}
-
-{% endblock %}
diff --git a/docs/docs/quick-start.md b/docs/docs/quick-start.md
index 2d6a3bf87..5d26cef19 100644
--- a/docs/docs/quick-start.md
+++ b/docs/docs/quick-start.md
@@ -1,3 +1,7 @@
+---
+description: Get started with Mockzilla in minutes. Add the dependency, configure your endpoints, and start a local mock HTTP server for your mobile app.
+---
+
# Quick Start
!!! important
Mockzilla does not support HTTPS, all traffic is cleartext HTTP.
diff --git a/docs/homepage/generate-fragment.mjs b/docs/homepage/generate-fragment.mjs
new file mode 100644
index 000000000..849fd2b60
--- /dev/null
+++ b/docs/homepage/generate-fragment.mjs
@@ -0,0 +1,112 @@
+import { build } from 'vite'
+import { readFileSync, writeFileSync, readdirSync } from 'fs'
+import { resolve, dirname } from 'path'
+import { fileURLToPath, pathToFileURL } from 'url'
+
+const __dirname = dirname(fileURLToPath(import.meta.url))
+const outputPath = resolve(__dirname, '../docs/overrides/homepage-content.html')
+
+// Read version from gradle; VITE_VERSION_NAME env var takes precedence (set by CI via Fastlane).
+const gradleText = readFileSync(resolve(__dirname, '../../mockzilla/build.gradle.kts'), 'utf-8')
+const versionMatch = gradleText.match(/"(.*?)" \/\/ x-release-please-version/)
+process.env.VITE_VERSION_NAME ||= versionMatch ? versionMatch[1] : 'Dev'
+
+// Collapses whitespace and strips single-line comments — sufficient for small inline scripts.
+const minify = src => src.replace(/\/\/[^\n]*/g, '').replace(/\s+/g, ' ').trim()
+
+// Reads Material's /.__palette key before first paint to prevent FOUC.
+// Homepage and docs share this single key so their dark-mode states are always in sync.
+const themeInitScript = minify(`
+ try {
+ var p = localStorage.getItem('/.__palette');
+ var dark = p
+ ? JSON.parse(p).index === 1
+ : window.matchMedia('(prefers-color-scheme:dark)').matches;
+ if (dark) document.documentElement.classList.add('dark');
+ } catch (e) {}
+`)
+
+// Wires up the toggle button and writes Material's /.__palette key on click.
+const toggleScript = minify(`
+ (function () {
+ var b = document.getElementById('theme-toggle');
+ if (!b) return;
+ b.addEventListener('click', function () {
+ var dark = document.documentElement.classList.toggle('dark');
+ try {
+ localStorage.setItem('/.__palette', JSON.stringify({ index: dark ? 1 : 0 }));
+ } catch (e) {}
+ });
+ })()
+`)
+
+// Step 1: Browser build — uses vite.config.mjs (SWC + Tailwind) to compile CSS.
+console.log('Building assets...')
+await build({ logLevel: 'warn' })
+
+// Step 2: SSR build — uses @vitejs/plugin-react (standard Babel, not SWC) because the SWC
+// plugin doesn't reliably produce Node.js-runnable output. react-syntax-highlighter is bundled
+// inline (noExternal) to avoid CJS/ESM interop errors when it's externalized.
+console.log('Building SSR bundle...')
+const { default: reactPlugin } = await import('@vitejs/plugin-react')
+await build({
+ configFile: false,
+ plugins: [reactPlugin()],
+ resolve: {
+ extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
+ alias: { '@': resolve(__dirname, './src') },
+ },
+ logLevel: 'warn',
+ ssr: { noExternal: ['react-syntax-highlighter'] },
+ build: {
+ ssr: 'src/ssr-entry.tsx',
+ outDir: 'dist-ssr',
+ rollupOptions: { output: { format: 'esm' } },
+ },
+})
+
+// Step 3: Run the SSR bundle to get pre-rendered HTML.
+// The cache-bust query param (?t=...) forces Node to re-import on repeated runs.
+console.log('Rendering HTML...')
+const ssrEntryPath = resolve(__dirname, 'dist-ssr/ssr-entry.js')
+const { render } = await import(`${pathToFileURL(ssrEntryPath).href}?t=${Date.now()}`)
+const bodyHtml = render()
+
+// Step 4: Inline the compiled CSS.
+const assetsDir = resolve(__dirname, 'build/homepage-assets')
+const css = readdirSync(assetsDir)
+ .filter(f => f.endsWith('.css'))
+ .map(f => readFileSync(resolve(assetsDir, f), 'utf-8'))
+ .join('\n')
+
+// Step 5: Write the complete standalone HTML document.
+const title = 'Mockzilla — Build API mocks with ease'
+const desc = 'A compile-safe solution for running and configuring a local HTTP server for your mobile apps. Supports Android, iOS, Kotlin Multiplatform and Flutter.'
+const ogUrl = 'https://mockzilla.apadmi.dev/'
+
+const fullDocument = `
+
+
+
+
+${title}
+
+
+
+
+
+
+
+
+
+
+
+${bodyHtml}
+
+
+`
+
+writeFileSync(outputPath, fullDocument)
+console.log(`✓ Standalone HTML document written to ${outputPath}`)
diff --git a/docs/homepage/package-lock.json b/docs/homepage/package-lock.json
index c2deb3321..ab3efef41 100644
--- a/docs/homepage/package-lock.json
+++ b/docs/homepage/package-lock.json
@@ -1187,9 +1187,6 @@
"arm"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1204,9 +1201,6 @@
"arm"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1221,9 +1215,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1238,9 +1229,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1255,9 +1243,6 @@
"loong64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1272,9 +1257,6 @@
"ppc64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1289,9 +1271,6 @@
"riscv64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1306,9 +1285,6 @@
"riscv64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1323,9 +1299,6 @@
"s390x"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1340,9 +1313,6 @@
"x64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1357,9 +1327,6 @@
"x64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1534,9 +1501,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
@@ -1554,9 +1518,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
@@ -1574,9 +1535,6 @@
"x64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
@@ -1594,9 +1552,6 @@
"x64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
@@ -1812,9 +1767,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1832,9 +1784,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1852,9 +1801,6 @@
"x64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -1872,9 +1818,6 @@
"x64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -3644,9 +3587,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -3668,9 +3608,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -3692,9 +3629,6 @@
"x64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -3716,9 +3650,6 @@
"x64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "MPL-2.0",
"optional": true,
"os": [
diff --git a/docs/homepage/package.json b/docs/homepage/package.json
index 16854a8eb..82377eb93 100644
--- a/docs/homepage/package.json
+++ b/docs/homepage/package.json
@@ -5,6 +5,7 @@
"scripts": {
"dev": "export VITE_VERSION_NAME=Debug; vite",
"build": "tsc -b && vite build",
+ "build:fragment": "node generate-fragment.mjs",
"lint": "eslint .",
"preview": "vite preview"
},
diff --git a/docs/homepage/src/App.tsx b/docs/homepage/src/App.tsx
index 0e5e39fc9..8dc3f3508 100644
--- a/docs/homepage/src/App.tsx
+++ b/docs/homepage/src/App.tsx
@@ -1,15 +1,14 @@
import { Features } from "./components/Features";
import { Footer } from "./components/Footer";
+import { Header } from "./components/Header";
import { Hero } from "./components/Hero";
import { PlatformBanner } from "./components/PlatformBanner";
import { PlatformSupport } from "./components/PlatformSupport";
-import { useTheme } from "./hooks/useTheme";
export default function App() {
- useTheme();
-
return (
+
diff --git a/docs/homepage/src/components/Footer.tsx b/docs/homepage/src/components/Footer.tsx
index 31362072a..504a039ab 100644
--- a/docs/homepage/src/components/Footer.tsx
+++ b/docs/homepage/src/components/Footer.tsx
@@ -1,6 +1,8 @@
-import { Button } from "./ui/button";
+import { buttonVariants } from "./ui/button";
+import { cn } from "./ui/utils";
import { GithubIcon } from "./ui/icons";
-import logo from "../assets/logo.svg";
+
+const logo = "/img/icon.svg";
export function Footer() {
return (
@@ -22,7 +24,6 @@ export function Footer() {
diff --git a/docs/homepage/src/components/Header.tsx b/docs/homepage/src/components/Header.tsx
new file mode 100644
index 000000000..1579d5e4d
--- /dev/null
+++ b/docs/homepage/src/components/Header.tsx
@@ -0,0 +1,69 @@
+import { GithubIcon } from "./ui/icons";
+
+const logo = "/img/icon.svg";
+
+export function Header() {
+ return (
+
+ );
+}
diff --git a/docs/homepage/src/components/Hero.tsx b/docs/homepage/src/components/Hero.tsx
index 6ba8470d4..d4db7ff05 100644
--- a/docs/homepage/src/components/Hero.tsx
+++ b/docs/homepage/src/components/Hero.tsx
@@ -1,43 +1,18 @@
-import { MockzillaLogoDark, MockzillaLogoLight } from "./ui/icons";
-import {
- atomOneDark,
- colorBrewer,
-} from "react-syntax-highlighter/dist/cjs/styles/hljs";
-import { useEffect, useState } from "react";
+import { MockzillaLogoLight } from "./ui/icons";
+import { atomOneDark } from "react-syntax-highlighter/dist/cjs/styles/hljs";
import { ArrowRight } from "lucide-react";
import { Badge } from "./ui/badge";
-import { Button } from "./ui/button";
+import { buttonVariants } from "./ui/button";
+import { cn } from "./ui/utils";
import SyntaxHighlighter from "react-syntax-highlighter";
export function Hero(props: any) {
- const [isDark, setIsDark] = useState(false);
-
- useEffect(() => {
- // Check initial theme
- const checkTheme = () => {
- setIsDark(document.documentElement.classList.contains("dark"));
- };
-
- checkTheme();
-
- // Watch for theme changes
- const observer = new MutationObserver(checkTheme);
- observer.observe(document.documentElement, {
- attributes: true,
- attributeFilter: ["class"],
- });
-
- return () => observer.disconnect();
- }, []);
-
return (
@@ -60,9 +35,7 @@ export function Hero(props: any) {
paddingLeft: "0",
paddingRight: "0",
}}
- style={
- isDark ? atomOneDark : colorBrewer
- }>{`// Configure Server
+ style={atomOneDark}>{`// Configure Server
val endpoint = EndpointConfiguration
.Builder("GET - Customer")
.setDefaultHandler {
@@ -75,7 +48,7 @@ val endpoint = EndpointConfiguration
val config = MockzillaConfig.Builder()
.addEndpoint(endpoint)
-
+
// Start Server
startMockzilla(config)`}
@@ -101,25 +74,23 @@ startMockzilla(config)`}
-
-
+
diff --git a/docs/homepage/src/components/ui/button.tsx b/docs/homepage/src/components/ui/button.tsx
index 78c536dfb..2e0668639 100644
--- a/docs/homepage/src/components/ui/button.tsx
+++ b/docs/homepage/src/components/ui/button.tsx
@@ -54,4 +54,4 @@ function Button({
);
}
-export { Button };
+export { Button, buttonVariants };
diff --git a/docs/homepage/src/components/ui/icons.tsx b/docs/homepage/src/components/ui/icons.tsx
index 4a1e66cd7..3588abb3a 100644
--- a/docs/homepage/src/components/ui/icons.tsx
+++ b/docs/homepage/src/components/ui/icons.tsx
@@ -134,5 +134,4 @@ export const FlutterIcon = (props: SVGProps) => (
);
-export const MockzillaLogoDark = `url('data:image/svg+xml,<%3Fxml version="1.0" encoding="UTF-8" standalone="no"%3F>')`;
export const MockzillaLogoLight = `url('data:image/svg+xml,<%3Fxml version="1.0" encoding="UTF-8" standalone="no"%3F>')`;
diff --git a/docs/homepage/src/ssr-entry.tsx b/docs/homepage/src/ssr-entry.tsx
new file mode 100644
index 000000000..31595d1a0
--- /dev/null
+++ b/docs/homepage/src/ssr-entry.tsx
@@ -0,0 +1,6 @@
+import { renderToStaticMarkup } from 'react-dom/server'
+import App from './App'
+
+export function render(): string {
+ return renderToStaticMarkup()
+}
diff --git a/docs/homepage/src/styles/globals.css b/docs/homepage/src/styles/globals.css
index 62d0f41c0..186a69d08 100644
--- a/docs/homepage/src/styles/globals.css
+++ b/docs/homepage/src/styles/globals.css
@@ -19,7 +19,7 @@
--secondary-foreground: #262626;
--muted: #f5f5f5;
--muted-foreground: #737373;
- --accent: #4eced8;
+ --accent: #3ea6af;
--accent-foreground: #262626;
--success: #4ed887;
--success-foreground: #0d0d0d;
@@ -258,3 +258,9 @@ html {
outline-offset: 2px;
}
}
+
+/* Theme toggle icon visibility — controlled by .dark class on */
+#icon-sun { display: none; }
+#icon-moon { display: block; }
+.dark #icon-sun { display: block; }
+.dark #icon-moon { display: none; }
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
deleted file mode 100644
index f64853152..000000000
--- a/docs/mkdocs.yml
+++ /dev/null
@@ -1,73 +0,0 @@
-site_name: Mockzilla
-site_url: https://mockzilla.apadmi.dev/
-repo_url: https://github.com/Apadmi-Engineering/Mockzilla
-copyright: Copyright © 2025 Apadmi Ltd
-theme:
- logo: "img/icon.svg"
- favicon: "img/favicon.ico"
- custom_dir: docs/overrides
- palette:
- # Palette toggle for light mode
- - media: "(prefers-color-scheme: light)"
- scheme: default
- toggle:
- icon: material/brightness-7
- name: Switch to dark mode
- primary: custom
- accent: custom
-
- # Palette toggle for dark mode
- - media: "(prefers-color-scheme: dark)"
- scheme: slate
- toggle:
- icon: material/brightness-4
- name: Switch to light mode
- primary: custom
- accent: custom
- name: material
- features:
- - navigation.tabs
- - navigation.sections
- - navigation.top
-plugins:
- - search
- - macros
-extra_css:
- - stylesheets/extra.css
-nav:
- - index.md
- - Docs:
- - quick-start.md
- - endpoints.md
- - Advanced:
- - additional_config.md
- - browser_stack.md
- - snapshots.md
- - Configuration at Runtime:
- - desktop/overview.md
- - mobile_ui.md
- - presets.md
- - Contributing:
- - contributing.md
- - Desktop App: desktop_contributing.md
- - Documentation: documentation.md
- - Flutter: flutter_contributing.md
- - Api Reference:
- ./dokka/index.html
-markdown_extensions:
- - pymdownx.arithmatex:
- generic: true
- - admonition
- - pymdownx.details
- - pymdownx.superfences
- - pymdownx.tabbed:
- alternate_style: true
- - pymdownx.superfences:
- custom_fences:
- - name: mermaid
- class: mermaid
- format: !!python/name:pymdownx.superfences.fence_code_format
-extra_javascript:
- - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
-hooks:
- - custom_hooks.py
\ No newline at end of file
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 96d706e0e..fe4ebb73d 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,2 +1 @@
-mkdocs-material==9.6.20
-mkdocs-macros-plugin==1.0.5
\ No newline at end of file
+zensical==0.0.43
\ No newline at end of file
diff --git a/docs/serve.sh b/docs/serve.sh
new file mode 100755
index 000000000..60b406976
--- /dev/null
+++ b/docs/serve.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+
+cd "$SCRIPT_DIR/homepage" && npm run build:fragment
+
+cd "$SCRIPT_DIR"
+if [[ -x "$SCRIPT_DIR/.venv/bin/zensical" ]]; then
+ "$SCRIPT_DIR/.venv/bin/zensical" serve
+ else
+ zensical serve
+ fi
\ No newline at end of file
diff --git a/docs/zensical.toml b/docs/zensical.toml
new file mode 100644
index 000000000..bf72cbdaf
--- /dev/null
+++ b/docs/zensical.toml
@@ -0,0 +1,77 @@
+[project]
+site_name = "Mockzilla"
+site_url = "https://mockzilla.apadmi.dev/"
+repo_url = "https://github.com/Apadmi-Engineering/Mockzilla"
+copyright = "Copyright © 2026 Apadmi Ltd"
+site_description = "A compile-safe solution for running and configuring a local HTTP server for your mobile apps. Supports Android, iOS, Kotlin Multiplatform and Flutter."
+extra_css = ["stylesheets/extra.css"]
+extra_javascript = ["https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"]
+
+nav = [
+ "index.md",
+ { Docs = [
+ "quick-start.md",
+ "endpoints.md",
+ { Advanced = [
+ "additional_config.md",
+ "browser_stack.md",
+ "snapshots.md",
+ ]},
+ { "Configuration at Runtime" = [
+ "desktop/overview.md",
+ "mobile_ui.md",
+ "presets.md",
+ ]},
+ ]},
+ { Contributing = [
+ "contributing.md",
+ { "Desktop App" = "desktop_contributing.md" },
+ { Documentation = "documentation.md" },
+ { Flutter = "flutter_contributing.md" },
+ ]},
+ { "Api Reference" = "./dokka/index.html" },
+]
+
+[project.theme]
+logo = "img/icon.svg"
+favicon = "img/favicon.ico"
+custom_dir = "docs/overrides"
+features = [
+ "navigation.tabs",
+ "navigation.sections",
+ "navigation.top",
+]
+
+[[project.theme.palette]]
+media = "(prefers-color-scheme: light)"
+scheme = "default"
+primary = "custom"
+accent = "custom"
+toggle.icon = "material/brightness-7"
+toggle.name = "Switch to dark mode"
+
+[[project.theme.palette]]
+media = "(prefers-color-scheme: dark)"
+scheme = "slate"
+primary = "custom"
+accent = "custom"
+toggle.icon = "material/brightness-4"
+toggle.name = "Switch to light mode"
+
+[project.markdown_extensions.pymdownx.arithmatex]
+generic = true
+
+[project.markdown_extensions.admonition]
+
+[project.markdown_extensions.pymdownx.details]
+
+[project.markdown_extensions.pymdownx.tabbed]
+alternate_style = true
+
+[project.markdown_extensions.pymdownx.superfences]
+custom_fences = [
+ { name = "mermaid", class = "mermaid", format = "pymdownx.superfences.fence_code_format" }
+]
+
+[project.markdown_extensions.zensical.extensions.macros]
+module_name = "main"
diff --git a/fastlane/fastfiles/docs.rb b/fastlane/fastfiles/docs.rb
index be3eb74b6..4c7497a10 100644
--- a/fastlane/fastfiles/docs.rb
+++ b/fastlane/fastfiles/docs.rb
@@ -1,6 +1,4 @@
lane :generate_docs do
- output_dir = "#{lane_context[:repo_root]}/generated_docs"
-
# Build the page to redirect to the desktop app download site
sh("cd #{lane_context[:repo_root]}/docs; python -c 'import main; main.update_download_file()'")
@@ -9,7 +7,7 @@
cd #{lane_context[:repo_root]}/docs/homepage;
npm i;
export VITE_VERSION_NAME=#{get_core_mockzilla_version_name};
- npm run build;
+ npm run build:fragment;
");
# Generate Kotlin documentation
@@ -20,6 +18,6 @@
}
)
- # Build mkdocs
- sh("cd #{lane_context[:repo_root]}/docs; mkdocs build -d #{output_dir}")
+ # Build docs
+ sh("cd #{lane_context[:repo_root]}/docs; zensical build")
end
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index c4e671f16..a4b603bb3 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -18,7 +18,7 @@ buildKonfig = "0.20.0" # https://github.com/yshrsmz/BuildKonfig
dokka = "2.2.0" # https://github.com/Kotlin/dokka
# Localization
-lyricist = "1.8.0" # https://github.com/adrielcafe/lyricist
+lyricist = "1.7.0" # https://github.com/adrielcafe/lyricist
# Networking
ktor = "3.4.3" # https://github.com/ktorio/ktor
@@ -93,6 +93,7 @@ semver = { module = "io.github.z4kn4fein:semver", version.ref = "semver" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
+ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
ktor-server-cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" }
diff --git a/mockzilla-common/build.gradle.kts b/mockzilla-common/build.gradle.kts
index 732afe3ba..c310208b3 100644
--- a/mockzilla-common/build.gradle.kts
+++ b/mockzilla-common/build.gradle.kts
@@ -79,6 +79,7 @@ kotlin {
}
compilerOptions {
freeCompilerArgs.addAll(CompilerConfig.freeCompilerArgs)
+ freeCompilerArgs.add("-opt-in=com.apadmi.mockzilla.lib.InternalMockzillaApi")
}
}
diff --git a/mockzilla-common/src/androidMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.kt b/mockzilla-common/src/androidMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.android.kt
similarity index 91%
rename from mockzilla-common/src/androidMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.kt
rename to mockzilla-common/src/androidMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.android.kt
index e415c8da8..3dc6db273 100644
--- a/mockzilla-common/src/androidMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.kt
+++ b/mockzilla-common/src/androidMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.android.kt
@@ -1,11 +1,15 @@
+@file:JvmName("FileIoKt")
+
package com.apadmi.mockzilla.lib.internal.utils
import android.annotation.TargetApi
import android.os.Build
+import com.apadmi.mockzilla.lib.InternalMockzillaApi
import java.io.File
import java.io.IOException
import java.nio.file.Files
+@InternalMockzillaApi
actual class FileIo(private val cacheDir: File) {
private val cacheDirectory
get() = File(
@@ -44,5 +48,6 @@ actual class FileIo(private val cacheDir: File) {
}
}
+@InternalMockzillaApi
@TargetApi(Build.VERSION_CODES.O)
actual fun createFileIoforTesting() = FileIo(Files.createTempDirectory("").toFile())
diff --git a/mockzilla-common/src/jvmMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.kt b/mockzilla-common/src/androidMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.android.kt
similarity index 66%
rename from mockzilla-common/src/jvmMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.kt
rename to mockzilla-common/src/androidMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.android.kt
index 745f795c5..14a30ea71 100644
--- a/mockzilla-common/src/jvmMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.kt
+++ b/mockzilla-common/src/androidMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.android.kt
@@ -1,6 +1,10 @@
+@file:JvmName("ServerUtilsKt")
+
package com.apadmi.mockzilla.lib.internal.utils
+import com.apadmi.mockzilla.lib.InternalMockzillaApi
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
+@InternalMockzillaApi
actual val Dispatchers.multiPlatformIo: CoroutineDispatcher get() = Dispatchers.IO
diff --git a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/InternalMockzillaApi.kt b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/InternalMockzillaApi.kt
similarity index 52%
rename from mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/InternalMockzillaApi.kt
rename to mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/InternalMockzillaApi.kt
index 04f417bc0..f0ce02080 100644
--- a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/InternalMockzillaApi.kt
+++ b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/InternalMockzillaApi.kt
@@ -1,8 +1,11 @@
-package com.apadmi.mockzilla.lib.internal.utils
+package com.apadmi.mockzilla.lib
/**
- * API marked with this annotation is internal, and it is not intended to be used outside Mockzilla.
- * It could be modified or removed without any notice. Please do not use it.
+ * API marked with this annotation is internal to Mockzilla and is not intended to be used outside
+ * the library. It could be modified or removed without any notice. Please do not use it.
+ *
+ * Library modules opt in at the module level via `freeCompilerArgs` in their `build.gradle.kts`.
+ * See `CONTRIBUTING.md` for guidance on when and how to apply this annotation.
*/
@RequiresOptIn(
level = RequiresOptIn.Level.ERROR,
@@ -16,7 +19,8 @@ package com.apadmi.mockzilla.lib.internal.utils
AnnotationTarget.FIELD,
AnnotationTarget.CONSTRUCTOR,
AnnotationTarget.PROPERTY_SETTER,
- AnnotationTarget.PROPERTY_SETTER
+ AnnotationTarget.PROPERTY_GETTER
)
@Retention(AnnotationRetention.BINARY)
+@MustBeDocumented
annotation class InternalMockzillaApi
diff --git a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/config/ZeroConfConfig.kt b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/config/ZeroConfConfig.kt
index 52e425563..7708a73b2 100644
--- a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/config/ZeroConfConfig.kt
+++ b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/config/ZeroConfConfig.kt
@@ -1,8 +1,17 @@
package com.apadmi.mockzilla.lib.config
+/**
+ * Constants for Mockzilla's ZeroConf (Bonjour/DNS-SD) service discovery integration. Used by
+ * the server to advertise itself and by the management UI to locate devices on the network.
+ */
object ZeroConfConfig {
+ /**
+ * The ZeroConf service type Mockzilla registers under.
+ */
const val serviceType = "_mockzilla._tcp"
- // Limit defined here: https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.1
+ /**
+ * Maximum byte length for a ZeroConf service name, as defined by RFC 1035 section 2.3.1.
+ */
const val serviceNameByteLimit = 63
}
diff --git a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/models/ClearCachesRequestDto.kt b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/models/ClearCachesRequestDto.kt
index c435279b9..b464a9d09 100644
--- a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/models/ClearCachesRequestDto.kt
+++ b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/models/ClearCachesRequestDto.kt
@@ -1,11 +1,13 @@
package com.apadmi.mockzilla.lib.internal.models
+import com.apadmi.mockzilla.lib.InternalMockzillaApi
import com.apadmi.mockzilla.lib.models.EndpointConfiguration
import kotlinx.serialization.Serializable
/**
* @property keys
*/
+@InternalMockzillaApi
@Serializable
data class ClearCachesRequestDto(
val keys: List
diff --git a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/models/SerializableEndpointConfig.kt b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/models/SerializableEndpointConfig.kt
index f1c3e0c86..71c32574a 100644
--- a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/models/SerializableEndpointConfig.kt
+++ b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/models/SerializableEndpointConfig.kt
@@ -2,6 +2,7 @@
package com.apadmi.mockzilla.lib.internal.models
+import com.apadmi.mockzilla.lib.InternalMockzillaApi
import com.apadmi.mockzilla.lib.internal.utils.HttpStatusCodeSerializer
import com.apadmi.mockzilla.lib.models.DashboardOverridePreset
import com.apadmi.mockzilla.lib.models.EndpointConfiguration
@@ -91,6 +92,7 @@ data class SerializableEndpointConfig(
* @property errorHeaders
* @property appliedPresetOverride
*/
+@InternalMockzillaApi
@Suppress("TYPE_ALIAS")
@Serializable
data class SerializableEndpointPatchItemDto(
@@ -137,6 +139,7 @@ data class SerializableEndpointPatchItemDto(
/**
* @property entries
*/
+@InternalMockzillaApi
@Serializable
data class MockDataResponseDto(
val entries: List
@@ -145,6 +148,7 @@ data class MockDataResponseDto(
/**
* @property entries
*/
+@InternalMockzillaApi
@Serializable
data class SerializableEndpointConfigPatchRequestDto(
val entries: List
@@ -152,6 +156,7 @@ data class SerializableEndpointConfigPatchRequestDto(
constructor(entry: SerializableEndpointPatchItemDto) : this(listOf(entry))
}
+@InternalMockzillaApi
@Serializable(with = ServiceResultSerializer::class)
sealed class SetOrDont {
@Serializable
@@ -166,6 +171,7 @@ sealed class SetOrDont {
data class Set(val value: T) : SetOrDont()
}
+@InternalMockzillaApi
class ServiceResultSerializer(
serializer: KSerializer
) : KSerializer> {
diff --git a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.kt b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.kt
index 052669541..1725438be 100644
--- a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.kt
+++ b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/FileIo.kt
@@ -1,5 +1,8 @@
package com.apadmi.mockzilla.lib.internal.utils
+import com.apadmi.mockzilla.lib.InternalMockzillaApi
+
+@InternalMockzillaApi
expect class FileIo {
suspend fun readFromCache(filename: String): String?
suspend fun saveToCache(filename: String, contents: String)
@@ -7,4 +10,5 @@ expect class FileIo {
suspend fun deleteAllCaches()
}
+@InternalMockzillaApi
expect fun createFileIoforTesting(): FileIo
diff --git a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/JsonProvider.kt b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/JsonProvider.kt
index 45243211e..7364b3d40 100644
--- a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/JsonProvider.kt
+++ b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/JsonProvider.kt
@@ -1,7 +1,9 @@
package com.apadmi.mockzilla.lib.internal.utils
+import com.apadmi.mockzilla.lib.InternalMockzillaApi
import kotlinx.serialization.json.Json
+@InternalMockzillaApi
object JsonProvider {
val json = Json {
ignoreUnknownKeys = true
diff --git a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.kt b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.kt
index 9579e15cc..7247a0f67 100644
--- a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.kt
+++ b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/internal/utils/ServerUtils.kt
@@ -1,6 +1,8 @@
package com.apadmi.mockzilla.lib.internal.utils
+import com.apadmi.mockzilla.lib.InternalMockzillaApi
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
+@InternalMockzillaApi
expect val Dispatchers.multiPlatformIo: CoroutineDispatcher
diff --git a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/models/EndpointConfiguration.kt b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/models/EndpointConfiguration.kt
index 133217c90..48fc53dfa 100644
--- a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/models/EndpointConfiguration.kt
+++ b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/models/EndpointConfiguration.kt
@@ -10,15 +10,27 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonNames
/**
- * @property name
- * @property key
- * @property shouldFail
- * @property delay
- * @property endpointMatcher
- * @property versionCode
- * @property defaultHandler
- * @property errorHandler
- * @property dashboardOptionsConfig
+ * Configures a single mock endpoint within a Mockzilla server. Defines how incoming requests are
+ * matched to this endpoint and what response to return, along with optional dashboard presets and
+ * latency simulation.
+ *
+ * Construct via [Builder].
+ *
+ * @property name Human-readable display name shown in the management dashboard.
+ * @property key Unique identifier for this endpoint, used in management API operations.
+ * @property shouldFail Whether this endpoint returns an error response by default. When `true`,
+ * [errorHandler] is called instead of [defaultHandler].
+ * @property delay Artificial response delay in milliseconds. `null` falls back to the global delay
+ * set on [MockzillaConfig.Builder].
+ * @property dashboardOptionsConfig Preset responses available to users in the management dashboard.
+ * @property versionCode Version number for this endpoint's configuration. Incrementing this value
+ * automatically invalidates any cached responses on connected devices.
+ * @property endpointMatcher Predicate that determines whether an incoming request should be routed
+ * to this endpoint. The first matching endpoint wins.
+ * @property defaultHandler Called when a request matches this endpoint and [shouldFail] is `false`.
+ * Returns the mock response to send back to the caller.
+ * @property errorHandler Called when a request matches this endpoint and [shouldFail] is `true`.
+ * Returns the simulated error response to send back to the caller.
*/
data class EndpointConfiguration(
val name: String,
@@ -32,7 +44,10 @@ data class EndpointConfiguration(
val errorHandler: suspend MockzillaHttpRequest.() -> MockzillaHttpResponse,
) {
/**
- * @property raw
+ * Unique serializable identifier for an [EndpointConfiguration]. Used to reference endpoints
+ * in management API operations such as cache clearing or runtime overrides.
+ *
+ * @property raw The raw string value of the key.
*/
@Serializable
@JvmInline
@@ -59,7 +74,7 @@ data class EndpointConfiguration(
/**
* Sets the human readable name of the endpoint (defaults to the value of the `key`)
*
- * @param name
+ * @param name The human-readable display name for this endpoint.
*/
fun setName(name: String) = apply {
config = config.copy(name = name)
@@ -98,17 +113,17 @@ data class EndpointConfiguration(
* [setShouldFail] causes Mockzilla to generate a failure response, then this block
* will *not* be called, instead the block specified by [setErrorHandler] is called.
*
- * @param handler
+ * @param handler Lambda invoked with the incoming request that returns the mock response.
*/
fun setDefaultHandler(handler: suspend MockzillaHttpRequest.() -> MockzillaHttpResponse) = apply {
config = config.copy(defaultHandler = handler)
}
/**
- * The block called when a network request is made to this endpoint but Mockzilladecides to
+ * The block called when a network request is made to this endpoint but Mockzilla decides to
* simulate a server failure.
*
- * @param handler
+ * @param handler Lambda invoked with the incoming request that returns the simulated error response.
*/
fun setErrorHandler(handler: suspend MockzillaHttpRequest.() -> MockzillaHttpResponse) = apply {
config = config.copy(errorHandler = handler)
@@ -117,8 +132,8 @@ data class EndpointConfiguration(
/**
* Configure the presets that are available to users of the dashboard.
*
- * @param action
- * @return
+ * @param action Builder block for configuring dashboard presets.
+ * @return This builder, for chaining.
*/
fun configureDashboardOverrides(
action: DashboardOptionsConfig.Builder.() -> DashboardOptionsConfig.Builder
@@ -142,7 +157,7 @@ data class EndpointConfiguration(
*
* This is just a utility wrapper around the more flexible [setPatternMatcher] endpoint.
*
- * @param regex
+ * @param regex The regular expression to match against the full request URI.
*/
@Suppress("unused")
fun setPattern(regex: String) = apply {
@@ -170,9 +185,13 @@ data class EndpointConfiguration(
}
/**
- * @property statusCode
- * @property headers
- * @property body
+ * An HTTP response returned by a mock endpoint handler. Returned from
+ * [EndpointConfiguration.Builder.setDefaultHandler] and [EndpointConfiguration.Builder.setErrorHandler]
+ * lambdas.
+ *
+ * @property statusCode The HTTP status code of the response. Defaults to `200 OK`.
+ * @property headers HTTP response headers.
+ * @property body The response body as a string.
*/
@Serializable
data class MockzillaHttpResponse(
@@ -185,9 +204,12 @@ data class MockzillaHttpResponse(
}
/**
- * @property statusCode
- * @property headers
- * @property body
+ * A partial HTTP response used by dashboard presets, allowing a subset of response fields to
+ * be overridden. `null` fields are left unchanged from the endpoint's default response.
+ *
+ * @property statusCode The HTTP status code override, or `null` to leave unchanged.
+ * @property headers HTTP response headers override, or `null` to leave unchanged.
+ * @property body The response body override, or `null` to leave unchanged.
*/
@Serializable
data class PartialMockzillaHttpResponse(
@@ -227,6 +249,12 @@ interface MockzillaHttpRequest {
}
/**
+ * Configures the preset responses available to users in the Mockzilla management dashboard for a
+ * specific endpoint. Presets let dashboard users quickly switch between common response scenarios
+ * without modifying code.
+ *
+ * Construct via [Builder] and attach to an endpoint using
+ * [EndpointConfiguration.Builder.configureDashboardOverrides].
* @property errorPresets
* @property successPresets
*/
@@ -242,10 +270,24 @@ data class DashboardOptionsConfig(
@JsonNames("presets")
val successPresets: List
) {
+ /**
+ * The list of preset responses available in the dashboard for this endpoint.
+ */
val presets get() = successPresets
class Builder {
private val presets = mutableListOf()
+
+ /**
+ * Adds a preset response option to the dashboard for this endpoint.
+ *
+ * @param response The full response this preset applies when selected.
+ * @param name Display name for this preset in the dashboard. Defaults to "Preset N".
+ * @param description Optional description shown alongside the preset.
+ * @param type Visual classification for this preset. Defaults to a type inferred from the
+ * response status code when `null`.
+ * @return This builder, for chaining.
+ */
fun addPreset(
response: MockzillaHttpResponse,
name: String? = null,
@@ -253,6 +295,17 @@ data class DashboardOptionsConfig(
type: DashboardOverridePreset.Type? = null
) = addPreset(response.toPartial(), name, description, type)
+ /**
+ * Adds a partial preset response option to the dashboard for this endpoint. Only fields
+ * set on [response] are overridden; `null` fields retain the endpoint's default values.
+ *
+ * @param response The partial response this preset applies when selected.
+ * @param name Display name for this preset in the dashboard. Defaults to "Preset N".
+ * @param description Optional description shown alongside the preset.
+ * @param type Visual classification for this preset. Defaults to a type inferred from the
+ * response status code when `null`.
+ * @return This builder, for chaining.
+ */
fun addPreset(
response: PartialMockzillaHttpResponse,
name: String? = null,
@@ -290,11 +343,17 @@ data class DashboardOptionsConfig(
}
/**
- * @property name
- * @property description
- * @property type Overrides the type of the preset shown in UI, defaults to correspond with status code
- * @property response
- * @property isManagementUiDefinedCustomPreset
+ * A named response configuration that can be applied to an endpoint from the Mockzilla management
+ * dashboard, overriding the endpoint's default or error response for a session.
+ *
+ * @property name Display name shown in the dashboard preset list.
+ * @property description Optional description shown alongside the preset in the dashboard.
+ * @property type Visual classification for the preset in the dashboard. Defaults to a type
+ * inferred from the response status code when `null`.
+ * @property response The partial response this preset applies when selected.
+ * @property isManagementUiDefinedCustomPreset `true` when this preset was created interactively
+ * by a user in the management dashboard, as opposed to being defined in code via
+ * [EndpointConfiguration.Builder.configureDashboardOverrides].
*/
@Serializable
data class DashboardOverridePreset(
@@ -304,6 +363,10 @@ data class DashboardOverridePreset(
val response: PartialMockzillaHttpResponse,
val isManagementUiDefinedCustomPreset: Boolean = false
) {
+ /**
+ * Visual classification for a [DashboardOverridePreset] in the management dashboard. Used to
+ * display presets with appropriate styling.
+ */
@Serializable
enum class Type {
ClientError,
diff --git a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/models/MetaData.kt b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/models/MetaData.kt
index 65834d718..4cbdef87d 100644
--- a/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/models/MetaData.kt
+++ b/mockzilla-common/src/commonMain/kotlin/com/apadmi/mockzilla/lib/models/MetaData.kt
@@ -8,19 +8,20 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonNames
/**
- * @property appName
- * @property appPackage
- * @property operatingSystemVersion
- * @property deviceModel
- * @property appVersion
- * @property runTarget
- * @property mockzillaVersion
+ * Device and application metadata collected when Mockzilla starts. Displayed in the management
+ * dashboard to identify the connected device, and used in ZeroConf service records.
*
- * Don't add non optional fields to this type since that will break backward compatibility
- *
- * Short alternative JsonNames used for encoding/decoding when ZeroConf is used to reduce payload size
+ * Don't add non-optional fields to this type since that will break backward compatibility
*
+ * @property appName The name of the application.
+ * @property appPackage The application package name or bundle identifier.
+ * @property operatingSystemVersion The OS version string of the device.
+ * @property deviceModel The device model identifier.
+ * @property appVersion The application version string.
+ * @property runTarget The platform the server is running on, or `null` if unknown.
+ * @property mockzillaVersion The version of the Mockzilla library.
*/
+@OptIn(ExperimentalSerializationApi::class)
@Serializable
data class MetaData @OptIn(ExperimentalSerializationApi::class) constructor(
@JsonNames("appName")
@@ -51,14 +52,27 @@ data class MetaData @OptIn(ExperimentalSerializationApi::class) constructor(
@SerialName("mzVer")
val mockzillaVersion: String
) {
+ /**
+ * `true` if the server is running on an Android device or emulator.
+ */
val isAndroid = runTarget in listOf(RunTarget.AndroidEmulator, RunTarget.AndroidDevice)
+ /**
+ * Serialises this metadata to a [Map] for embedding in ZeroConf TXT records.
+ *
+ * @return A map of field names to string values.
+ */
fun toMap(): Map {
val encoded = json.encodeToString(this)
return json.decodeFromString