diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..5e2f3ba --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,35 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module", + "ecmaFeatures": { + "jsx": true + }, + "project": "./tsconfig.json" + }, + "env": { + "browser": true, + "node": true, + "es6": true + }, + "plugins": ["@typescript-eslint", "react", "react-hooks"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react/recommended", + "plugin:react-hooks/recommended", + "prettier" + ], + "settings": { + "react": { + "version": "detect" + } + }, + "rules": { + "@typescript-eslint/no-explicit-any": "warn", + "react/react-in-jsx-scope": "off" + }, + "ignorePatterns": [".docusaurus", "build", "node_modules"] +} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 56ff59f..aaabe22 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,6 +25,11 @@ jobs: - name: Install dependencies run: npm ci + # Code quality checks + - name: Check code formatting + run: npm run format:check + - name: Run ESLint + run: npm run lint # Fast validation tests first - name: Run Fast Validation Tests run: npm run test diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..45cc0d9 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +node_modules +.docusaurus +build +package-lock.json +*.min.js + diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..8413751 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,11 @@ +{ + "semi": true, + "trailingComma": "es5", + "singleQuote": false, + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "arrowParens": "always", + "endOfLine": "lf" +} + diff --git a/README.md b/README.md index 4793827..77c942d 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ npm run test ``` This validates: + - All `docId` references in `docusaurus.config.ts` point to existing files - Internal markdown links are valid - Configuration paths are correct @@ -54,6 +55,38 @@ git push --no-verify ⚠️ **Note:** Even if you skip the hook, CI will still validate your changes and block deployment if validation fails. +## Code Quality + +This project uses ESLint for linting and Prettier for code formatting to maintain consistent code style. + +### Formatting + +Format all files according to the Prettier configuration: + +```bash +npm run format +``` + +Check if files are formatted correctly without modifying them: + +```bash +npm run format:check +``` + +### Linting + +Check for linting issues: + +```bash +npm run lint +``` + +Automatically fix linting issues where possible: + +```bash +npm run lint:fix +``` + ## Deployment The website is deployed automatically using GitHub Actions when changes are pushed to the `main` branch. The deployment process: @@ -62,4 +95,4 @@ The website is deployed automatically using GitHub Actions when changes are push 2. Runs full Docusaurus build 3. Deploys to GitHub Pages (only if all checks pass) -Broken links or validation errors will prevent deployment. \ No newline at end of file +Broken links or validation errors will prevent deployment. diff --git a/docs/For-developers/android/_category_.json b/docs/For-developers/android/_category_.json index 348bfab..064c50d 100644 --- a/docs/For-developers/android/_category_.json +++ b/docs/For-developers/android/_category_.json @@ -6,4 +6,3 @@ "description": "Android development setup and guides for ODE developers." } } - diff --git a/docs/For-developers/android/adb-setup.md b/docs/For-developers/android/adb-setup.md index 4c51e46..1038f0d 100644 --- a/docs/For-developers/android/adb-setup.md +++ b/docs/For-developers/android/adb-setup.md @@ -10,6 +10,7 @@ This guide will walk you through setting up Android Debug Bridge (ADB) on your d ## What is ADB? **Android Debug Bridge (ADB)** is a versatile command-line tool that lets you: + - Install and debug Android applications - Access a Unix shell on your Android device - Transfer files between your computer and device @@ -45,6 +46,7 @@ export PATH=$PATH:$ANDROID_HOME/tools ``` 4. Reload your shell configuration: + ```bash source ~/.zshrc # or source ~/.bash_profile ``` @@ -80,17 +82,20 @@ scoop install adb #### Option 1: Using Package Manager **Ubuntu/Debian:** + ```bash sudo apt-get update sudo apt-get install android-tools-adb android-tools-fastboot ``` **Fedora:** + ```bash sudo dnf install android-tools ``` **Arch Linux:** + ```bash sudo pacman -S android-tools ``` @@ -108,6 +113,7 @@ export PATH=$PATH:$ANDROID_HOME/tools ``` 4. Reload your shell configuration: + ```bash source ~/.bashrc # or source ~/.zshrc ``` @@ -121,6 +127,7 @@ adb version ``` You should see output like: + ``` Android Debug Bridge version 1.0.41 Version 33.0.3-8952118 @@ -158,12 +165,14 @@ adb devices ``` You should see output like: + ``` List of devices attached ABC123XYZ456 device ``` If you see `unauthorized` instead of `device`, you need to: + 1. Check your device screen for the USB debugging authorization prompt 2. Tap **Allow** on the prompt 3. Run `adb devices` again @@ -173,11 +182,13 @@ If you see `unauthorized` instead of `device`, you need to: Here are some useful ADB commands for development: ### Check Connected Devices + ```bash adb devices ``` ### Install an APK + ```bash adb install path/to/app.apk ``` @@ -185,56 +196,67 @@ adb install path/to/app.apk This is particularly useful for installing Formulus APK files or other ODE applications for testing. ### Install with Replace (upgrade existing app) + ```bash adb install -r path/to/app.apk ``` ### Uninstall an App + ```bash adb uninstall com.example.package ``` ### View Device Logs + ```bash adb logcat ``` ### Filter Logs by Tag + ```bash adb logcat -s TAG_NAME ``` ### Clear Logs + ```bash adb logcat -c ``` ### Pull File from Device + ```bash adb pull /sdcard/file.txt ~/Desktop/ ``` ### Push File to Device + ```bash adb push ~/Desktop/file.txt /sdcard/ ``` ### Open Shell on Device + ```bash adb shell ``` ### Reboot Device + ```bash adb reboot ``` ### Reboot to Bootloader + ```bash adb reboot bootloader ``` ### Port Forwarding (Reverse) + ```bash adb reverse tcp:LOCAL_PORT tcp:DEVICE_PORT ``` @@ -248,6 +270,7 @@ This forwards a port from your Android device to your local machine. Very useful **Issue:** `adb devices` shows no devices or shows `unauthorized` **Solutions:** + 1. **Check USB cable**: Try a different USB cable (some cables are charge-only) 2. **Check USB port**: Try a different USB port on your computer 3. **Check USB mode**: On your device, when connected, pull down the notification shade and ensure USB mode is set to **File Transfer** or **MTP** (not Charge only) @@ -262,6 +285,7 @@ This forwards a port from your Android device to your local machine. Very useful ### macOS: "adb: command not found" **Solution:** Make sure you've added ADB to your PATH and reloaded your shell: + ```bash echo 'export PATH=$PATH:$HOME/Library/Android/sdk/platform-tools' >> ~/.zshrc source ~/.zshrc @@ -269,7 +293,8 @@ source ~/.zshrc ### Windows: "adb is not recognized" -**Solution:** +**Solution:** + 1. Verify ADB is in your PATH by checking `C:\Android\sdk\platform-tools\adb.exe` exists 2. Open a **new** Command Prompt window (PATH changes require a new session) 3. Try the full path: `C:\Android\sdk\platform-tools\adb.exe devices` @@ -279,22 +304,27 @@ source ~/.zshrc **Solution:** Create a udev rule for your device: 1. Find your device's vendor ID: + ```bash lsusb ``` + Look for your device and note the ID (e.g., `18d1:4ee2`) 2. Create a udev rule file: + ```bash sudo nano /etc/udev/rules.d/51-android.rules ``` 3. Add a line (replace `18d1` with your vendor ID): + ``` SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0664", GROUP="plugdev" ``` 4. Set permissions: + ```bash sudo chmod a+r /etc/udev/rules.d/51-android.rules sudo udevadm control --reload-rules @@ -310,6 +340,7 @@ source ~/.zshrc ### Device Shows as "Offline" **Solutions:** + 1. Disconnect and reconnect the USB cable 2. Restart ADB server: ```bash @@ -335,6 +366,7 @@ For wireless debugging (Android 11+), you can connect via Wi-Fi: ## Next Steps Now that ADB is set up, you can: + - Install and test Android applications - Debug apps using `adb logcat` - Transfer files between your computer and device @@ -345,14 +377,17 @@ Now that ADB is set up, you can: Once ADB is configured and your Android device is connected, you can develop Formulus using React Native: 1. **Navigate to the Formulus folder** in your terminal: + ```bash cd path/to/formulus ``` 2. **Run the React Native app** on your connected Android device: + ```bash npx react-native run-android ``` + This command will: - Build the React Native app - Install it on your connected Android device via ADB @@ -373,14 +408,17 @@ When developing with ODE, you often need to connect Formulus running on your And 1. **Start your local Synkronus server** on your development machine (e.g., on port 8080) 2. **Forward the port** from your Android device to your local machine: + ```bash adb reverse tcp:8080 tcp:8080 ``` + This command forwards port 8080 on your Android device to port 8080 on your local machine. 3. **Configure Formulus** to use `http://localhost:8080` as the server URL. The app will connect to your local Synkronus server through the forwarded port. **Example Workflow:** + ```bash # Terminal 1: Start Synkronus server locally ./synkronus # Running on localhost:8080 @@ -397,6 +435,7 @@ This setup allows you to develop and test the full ODE stack locally without dep ### Other ODE Development Tasks For ODE-specific development, you can now: + - Install Formulus APK files for testing - View logs from Synkronus server interactions - Debug custom applications built with ODE @@ -410,6 +449,6 @@ For ODE-specific development, you can now: ## Need Help? If you encounter issues not covered here, please: + 1. Check the [Android Developer Forums](https://developer.android.com/studio/intro/community) 2. Reach out to the ODE community at [hello@opendataensemble.org](mailto:hello@opendataensemble.org) - diff --git a/docs/For-developers/docusaurus/tutorial-extras/manage-docs-versions.md b/docs/For-developers/docusaurus/tutorial-extras/manage-docs-versions.md index e48782f..ede8e2f 100644 --- a/docs/For-developers/docusaurus/tutorial-extras/manage-docs-versions.md +++ b/docs/For-developers/docusaurus/tutorial-extras/manage-docs-versions.md @@ -35,7 +35,7 @@ export default { items: [ // highlight-start { - type: 'docsVersionDropdown', + type: "docsVersionDropdown", }, // highlight-end ], diff --git a/docs/ODE.md b/docs/ODE.md index cb13da2..94d6906 100644 --- a/docs/ODE.md +++ b/docs/ODE.md @@ -14,6 +14,7 @@ The source code for the pre-release version of ODE is now publicly available! Wh **Get involved:** Reach out to us at [hello@opendataensemble.org](mailto:hello@opendataensemble.org) - we'd love to hear from you! **Source Code:** Our mono repo on GitHub contains the source code for: + - **formulus**: React Native application for mobile data collection - **formplayer**: React project for form interaction - **synkronus**: Go-based server backend @@ -21,7 +22,7 @@ The source code for the pre-release version of ODE is now publicly available! Wh Visit our repository: [https://github.com/OpenDataEnsemble/ode](https://github.com/OpenDataEnsemble/ode) -*Reference implementation projects will be added as they become available.* +_Reference implementation projects will be added as they become available._ ::: @@ -29,9 +30,9 @@ Visit our repository: [https://github.com/OpenDataEnsemble/ode](https://github.c ODE stands out through its: -* **Simplicity & Efficiency:** Quickly create complex, validated forms using a powerful yet intuitive JSON-based approach. -* **Advanced Offline Sync:** Reliable and conflict-resilient synchronization powered by [WatermelonDB](https://watermelondb.dev). -* **Flexible & Extensible UI:** Customize form presentation and interaction effortlessly with [JSON Forms](https://jsonforms.io), enabling rich, interactive user experiences. +- **Simplicity & Efficiency:** Quickly create complex, validated forms using a powerful yet intuitive JSON-based approach. +- **Advanced Offline Sync:** Reliable and conflict-resilient synchronization powered by [WatermelonDB](https://watermelondb.dev). +- **Flexible & Extensible UI:** Customize form presentation and interaction effortlessly with [JSON Forms](https://jsonforms.io), enabling rich, interactive user experiences. Inspired by pioneering open-source projects, ODE leverages cutting-edge frameworks to deliver unparalleled ease-of-use and flexibility, especially suited for challenging environments where reliable offline performance is crucial. @@ -43,9 +44,9 @@ Here's an overview of the current members of the ensemble: Component overview -* [formulus](/docs/documentation/formulus/): The Android and iOS app for data collection and form interaction. -* [synkronus](/docs/documentation/synkronus/): The robust server backend managing synchronization and data storage. -* [synkronus-cli](/docs/documentation/synkronus-cli/cli): Command-line interface for convenient server management and administrative tasks. +- [formulus](/docs/documentation/formulus/): The Android and iOS app for data collection and form interaction. +- [synkronus](/docs/documentation/synkronus/): The robust server backend managing synchronization and data storage. +- [synkronus-cli](/docs/documentation/synkronus-cli/cli): Command-line interface for convenient server management and administrative tasks. :::tip[Ready to get started?] @@ -55,8 +56,7 @@ Check out the [Quick Start guide](/docs/quick-start)! ODE is a platform for building sophisticated data collection instruments. - - \ No newline at end of file +This is Facebook blue ! --> diff --git a/docs/community/_category_.json b/docs/community/_category_.json index d41a22d..8a81fd9 100644 --- a/docs/community/_category_.json +++ b/docs/community/_category_.json @@ -2,4 +2,3 @@ "label": "Community", "position": 8 } - diff --git a/docs/community/contribute/about.md b/docs/community/contribute/about.md index 2138d54..b083614 100644 --- a/docs/community/contribute/about.md +++ b/docs/community/contribute/about.md @@ -22,4 +22,3 @@ How to contribute to ODE. - [First Time Contributors](/docs/community/contribute/first-time) - [Code of Conduct](/docs/community/contribute/code-of-conduct) - diff --git a/docs/community/contribute/code-of-conduct.md b/docs/community/contribute/code-of-conduct.md index c0a1d0a..4fcc2a6 100644 --- a/docs/community/contribute/code-of-conduct.md +++ b/docs/community/contribute/code-of-conduct.md @@ -22,4 +22,3 @@ Code of conduct for the ODE community. - [About Contributions](/docs/community/contribute/about) - [First Time Contributors](/docs/community/contribute/first-time) - diff --git a/docs/community/contribute/first-time.md b/docs/community/contribute/first-time.md index 1557c22..12b36c6 100644 --- a/docs/community/contribute/first-time.md +++ b/docs/community/contribute/first-time.md @@ -22,4 +22,3 @@ Guide for first-time contributors to ODE. - [About Contributions](/docs/community/contribute/about) - [Code of Conduct](/docs/community/contribute/code-of-conduct) - diff --git a/docs/community/index.md b/docs/community/index.md index 795a41a..5a7b237 100644 --- a/docs/community/index.md +++ b/docs/community/index.md @@ -32,4 +32,3 @@ Join the ODE community to contribute, get help, and stay updated. subtitle="Projects built by the ODE community" /> - diff --git a/docs/community/resources/examples.md b/docs/community/resources/examples.md index b49844b..dfd9749 100644 --- a/docs/community/resources/examples.md +++ b/docs/community/resources/examples.md @@ -22,4 +22,3 @@ Example ODE applications and configurations. - [Community Projects](/docs/community/resources/projects) - [Tutorials](/docs/tutorials/getting-started/first-form) - diff --git a/docs/community/resources/projects.md b/docs/community/resources/projects.md index e874944..f14035e 100644 --- a/docs/community/resources/projects.md +++ b/docs/community/resources/projects.md @@ -22,4 +22,3 @@ Projects built by the ODE community. - [Examples](/docs/community/resources/examples) - [Contribute](/docs/community/contribute/about) - diff --git a/docs/community/support/getting-help.md b/docs/community/support/getting-help.md index 3a5b021..cc63a20 100644 --- a/docs/community/support/getting-help.md +++ b/docs/community/support/getting-help.md @@ -22,4 +22,3 @@ Where to get help with ODE. - [Reporting Issues](/docs/community/support/reporting-issues) - [FAQ](/docs/quick-start/faq) - diff --git a/docs/community/support/reporting-issues.md b/docs/community/support/reporting-issues.md index f6e32fb..ee00317 100644 --- a/docs/community/support/reporting-issues.md +++ b/docs/community/support/reporting-issues.md @@ -26,4 +26,3 @@ How to report bugs and issues. - [Getting Help](/docs/community/support/getting-help) - [GitHub Issues](https://github.com/OpenDataEnsemble/ode/issues) - diff --git a/docs/components/_category_.json b/docs/components/_category_.json index 67eb80b..52e6a48 100644 --- a/docs/components/_category_.json +++ b/docs/components/_category_.json @@ -2,4 +2,3 @@ "label": "Components", "position": 4 } - diff --git a/docs/components/formplayer/integration.md b/docs/components/formplayer/integration.md index c9a83c6..533fc00 100644 --- a/docs/components/formplayer/integration.md +++ b/docs/components/formplayer/integration.md @@ -22,4 +22,3 @@ Integrate Formplayer into your custom applications. - [Formplayer Overview](/docs/components/formplayer/overview) - [Custom Applications](/docs/build/custom-applications/overview) - diff --git a/docs/components/formplayer/overview.md b/docs/components/formplayer/overview.md index 5cf9169..4741974 100644 --- a/docs/components/formplayer/overview.md +++ b/docs/components/formplayer/overview.md @@ -25,4 +25,3 @@ Formplayer is a React-based component that renders forms using JSON Forms. - [JSON Forms](/docs/technical-overview/concepts/json-forms) - [Form Design](/docs/build/forms/design/ui-schema) - diff --git a/docs/components/formulus/configuration.md b/docs/components/formulus/configuration.md index f168da1..e31ebb3 100644 --- a/docs/components/formulus/configuration.md +++ b/docs/components/formulus/configuration.md @@ -26,4 +26,3 @@ Configure Formulus to connect to your Synkronus server. - [Installation](/docs/components/formulus/installation) - [Features](/docs/components/formulus/features) - diff --git a/docs/components/formulus/features.md b/docs/components/formulus/features.md index 44d9141..7ee6ec9 100644 --- a/docs/components/formulus/features.md +++ b/docs/components/formulus/features.md @@ -26,4 +26,3 @@ Key features of the Formulus mobile application. - [Formulus Overview](/docs/components/formulus/overview) - [Custom Applications](/docs/build/custom-applications/overview) - diff --git a/docs/components/formulus/installation.md b/docs/components/formulus/installation.md index 14fb322..a9c7ea8 100644 --- a/docs/components/formulus/installation.md +++ b/docs/components/formulus/installation.md @@ -26,4 +26,3 @@ Install Formulus on Android or iOS devices. - [Configuration](/docs/components/formulus/configuration) - [Quick Start](/docs/quick-start/formulus-app) - diff --git a/docs/components/formulus/integration.md b/docs/components/formulus/integration.md index f6ebd90..017afa4 100644 --- a/docs/components/formulus/integration.md +++ b/docs/components/formulus/integration.md @@ -22,4 +22,3 @@ Integrate custom applications with Formulus. - [Custom Applications](/docs/build/custom-applications/overview) - [Formulus Features](/docs/components/formulus/features) - diff --git a/docs/components/formulus/overview.md b/docs/components/formulus/overview.md index cd971a0..fc58851 100644 --- a/docs/components/formulus/overview.md +++ b/docs/components/formulus/overview.md @@ -27,4 +27,3 @@ Formulus is the mobile application component of ODE, available for Android and i - [Formulus Documentation](/docs/documentation/formulus/formulus) - [Quick Start Guide](/docs/quick-start/formulus-app) - diff --git a/docs/components/formulus/troubleshooting.md b/docs/components/formulus/troubleshooting.md index 2cb4813..1bbce68 100644 --- a/docs/components/formulus/troubleshooting.md +++ b/docs/components/formulus/troubleshooting.md @@ -22,4 +22,3 @@ Common issues and solutions for Formulus. - [Configuration](/docs/components/formulus/configuration) - [Synchronization Troubleshooting](/docs/build/synchronization/troubleshooting) - diff --git a/docs/components/synkronus-cli/commands-reference.md b/docs/components/synkronus-cli/commands-reference.md index 8206057..20b1b34 100644 --- a/docs/components/synkronus-cli/commands-reference.md +++ b/docs/components/synkronus-cli/commands-reference.md @@ -26,4 +26,3 @@ Complete reference for Synkronus CLI commands. - [Synkronus CLI Documentation](/docs/documentation/synkronus-cli/cli) - [App Bundle Management](/docs/build/custom-applications/deployment) - diff --git a/docs/components/synkronus-cli/installation.md b/docs/components/synkronus-cli/installation.md index d94c189..56fa8e7 100644 --- a/docs/components/synkronus-cli/installation.md +++ b/docs/components/synkronus-cli/installation.md @@ -22,4 +22,3 @@ Install the Synkronus CLI tool. - [Commands Reference](/docs/components/synkronus-cli/commands-reference) - [Synkronus CLI Documentation](/docs/documentation/synkronus-cli/cli) - diff --git a/docs/components/synkronus-cli/overview.md b/docs/components/synkronus-cli/overview.md index 1322ddb..919219f 100644 --- a/docs/components/synkronus-cli/overview.md +++ b/docs/components/synkronus-cli/overview.md @@ -26,4 +26,3 @@ Synkronus CLI is a command-line tool for interacting with Synkronus servers. - [Synkronus CLI Documentation](/docs/documentation/synkronus-cli/cli) - [Quick Start Guide](/docs/quick-start/synkronus-server) - diff --git a/docs/components/synkronus/api-reference.md b/docs/components/synkronus/api-reference.md index b005fd9..8eddb2a 100644 --- a/docs/components/synkronus/api-reference.md +++ b/docs/components/synkronus/api-reference.md @@ -22,4 +22,3 @@ Complete API reference for Synkronus. - [REST API Documentation](/docs/reference/rest-api/overview) - [OpenAPI Specification](/api) - diff --git a/docs/components/synkronus/configuration.md b/docs/components/synkronus/configuration.md index 7a85866..500bc2a 100644 --- a/docs/components/synkronus/configuration.md +++ b/docs/components/synkronus/configuration.md @@ -26,4 +26,3 @@ Configure Synkronus server settings. - [Installation](/docs/components/synkronus/installation) - [API Reference](/docs/components/synkronus/api-reference) - diff --git a/docs/components/synkronus/installation.md b/docs/components/synkronus/installation.md index 5dfab39..f1bf022 100644 --- a/docs/components/synkronus/installation.md +++ b/docs/components/synkronus/installation.md @@ -26,4 +26,3 @@ Install and set up Synkronus server. - [Configuration](/docs/components/synkronus/configuration) - [Quick Start](/docs/quick-start/synkronus-server) - diff --git a/docs/components/synkronus/overview.md b/docs/components/synkronus/overview.md index 1f19f4d..c4c2ce4 100644 --- a/docs/components/synkronus/overview.md +++ b/docs/components/synkronus/overview.md @@ -28,4 +28,3 @@ Synkronus is the server component of ODE, built in Go, that handles data synchro - [Synkronus Documentation](/docs/documentation/synkronus/synkronus) - [Quick Start Guide](/docs/quick-start/synkronus-server) - diff --git a/docs/documentation/formulus/formulus.md b/docs/documentation/formulus/formulus.md index 46b4de4..8859e9a 100644 --- a/docs/documentation/formulus/formulus.md +++ b/docs/documentation/formulus/formulus.md @@ -1,73 +1,75 @@ ---- -sidebar_position: 1 ---- - -# ODE Formulus - -Formulus is an offline-first mobile app available for Android and iOS that enables seamless data collection in environments with limited connectivity. It allows users to collect data offline and synchronize it with a `synkronus` server when connectivity is restored. The app also displays your custom application as the main entry point, providing a tailored user experience. - -## Installation - -:::caution Early Development Phase -Formulus is currently in early development. The app is only available for Android and requires installation via Android Debug Bridge (adb). -::: - -You can download the latest version from the GitHub releases page (available after the first alpha release) and install it on your Android device using the following command: - -```bash -adb install formulus.apk -``` - -**System Requirements:** -- Android 7.0 (API level 24) or higher -- Developer options enabled on your device -- USB debugging enabled - -We are actively working to make the app available through official app stores for both Android and iOS platforms. - -## Usage - -### Initial Setup - -When you first launch Formulus, you'll be prompted to connect to your `synkronus` server: - -1. **Server Configuration**: Enter your server URL and credentials -2. **Authentication**: Log in with the username and password you created in your synkronus instance -3. **Synchronization**: The app will download your custom application specification, including: - - Form definitions and schemas - - UI render packs (powered by [jsonforms](https://jsonforms.io/)) - - Custom styling and branding - -### Main Interface - -Once authenticated, Formulus displays your custom application as the primary interface, providing seamless access to your data collection workflows. - -## Key Features - -Formulus serves as a comprehensive wrapper around your custom application, providing essential mobile data collection capabilities: - -- **Offline-First Architecture**: Collect data without internet connectivity -- **Automatic Synchronization**: Seamlessly sync with your `synkronus` server when online -- **Advanced Form Rendering**: Powered by jsonforms with support for: - - Native device features (camera, GPS, file storage) - - Rich input types and validation - - Custom UI components -- **Robust Data Management**: Secure local storage with conflict resolution -- **Cross-Platform Compatibility**: Consistent experience across Android and iOS - -## Using Formulus without a Custom App - -:::warning Alpha Feature -This feature is currently in alpha development and may be unstable. Use with caution in production environments. -::: - -Formulus can operate in standalone mode without requiring a custom application. To use this feature: - -1. **Download and Install**: Follow the installation instructions above -2. **Server Connection**: Log in directly to your `synkronus` server using your credentials -3. **Form Access**: Formulus will automatically display a list of all forms available in your synkronus instance - -This mode is ideal for: -- **Quick prototyping** and testing form designs -- **Simple data collection** workflows that don't require custom UI -- **Getting started** with ODE before developing a full custom application +--- +sidebar_position: 1 +--- + +# ODE Formulus + +Formulus is an offline-first mobile app available for Android and iOS that enables seamless data collection in environments with limited connectivity. It allows users to collect data offline and synchronize it with a `synkronus` server when connectivity is restored. The app also displays your custom application as the main entry point, providing a tailored user experience. + +## Installation + +:::caution Early Development Phase +Formulus is currently in early development. The app is only available for Android and requires installation via Android Debug Bridge (adb). +::: + +You can download the latest version from the GitHub releases page (available after the first alpha release) and install it on your Android device using the following command: + +```bash +adb install formulus.apk +``` + +**System Requirements:** + +- Android 7.0 (API level 24) or higher +- Developer options enabled on your device +- USB debugging enabled + +We are actively working to make the app available through official app stores for both Android and iOS platforms. + +## Usage + +### Initial Setup + +When you first launch Formulus, you'll be prompted to connect to your `synkronus` server: + +1. **Server Configuration**: Enter your server URL and credentials +2. **Authentication**: Log in with the username and password you created in your synkronus instance +3. **Synchronization**: The app will download your custom application specification, including: + - Form definitions and schemas + - UI render packs (powered by [jsonforms](https://jsonforms.io/)) + - Custom styling and branding + +### Main Interface + +Once authenticated, Formulus displays your custom application as the primary interface, providing seamless access to your data collection workflows. + +## Key Features + +Formulus serves as a comprehensive wrapper around your custom application, providing essential mobile data collection capabilities: + +- **Offline-First Architecture**: Collect data without internet connectivity +- **Automatic Synchronization**: Seamlessly sync with your `synkronus` server when online +- **Advanced Form Rendering**: Powered by jsonforms with support for: + - Native device features (camera, GPS, file storage) + - Rich input types and validation + - Custom UI components +- **Robust Data Management**: Secure local storage with conflict resolution +- **Cross-Platform Compatibility**: Consistent experience across Android and iOS + +## Using Formulus without a Custom App + +:::warning Alpha Feature +This feature is currently in alpha development and may be unstable. Use with caution in production environments. +::: + +Formulus can operate in standalone mode without requiring a custom application. To use this feature: + +1. **Download and Install**: Follow the installation instructions above +2. **Server Connection**: Log in directly to your `synkronus` server using your credentials +3. **Form Access**: Formulus will automatically display a list of all forms available in your synkronus instance + +This mode is ideal for: + +- **Quick prototyping** and testing form designs +- **Simple data collection** workflows that don't require custom UI +- **Getting started** with ODE before developing a full custom application diff --git a/docs/documentation/synkronus-cli/cli.md b/docs/documentation/synkronus-cli/cli.md index 37c05df..78d7527 100644 --- a/docs/documentation/synkronus-cli/cli.md +++ b/docs/documentation/synkronus-cli/cli.md @@ -1,51 +1,56 @@ ---- -sidebar_position: 1 ---- - -# Synkronus CLI - -The Synkronus CLI is a tool for interacting with the Synkronus server. -It is used to authenticate, upload and download the custom_app as well as data and attachments. - -## Installation - -```bash -//Todo -``` - -## Usage - -```javascript -//Todo -``` - - -The completion command in the Synkronus CLI is a feature provided by Cobra, the CLI framework being used. It generates shell completion scripts for different shells, including PowerShell. Here's how to use it: - -For PowerShell Completion: -Generate the completion script: Run this command to generate the completion script for PowerShell: -```powershell -# For the current session only -.\synk.exe completion powershell > synk_completion.ps1 -. .\synk_completion.ps1 -``` -To make it permanent, add the following to your PowerShell profile: -```powershell -# Add this to your $PROFILE -Register-ArgumentCompleter -Native -CommandName synk.exe -ScriptBlock { - param($wordToComplete, $commandAst, $cursorPosition) - $completions = @(synk.exe completion --shell powershell -- "$wordToComplete" "$($commandAst.ToString().Split() | Select-Object -Skip 1)") - $completions | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) } -} -``` - -To find your PowerShell profile location, run: -```powershell -CopyInsert in Terminal -$PROFILE -``` -Reload your profile: -```powershell -CopyInsert in Terminal -. $PROFILE -``` \ No newline at end of file +--- +sidebar_position: 1 +--- + +# Synkronus CLI + +The Synkronus CLI is a tool for interacting with the Synkronus server. +It is used to authenticate, upload and download the custom_app as well as data and attachments. + +## Installation + +```bash +//Todo +``` + +## Usage + +```javascript +//Todo +``` + +The completion command in the Synkronus CLI is a feature provided by Cobra, the CLI framework being used. It generates shell completion scripts for different shells, including PowerShell. Here's how to use it: + +For PowerShell Completion: +Generate the completion script: Run this command to generate the completion script for PowerShell: + +```powershell +# For the current session only +.\synk.exe completion powershell > synk_completion.ps1 +. .\synk_completion.ps1 +``` + +To make it permanent, add the following to your PowerShell profile: + +```powershell +# Add this to your $PROFILE +Register-ArgumentCompleter -Native -CommandName synk.exe -ScriptBlock { + param($wordToComplete, $commandAst, $cursorPosition) + $completions = @(synk.exe completion --shell powershell -- "$wordToComplete" "$($commandAst.ToString().Split() | Select-Object -Skip 1)") + $completions | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) } +} +``` + +To find your PowerShell profile location, run: + +```powershell +CopyInsert in Terminal +$PROFILE +``` + +Reload your profile: + +```powershell +CopyInsert in Terminal +. $PROFILE +``` diff --git a/docs/documentation/synkronus/app-bundle.md b/docs/documentation/synkronus/app-bundle.md index 7041c3f..400191c 100644 --- a/docs/documentation/synkronus/app-bundle.md +++ b/docs/documentation/synkronus/app-bundle.md @@ -1,223 +1,253 @@ -# App Bundle API Documentation - -## Overview -The App Bundle API provides endpoints for managing custom application bundles, including form specifications and custom renderers. This documentation explains the core concepts and available endpoints. - -## Core Concepts - -### App Bundle Structure -An app bundle is a ZIP file containing: - -1. **Form Specifications** (required): - - Located in `/forms/{form_name}/` - - Each form requires two files: - - `schema.json`: The JSON Schema definition for the form - - `ui.json`: The UI configuration for the form - -2. **Custom Renderers** (optional): - - Located in `/renderers/` - - Custom question types referenced by UI schemas - -### Core Fields -Forms may include special fields that are considered part of the core entity: - -- Fields prefixed with `core_` (e.g., `core_id`, `core_name`) -- Fields marked with `"x-core": true` in the schema - -**Important Rules for Core Fields:** -- Core fields are immutable once created -- They form the unique identity of each form entry -- To modify core fields, you must create a new form and migrate data -- Non-core fields can be freely added, modified, or removed in new versions - -## API Endpoints - -### 1. Get Changes Between Versions -`GET /app-bundle/changes` - -Compare two versions of an app bundle to see what has changed. - -**Query Parameters:** -- `current`: (optional) The current version (defaults to latest) -- `target`: (optional) The target version to compare against (defaults to previous version) - -**Response:** -- `200`: Returns a `ChangeLog` object with detailed changes -- `400`: Invalid version format or parameters -- `404`: One or both versions not found - -### 2. Get Current Manifest -`GET /app-bundle/manifest` - -Retrieve the current app bundle's file list and metadata. - -**Response Headers:** -- `ETag`: Hash of the manifest for caching - -**Response:** -- `200`: Returns an `AppBundleManifest` object - -### 3. Download File -`GET /app-bundle/download/{path}` - -Download a specific file from the app bundle. - -**Path Parameters:** -- `path`: Path to the file within the bundle - -**Query Parameters:** -- `preview`: (boolean, default: false) If true, gets the file from the latest version including unreleased changes - -**Headers:** -- `If-None-Match`: Optional ETag for conditional requests - -**Responses:** -- `200`: File content -- `304`: Not Modified - -### 4. List Available Versions -`GET /app-bundle/versions` - -Get a list of all available app bundle versions. - -**Response:** -- `200`: Returns an `AppBundleVersions` object with version list - -### 5. Upload New Bundle (Admin Only) -`POST /app-bundle/push` - -Upload a new version of the app bundle. - -**Request Body:** -- `bundle`: (multipart/form-data) ZIP file containing the new app bundle - -**Responses:** -- `200`: Bundle successfully uploaded -- `400`: Bad request -- `401`: Unauthorized -- `403`: Admin role required -- `413`: File too large - -### 6. Switch Version (Admin Only) -`POST /app-bundle/switch/{version}` - -Switch the active app bundle to a specific version. - -**Path Parameters:** -- `version`: The version identifier to switch to - -**Responses:** -- `200`: Successfully switched versions -- `400`: Bad request -- `401`: Unauthorized -- `403`: Admin role required -- `404`: Version not found - -## Versioning - -### API Versioning -- All endpoints support an optional `X-API-Version` header -- Format: `MAJOR.MINOR.PATCH` (e.g., `1.0.0`) -- Follows semantic versioning principles - -### App Bundle Versioning -- Each upload creates a new version -- Versions are immutable once created -- The system maintains a history of all versions -- Only one version can be active at a time - -## Best Practices - -1. **Form Design**: - - Carefully plan your core fields as they cannot be changed - - Use descriptive names for all fields - - Document your form structure and field purposes - -2. **Version Management**: - - Test new versions thoroughly before switching - - Version numbers will be assigned by synkronus (0001, 0002, etc. ...) - - Maintain backward compatibility when possible - -## Error Handling - -All error responses follow a consistent format: - -```json -{ - "type": "string", - "title": "string", - "status": 0, - "detail": "string", - "instance": "string" -} -``` - -Common error statuses include: -- `400`: Bad request (invalid input) -- `401`: Unauthorized -- `403`: Forbidden (missing permissions) -- `404`: Resource not found -- `413`: Payload too large -- `500`: Internal server error - -## Using the CLI to handle app-bundle - -The `synkronus-cli` provides a powerful command-line interface for managing app bundles, making it easy to interact with the App Bundle API. Key features include: -- **Uploading** new app bundle versions with a single command -- **Downloading** specific versions or the latest bundle -- **Switching** between different versions of your app bundle -- **Viewing** the current active version and available versions -- **Comparing** changes between different versions -- **Managing** form specifications and custom renderers through simple commands - -The CLI handles authentication, version tracking, and file operations, providing a streamlined workflow for development and deployment. All operations can be performed with simple, intuitive commands, and support both interactive and scripted usage patterns. - -### CLI Examples - -#### Upload a new app bundle version -```bash -# Upload a new version from a ZIP file -synkronus-cli app-bundle upload ./my-app-bundle.zip - -# Upload with a specific version number -synkronus-cli app-bundle upload ./my-app-bundle.zip --version 1.2.3 -``` - -#### List and manage versions - -```bash -# List all available versions -synkronus-cli app-bundle versions - -# Show current active version -synkronus-cli app-bundle current - -# Switch to a specific version -synkronus-cli app-bundle switch 1.2.3 -``` - -#### Download and inspect bundles -```bash -# Download the latest version -synkronus-cli app-bundle download --output ./latest-bundle - -# Download a specific version -synkronus-cli app-bundle download --version 1.2.3 --output ./v1.2.3-bundle - -# Compare changes between versions -synkronus-cli app-bundle diff 1.2.2 1.2.3 -``` - -#### Form management -```bash -# List all forms in the current bundle -synkronus-cli app-bundle forms list - -# Get details for a specific form -synkronus-cli app-bundle forms show my-form - -# Validate a form schema -synkronus-cli app-bundle forms validate ./my-form/schema.json -``` - -These examples demonstrate common workflows. Use `synkronus-cli app-bundle --help` for a complete list of available commands and options. +# App Bundle API Documentation + +## Overview + +The App Bundle API provides endpoints for managing custom application bundles, including form specifications and custom renderers. This documentation explains the core concepts and available endpoints. + +## Core Concepts + +### App Bundle Structure + +An app bundle is a ZIP file containing: + +1. **Form Specifications** (required): + - Located in `/forms/{form_name}/` + - Each form requires two files: + - `schema.json`: The JSON Schema definition for the form + - `ui.json`: The UI configuration for the form + +2. **Custom Renderers** (optional): + - Located in `/renderers/` + - Custom question types referenced by UI schemas + +### Core Fields + +Forms may include special fields that are considered part of the core entity: + +- Fields prefixed with `core_` (e.g., `core_id`, `core_name`) +- Fields marked with `"x-core": true` in the schema + +**Important Rules for Core Fields:** + +- Core fields are immutable once created +- They form the unique identity of each form entry +- To modify core fields, you must create a new form and migrate data +- Non-core fields can be freely added, modified, or removed in new versions + +## API Endpoints + +### 1. Get Changes Between Versions + +`GET /app-bundle/changes` + +Compare two versions of an app bundle to see what has changed. + +**Query Parameters:** + +- `current`: (optional) The current version (defaults to latest) +- `target`: (optional) The target version to compare against (defaults to previous version) + +**Response:** + +- `200`: Returns a `ChangeLog` object with detailed changes +- `400`: Invalid version format or parameters +- `404`: One or both versions not found + +### 2. Get Current Manifest + +`GET /app-bundle/manifest` + +Retrieve the current app bundle's file list and metadata. + +**Response Headers:** + +- `ETag`: Hash of the manifest for caching + +**Response:** + +- `200`: Returns an `AppBundleManifest` object + +### 3. Download File + +`GET /app-bundle/download/{path}` + +Download a specific file from the app bundle. + +**Path Parameters:** + +- `path`: Path to the file within the bundle + +**Query Parameters:** + +- `preview`: (boolean, default: false) If true, gets the file from the latest version including unreleased changes + +**Headers:** + +- `If-None-Match`: Optional ETag for conditional requests + +**Responses:** + +- `200`: File content +- `304`: Not Modified + +### 4. List Available Versions + +`GET /app-bundle/versions` + +Get a list of all available app bundle versions. + +**Response:** + +- `200`: Returns an `AppBundleVersions` object with version list + +### 5. Upload New Bundle (Admin Only) + +`POST /app-bundle/push` + +Upload a new version of the app bundle. + +**Request Body:** + +- `bundle`: (multipart/form-data) ZIP file containing the new app bundle + +**Responses:** + +- `200`: Bundle successfully uploaded +- `400`: Bad request +- `401`: Unauthorized +- `403`: Admin role required +- `413`: File too large + +### 6. Switch Version (Admin Only) + +`POST /app-bundle/switch/{version}` + +Switch the active app bundle to a specific version. + +**Path Parameters:** + +- `version`: The version identifier to switch to + +**Responses:** + +- `200`: Successfully switched versions +- `400`: Bad request +- `401`: Unauthorized +- `403`: Admin role required +- `404`: Version not found + +## Versioning + +### API Versioning + +- All endpoints support an optional `X-API-Version` header +- Format: `MAJOR.MINOR.PATCH` (e.g., `1.0.0`) +- Follows semantic versioning principles + +### App Bundle Versioning + +- Each upload creates a new version +- Versions are immutable once created +- The system maintains a history of all versions +- Only one version can be active at a time + +## Best Practices + +1. **Form Design**: + - Carefully plan your core fields as they cannot be changed + - Use descriptive names for all fields + - Document your form structure and field purposes + +2. **Version Management**: + - Test new versions thoroughly before switching + - Version numbers will be assigned by synkronus (0001, 0002, etc. ...) + - Maintain backward compatibility when possible + +## Error Handling + +All error responses follow a consistent format: + +```json +{ + "type": "string", + "title": "string", + "status": 0, + "detail": "string", + "instance": "string" +} +``` + +Common error statuses include: + +- `400`: Bad request (invalid input) +- `401`: Unauthorized +- `403`: Forbidden (missing permissions) +- `404`: Resource not found +- `413`: Payload too large +- `500`: Internal server error + +## Using the CLI to handle app-bundle + +The `synkronus-cli` provides a powerful command-line interface for managing app bundles, making it easy to interact with the App Bundle API. Key features include: + +- **Uploading** new app bundle versions with a single command +- **Downloading** specific versions or the latest bundle +- **Switching** between different versions of your app bundle +- **Viewing** the current active version and available versions +- **Comparing** changes between different versions +- **Managing** form specifications and custom renderers through simple commands + +The CLI handles authentication, version tracking, and file operations, providing a streamlined workflow for development and deployment. All operations can be performed with simple, intuitive commands, and support both interactive and scripted usage patterns. + +### CLI Examples + +#### Upload a new app bundle version + +```bash +# Upload a new version from a ZIP file +synkronus-cli app-bundle upload ./my-app-bundle.zip + +# Upload with a specific version number +synkronus-cli app-bundle upload ./my-app-bundle.zip --version 1.2.3 +``` + +#### List and manage versions + +```bash +# List all available versions +synkronus-cli app-bundle versions + +# Show current active version +synkronus-cli app-bundle current + +# Switch to a specific version +synkronus-cli app-bundle switch 1.2.3 +``` + +#### Download and inspect bundles + +```bash +# Download the latest version +synkronus-cli app-bundle download --output ./latest-bundle + +# Download a specific version +synkronus-cli app-bundle download --version 1.2.3 --output ./v1.2.3-bundle + +# Compare changes between versions +synkronus-cli app-bundle diff 1.2.2 1.2.3 +``` + +#### Form management + +```bash +# List all forms in the current bundle +synkronus-cli app-bundle forms list + +# Get details for a specific form +synkronus-cli app-bundle forms show my-form + +# Validate a form schema +synkronus-cli app-bundle forms validate ./my-form/schema.json +``` + +These examples demonstrate common workflows. Use `synkronus-cli app-bundle --help` for a complete list of available commands and options. diff --git a/docs/documentation/synkronus/synkronus.md b/docs/documentation/synkronus/synkronus.md index d81c657..2540fcc 100644 --- a/docs/documentation/synkronus/synkronus.md +++ b/docs/documentation/synkronus/synkronus.md @@ -1,63 +1,63 @@ ---- -sidebar_position: 1 ---- - -# synkronus - -synkronus is the core backend server for the OpenDataEnsemble (ODE) ecosystem, built in Go. It serves as the central synchronization hub that enables seamless data exchange between your custom applications and Formulus mobile clients. The server provides a comprehensive REST API (documented in `synkronus.yaml`) that handles authentication, data management, and real-time synchronization across multiple devices and platforms. - -## Installation & Setup - -:::info Development Status -During development, synkronus is provided as a single executable Go binary and requires a separate PostgreSQL instance. We are actively working on a comprehensive Docker image for easier deployment. -::: - -### Prerequisites - -- **PostgreSQL Database**: A running PostgreSQL instance (version 12 or higher recommended) -- **Go Runtime**: Go 1.19+ if building from source - -### Development Setup - -1. **Database Setup**: Ensure PostgreSQL is running and accessible -2. **Configuration**: Set up your database connection and server configuration -3. **Run synkronus**: Execute the Go binary with appropriate environment variables - -```bash -# Example configuration (adjust for your environment) -export DATABASE_URL="postgres://username:password@localhost:5432/synkronus" -export SERVER_PORT="8080" -./synkronus -``` - -## API Documentation - -The complete synkronus REST API is documented in the `synkronus.yaml` OpenAPI specification. Key endpoints include: - -- **Authentication**: User login and session management -- **Data Synchronization**: Bidirectional sync of form data and attachments -- **Application Management**: Deploy and version custom applications -- **Form Management**: Create, update, and manage form specifications - -### Basic Usage Example - -```bash -# Authenticate with the server -curl -X POST http://localhost:8080/auth/login \ - -H "Content-Type: application/json" \ - -d '{"username": "your_username", "password": "your_password"}' - -# Sync form data -curl -X GET http://localhost:8080/api/v1/data/forms \ - -H "Authorization: Bearer YOUR_TOKEN" -``` - -## Architecture - -synkronus follows a modular architecture designed for scalability and reliability: - -- **RESTful API**: Clean, versioned API endpoints for all operations -- **PostgreSQL Integration**: Robust data persistence with ACID compliance -- **Conflict Resolution**: Intelligent handling of offline data synchronization conflicts -- **Versioning System**: Built-in versioning for applications, forms, and render packs -- **Security**: JWT-based authentication with role-based access control +--- +sidebar_position: 1 +--- + +# synkronus + +synkronus is the core backend server for the OpenDataEnsemble (ODE) ecosystem, built in Go. It serves as the central synchronization hub that enables seamless data exchange between your custom applications and Formulus mobile clients. The server provides a comprehensive REST API (documented in `synkronus.yaml`) that handles authentication, data management, and real-time synchronization across multiple devices and platforms. + +## Installation & Setup + +:::info Development Status +During development, synkronus is provided as a single executable Go binary and requires a separate PostgreSQL instance. We are actively working on a comprehensive Docker image for easier deployment. +::: + +### Prerequisites + +- **PostgreSQL Database**: A running PostgreSQL instance (version 12 or higher recommended) +- **Go Runtime**: Go 1.19+ if building from source + +### Development Setup + +1. **Database Setup**: Ensure PostgreSQL is running and accessible +2. **Configuration**: Set up your database connection and server configuration +3. **Run synkronus**: Execute the Go binary with appropriate environment variables + +```bash +# Example configuration (adjust for your environment) +export DATABASE_URL="postgres://username:password@localhost:5432/synkronus" +export SERVER_PORT="8080" +./synkronus +``` + +## API Documentation + +The complete synkronus REST API is documented in the `synkronus.yaml` OpenAPI specification. Key endpoints include: + +- **Authentication**: User login and session management +- **Data Synchronization**: Bidirectional sync of form data and attachments +- **Application Management**: Deploy and version custom applications +- **Form Management**: Create, update, and manage form specifications + +### Basic Usage Example + +```bash +# Authenticate with the server +curl -X POST http://localhost:8080/auth/login \ + -H "Content-Type: application/json" \ + -d '{"username": "your_username", "password": "your_password"}' + +# Sync form data +curl -X GET http://localhost:8080/api/v1/data/forms \ + -H "Authorization: Bearer YOUR_TOKEN" +``` + +## Architecture + +synkronus follows a modular architecture designed for scalability and reliability: + +- **RESTful API**: Clean, versioned API endpoints for all operations +- **PostgreSQL Integration**: Robust data persistence with ACID compliance +- **Conflict Resolution**: Intelligent handling of offline data synchronization conflicts +- **Versioning System**: Built-in versioning for applications, forms, and render packs +- **Security**: JWT-based authentication with role-based access control diff --git a/docs/host/_category_.json b/docs/host/_category_.json index e871295..46dbe48 100644 --- a/docs/host/_category_.json +++ b/docs/host/_category_.json @@ -2,4 +2,3 @@ "label": "Host", "position": 5 } - diff --git a/docs/host/data-management.md b/docs/host/data-management.md index 60e35be..f851c25 100644 --- a/docs/host/data-management.md +++ b/docs/host/data-management.md @@ -26,4 +26,3 @@ Manage data in production environments. - [Backups](/docs/host/synkronus-server/backups) - [Database Schema](/docs/technical-overview/database/schema) - diff --git a/docs/host/index.md b/docs/host/index.md index 2001662..0116952 100644 --- a/docs/host/index.md +++ b/docs/host/index.md @@ -32,4 +32,3 @@ This section provides guides for hosting Synkronus servers, monitoring, and mana subtitle="Security best practices for ODE deployments" /> - diff --git a/docs/host/monitoring/overview.md b/docs/host/monitoring/overview.md index 7aad2a0..5b6b8bb 100644 --- a/docs/host/monitoring/overview.md +++ b/docs/host/monitoring/overview.md @@ -22,4 +22,3 @@ Monitor and alert on ODE system health. - [Server Monitoring](/docs/host/synkronus-server/monitoring) - [Production Monitoring](/docs/host/monitoring/production) - diff --git a/docs/host/monitoring/production.md b/docs/host/monitoring/production.md index 49b2eb7..a15cbaf 100644 --- a/docs/host/monitoring/production.md +++ b/docs/host/monitoring/production.md @@ -22,4 +22,3 @@ Monitor production ODE deployments. - [Monitoring Setup](/docs/host/monitoring/setup) - [Server Monitoring](/docs/host/synkronus-server/monitoring) - diff --git a/docs/host/monitoring/setup.md b/docs/host/monitoring/setup.md index f24794b..11abd4a 100644 --- a/docs/host/monitoring/setup.md +++ b/docs/host/monitoring/setup.md @@ -22,4 +22,3 @@ Set up monitoring for ODE. - [Monitoring Overview](/docs/host/monitoring/overview) - [Production Monitoring](/docs/host/monitoring/production) - diff --git a/docs/host/security.md b/docs/host/security.md index a5478f3..f50b9c5 100644 --- a/docs/host/security.md +++ b/docs/host/security.md @@ -26,4 +26,3 @@ Security best practices for ODE deployments. - [Users & Authentication](/docs/build/users-authentication) - [Production Deployment](/docs/host/synkronus-server/production) - diff --git a/docs/host/synkronus-server/backups.md b/docs/host/synkronus-server/backups.md index a394192..c5bdf5f 100644 --- a/docs/host/synkronus-server/backups.md +++ b/docs/host/synkronus-server/backups.md @@ -22,4 +22,3 @@ Backup strategies for Synkronus. - [Data Management](/docs/host/data-management) - [Production Deployment](/docs/host/synkronus-server/production) - diff --git a/docs/host/synkronus-server/cloud.md b/docs/host/synkronus-server/cloud.md index 69c454f..408a639 100644 --- a/docs/host/synkronus-server/cloud.md +++ b/docs/host/synkronus-server/cloud.md @@ -22,4 +22,3 @@ Deploy Synkronus on cloud platforms. - [Production Deployment](/docs/host/synkronus-server/production) - [Docker Deployment](/docs/host/synkronus-server/docker) - diff --git a/docs/host/synkronus-server/docker.md b/docs/host/synkronus-server/docker.md index f07ab9d..4d7bda1 100644 --- a/docs/host/synkronus-server/docker.md +++ b/docs/host/synkronus-server/docker.md @@ -22,4 +22,3 @@ Deploy Synkronus using Docker. - [Production Deployment](/docs/host/synkronus-server/production) - [Requirements](/docs/host/synkronus-server/requirements) - diff --git a/docs/host/synkronus-server/kubernetes.md b/docs/host/synkronus-server/kubernetes.md index c07b33a..0929ab9 100644 --- a/docs/host/synkronus-server/kubernetes.md +++ b/docs/host/synkronus-server/kubernetes.md @@ -22,4 +22,3 @@ Deploy Synkronus on Kubernetes. - [Production Deployment](/docs/host/synkronus-server/production) - [Requirements](/docs/host/synkronus-server/requirements) - diff --git a/docs/host/synkronus-server/monitoring.md b/docs/host/synkronus-server/monitoring.md index 7feb07a..9c6cf8a 100644 --- a/docs/host/synkronus-server/monitoring.md +++ b/docs/host/synkronus-server/monitoring.md @@ -22,4 +22,3 @@ Monitor Synkronus server health and performance. - [Monitoring & Alerting](/docs/host/monitoring/overview) - [Production Deployment](/docs/host/synkronus-server/production) - diff --git a/docs/host/synkronus-server/overview.md b/docs/host/synkronus-server/overview.md index c9b4003..184eca2 100644 --- a/docs/host/synkronus-server/overview.md +++ b/docs/host/synkronus-server/overview.md @@ -24,4 +24,3 @@ Host Synkronus in production environments. - [Requirements](/docs/host/synkronus-server/requirements) - [Production Deployment](/docs/host/synkronus-server/production) - diff --git a/docs/host/synkronus-server/production.md b/docs/host/synkronus-server/production.md index be8182b..59e091c 100644 --- a/docs/host/synkronus-server/production.md +++ b/docs/host/synkronus-server/production.md @@ -22,4 +22,3 @@ Deploy Synkronus in production. - [Docker Deployment](/docs/host/synkronus-server/docker) - [Monitoring](/docs/host/monitoring/overview) - diff --git a/docs/host/synkronus-server/requirements.md b/docs/host/synkronus-server/requirements.md index 007237b..0051cbb 100644 --- a/docs/host/synkronus-server/requirements.md +++ b/docs/host/synkronus-server/requirements.md @@ -26,4 +26,3 @@ System requirements for hosting Synkronus. - [Docker Deployment](/docs/host/synkronus-server/docker) - [Production Deployment](/docs/host/synkronus-server/production) - diff --git a/docs/quick-start/custom-app.md b/docs/quick-start/custom-app.md index 3457277..4f5e111 100644 --- a/docs/quick-start/custom-app.md +++ b/docs/quick-start/custom-app.md @@ -1,9 +1,9 @@ ---- -sidebar_position: 4 ---- - -# Making it yours - -## Add forms - -## Start with the reference app \ No newline at end of file +--- +sidebar_position: 4 +--- + +# Making it yours + +## Add forms + +## Start with the reference app diff --git a/docs/quick-start/deploy-local-instance.md b/docs/quick-start/deploy-local-instance.md index 1f905b2..0cb7d8c 100644 --- a/docs/quick-start/deploy-local-instance.md +++ b/docs/quick-start/deploy-local-instance.md @@ -58,4 +58,3 @@ docker-compose ps - [Upload Test Data](/docs/quick-start/upload-test-data) - [Connect Formulus](/docs/components/formulus/configuration) - diff --git a/docs/quick-start/faq.md b/docs/quick-start/faq.md index b795e60..0334712 100644 --- a/docs/quick-start/faq.md +++ b/docs/quick-start/faq.md @@ -43,4 +43,3 @@ See the [Formulus configuration guide](/docs/components/formulus/configuration). ### Common issues and solutions [Answer placeholder] - diff --git a/docs/quick-start/formulus-app.md b/docs/quick-start/formulus-app.md index fe435fd..0c052f9 100644 --- a/docs/quick-start/formulus-app.md +++ b/docs/quick-start/formulus-app.md @@ -1,272 +1,272 @@ ---- -sidebar_position: 4 ---- - -# Formulus App Setup - -Build and run the Formulus Android app on a physical device or emulator. - -## Prerequisites - -Before starting, ensure: - -- [ ] Android device connected via USB (or emulator running) -- [ ] USB debugging enabled on device -- [ ] ADB recognizes your device -- [ ] Server is running (see [Synkronus Server Setup](/docs/quick-start/synkronus-server)) - -## Step 1: Verify Device Connection - -Check that your device is recognized: - -```bash -adb devices -``` - -**Expected output:** - -``` -List of devices attached -YCYNW18209009206 device -``` - -If no devices appear: - -1. Enable **Developer Options** on your Android device: - - Go to Settings → About Phone - - Tap "Build Number" 7 times - -2. Enable **USB Debugging**: - - Go to Settings → Developer Options - - Enable "USB Debugging" - -3. Accept the USB debugging prompt on your device - -4. Try again: - - ```bash - adb devices - ``` - -## Step 2: Navigate to Formulus Directory - -```bash -cd formulus -``` - -## Step 3: Start Metro Bundler (Optional but Recommended) - -In a separate terminal, start the Metro bundler: - -```bash -cd formulus -npm start -``` - -Keep this terminal open. Metro is the JavaScript bundler for React Native. - -**Alternative:** Metro will start automatically when you run the app, but starting it manually gives you better control. - -## Step 4: Build and Run Android App - -Build and install the app on your connected device: - -```bash -npm run android -``` - -**What this does:** - -1. Compiles the Android app -2. Builds the APK -3. Installs it on your device -4. Starts the app -5. Connects to Metro bundler - -**Expected output:** - -``` -> formulus-app@0.0.1 android -> react-native run-android - -info Installing the app... -... -Installing APK 'formulus-v1.0-1-debug-20251211.apk' on 'FIG-LX1 - 8.0.0' for :app:debug -Installed on 1 device. -info Connecting to the development server... -info Starting the app on "YCYNW18209009206"... -``` - -## Step 5: Verify App is Running - -The app should automatically open on your device. You should see: - -- Formulus splash screen -- Main app interface -- No connection errors (yet - we'll configure the server next) - -## Building for Different Scenarios - -### Build Only (Don't Install) - -```bash -cd formulus/android -./gradlew assembleDebug -``` - -The APK will be at: - -``` -formulus/android/app/build/outputs/apk/debug/formulus-v1.0-1-debug-YYYYMMDD.apk -``` - -### Install on Specific Device - -```bash -adb -s DEVICE_ID install -r path/to/app.apk -``` - -### Run on Emulator - -```bash -# Start emulator first -emulator -avd YOUR_AVD_NAME - -# Then run -npm run android -``` - -## Development Workflow - -### Hot Reload - -The app supports Fast Refresh. When you save a file: - -- **JavaScript changes** - Automatically reload -- **Native changes** - Require app restart - -### Reload Manually - -- **Shake device** → Select "Reload" -- **Or** Press `R` twice in Metro terminal -- **Or** Press `Ctrl+M` (Windows/Linux) or `Cmd+M` (Mac) → Select "Reload" - -### Debug Menu - -Access the developer menu: - -- **Shake device** -- **Or** `adb shell input keyevent 82` (Menu key) -- **Or** `Ctrl+M` / `Cmd+M` - -## Configuring the App - -### Option A: Scan QR Code (Recommended) - -1. **Generate QR code** using Synkronus CLI (see [QR Code Login](/docs/components/formulus/configuration#qr-code-login)) -2. **Open Formulus app** on your device -3. **Tap "Scan QR Code"** on the welcome/settings screen -4. **Point camera** at the QR code -5. **Settings auto-populate** - Server URL, username, password -6. **Tap "Connect"** to verify and save - -### Option B: Manual Configuration - -1. **Open Formulus app** -2. **Go to Settings** (gear icon or menu) -3. **Enter Server URL**: `http://YOUR_SERVER_IP` (e.g., `http://192.168.100.7`) -4. **Enter Username**: Your username -5. **Enter Password**: Your password -6. **Tap "Test Connection"** to verify -7. **Tap "Save"** - -**Important:** Use your computer's IP address (not `localhost`) since your Android device is on a different machine. - -### Finding Your Server IP - -```bash -# Linux -hostname -I | awk '{print $1}' - -# macOS -ifconfig | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | head -1 -``` - -## Troubleshooting - -### Issue: "No devices/emulators found" - -**Solutions:** - -```bash -# Restart ADB -adb kill-server -adb start-server - -# Check devices -adb devices - -# Verify USB debugging is enabled -``` - -### Issue: Build fails with lint errors - -**Solution:** For development, you can skip lint: - -```bash -cd formulus/android -./gradlew assembleDebug -x lintDebug -x lintRelease -``` - -### Issue: "Metro bundler not found" - -**Solution:** Start Metro manually: - -```bash -cd formulus -npm start -``` - -Then in another terminal: - -```bash -npm run android -``` - -### Issue: App crashes on startup - -**Check:** - -1. Metro bundler is running -2. Device and computer are on the same network (for Metro) -3. Check device logs: - - ```bash - adb logcat | grep -i "reactnative\|formulus" - ``` - -### Issue: "Unable to resolve module" - -**Solution:** - -```bash -cd formulus -rm -rf node_modules -npm install -npm start -- --reset-cache -``` - -## Next Steps - -Now that the app is running: - -1. **Configure the server connection** (see above) -2. **Login** with your credentials -3. **Sync app bundle** to download forms -4. **Start collecting data!** - -For more details, see: - -- [Formulus Configuration](/docs/components/formulus/configuration) -- [Using Formulus App](/docs/components/formulus/features) -- [Troubleshooting](/docs/components/formulus/troubleshooting) +--- +sidebar_position: 4 +--- + +# Formulus App Setup + +Build and run the Formulus Android app on a physical device or emulator. + +## Prerequisites + +Before starting, ensure: + +- [ ] Android device connected via USB (or emulator running) +- [ ] USB debugging enabled on device +- [ ] ADB recognizes your device +- [ ] Server is running (see [Synkronus Server Setup](/docs/quick-start/synkronus-server)) + +## Step 1: Verify Device Connection + +Check that your device is recognized: + +```bash +adb devices +``` + +**Expected output:** + +``` +List of devices attached +YCYNW18209009206 device +``` + +If no devices appear: + +1. Enable **Developer Options** on your Android device: + - Go to Settings → About Phone + - Tap "Build Number" 7 times + +2. Enable **USB Debugging**: + - Go to Settings → Developer Options + - Enable "USB Debugging" + +3. Accept the USB debugging prompt on your device + +4. Try again: + + ```bash + adb devices + ``` + +## Step 2: Navigate to Formulus Directory + +```bash +cd formulus +``` + +## Step 3: Start Metro Bundler (Optional but Recommended) + +In a separate terminal, start the Metro bundler: + +```bash +cd formulus +npm start +``` + +Keep this terminal open. Metro is the JavaScript bundler for React Native. + +**Alternative:** Metro will start automatically when you run the app, but starting it manually gives you better control. + +## Step 4: Build and Run Android App + +Build and install the app on your connected device: + +```bash +npm run android +``` + +**What this does:** + +1. Compiles the Android app +2. Builds the APK +3. Installs it on your device +4. Starts the app +5. Connects to Metro bundler + +**Expected output:** + +``` +> formulus-app@0.0.1 android +> react-native run-android + +info Installing the app... +... +Installing APK 'formulus-v1.0-1-debug-20251211.apk' on 'FIG-LX1 - 8.0.0' for :app:debug +Installed on 1 device. +info Connecting to the development server... +info Starting the app on "YCYNW18209009206"... +``` + +## Step 5: Verify App is Running + +The app should automatically open on your device. You should see: + +- Formulus splash screen +- Main app interface +- No connection errors (yet - we'll configure the server next) + +## Building for Different Scenarios + +### Build Only (Don't Install) + +```bash +cd formulus/android +./gradlew assembleDebug +``` + +The APK will be at: + +``` +formulus/android/app/build/outputs/apk/debug/formulus-v1.0-1-debug-YYYYMMDD.apk +``` + +### Install on Specific Device + +```bash +adb -s DEVICE_ID install -r path/to/app.apk +``` + +### Run on Emulator + +```bash +# Start emulator first +emulator -avd YOUR_AVD_NAME + +# Then run +npm run android +``` + +## Development Workflow + +### Hot Reload + +The app supports Fast Refresh. When you save a file: + +- **JavaScript changes** - Automatically reload +- **Native changes** - Require app restart + +### Reload Manually + +- **Shake device** → Select "Reload" +- **Or** Press `R` twice in Metro terminal +- **Or** Press `Ctrl+M` (Windows/Linux) or `Cmd+M` (Mac) → Select "Reload" + +### Debug Menu + +Access the developer menu: + +- **Shake device** +- **Or** `adb shell input keyevent 82` (Menu key) +- **Or** `Ctrl+M` / `Cmd+M` + +## Configuring the App + +### Option A: Scan QR Code (Recommended) + +1. **Generate QR code** using Synkronus CLI (see [QR Code Login](/docs/components/formulus/configuration#qr-code-login)) +2. **Open Formulus app** on your device +3. **Tap "Scan QR Code"** on the welcome/settings screen +4. **Point camera** at the QR code +5. **Settings auto-populate** - Server URL, username, password +6. **Tap "Connect"** to verify and save + +### Option B: Manual Configuration + +1. **Open Formulus app** +2. **Go to Settings** (gear icon or menu) +3. **Enter Server URL**: `http://YOUR_SERVER_IP` (e.g., `http://192.168.100.7`) +4. **Enter Username**: Your username +5. **Enter Password**: Your password +6. **Tap "Test Connection"** to verify +7. **Tap "Save"** + +**Important:** Use your computer's IP address (not `localhost`) since your Android device is on a different machine. + +### Finding Your Server IP + +```bash +# Linux +hostname -I | awk '{print $1}' + +# macOS +ifconfig | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | head -1 +``` + +## Troubleshooting + +### Issue: "No devices/emulators found" + +**Solutions:** + +```bash +# Restart ADB +adb kill-server +adb start-server + +# Check devices +adb devices + +# Verify USB debugging is enabled +``` + +### Issue: Build fails with lint errors + +**Solution:** For development, you can skip lint: + +```bash +cd formulus/android +./gradlew assembleDebug -x lintDebug -x lintRelease +``` + +### Issue: "Metro bundler not found" + +**Solution:** Start Metro manually: + +```bash +cd formulus +npm start +``` + +Then in another terminal: + +```bash +npm run android +``` + +### Issue: App crashes on startup + +**Check:** + +1. Metro bundler is running +2. Device and computer are on the same network (for Metro) +3. Check device logs: + + ```bash + adb logcat | grep -i "reactnative\|formulus" + ``` + +### Issue: "Unable to resolve module" + +**Solution:** + +```bash +cd formulus +rm -rf node_modules +npm install +npm start -- --reset-cache +``` + +## Next Steps + +Now that the app is running: + +1. **Configure the server connection** (see above) +2. **Login** with your credentials +3. **Sync app bundle** to download forms +4. **Start collecting data!** + +For more details, see: + +- [Formulus Configuration](/docs/components/formulus/configuration) +- [Using Formulus App](/docs/components/formulus/features) +- [Troubleshooting](/docs/components/formulus/troubleshooting) diff --git a/docs/quick-start/formulus-prerelease-android.md b/docs/quick-start/formulus-prerelease-android.md index f462b45..41e5922 100644 --- a/docs/quick-start/formulus-prerelease-android.md +++ b/docs/quick-start/formulus-prerelease-android.md @@ -10,14 +10,18 @@ This guide will walk you through installing the pre-release version of the Formu ## What You'll Need ### F-Droid + **F-Droid** is an open-source app store for Android that focuses on free and open-source software (FOSS). Unlike the Google Play Store, F-Droid: + - Doesn't require a Google account - Respects your privacy (no tracking) - Only hosts open-source applications - Provides transparent app information and build processes ### Obtainium + **Obtainium** allows you to install and update apps directly from their source code repositories (like GitHub). Benefits include: + - Get updates directly from developers, often faster than app stores - Access pre-release and beta versions - No intermediary app store required @@ -97,6 +101,7 @@ When you first open Formulus, you'll see the welcome screen. To get started, tap ## Keeping Formulus Updated Obtainium will automatically check for new pre-release versions of Formulus. When an update is available: + 1. You'll receive a notification from Obtainium 2. Open Obtainium and tap on Formulus 3. Tap **"Update"** to download and install the latest version @@ -106,18 +111,23 @@ You can also manually check for updates by opening Obtainium and pulling down to ## Troubleshooting ### Can't Install from Unknown Sources + If you're unable to install F-Droid or apps from Obtainium, you may need to enable installation from unknown sources: + - Go to **Settings** > **Security** (or **Apps**) - Find and enable **"Install unknown apps"** or **"Unknown sources"** - Grant permission for your browser (for F-Droid) and Obtainium ### F-Droid Repository Not Loading + If F-Droid's repository isn't loading: + - Ensure you have a stable internet connection - Try force-closing and reopening F-Droid - Go to **Settings** in F-Droid and tap **"Repositories"**, then pull down to refresh ### Obtainium Can't Find the App + Make sure you've typed the repository name correctly: **`OpenDataEnsemble/ode`** If issues persist, you can try entering the full GitHub URL: **`https://github.com/OpenDataEnsemble/ode`** diff --git a/docs/quick-start/index.md b/docs/quick-start/index.md index e210f9f..67e258c 100644 --- a/docs/quick-start/index.md +++ b/docs/quick-start/index.md @@ -1,49 +1,49 @@ ---- -sidebar_position: 1 ---- - -# Quick Start - -Get started with ODE in minutes. - -## Overview - -This section will help you set up your development environment and deploy your first ODE instance. - - - - - - - -## Installation Guides - - - - - - \ No newline at end of file +--- +sidebar_position: 1 +--- + +# Quick Start + +Get started with ODE in minutes. + +## Overview + +This section will help you set up your development environment and deploy your first ODE instance. + + + + + + + +## Installation Guides + + + + + + diff --git a/docs/quick-start/prerequisites.md b/docs/quick-start/prerequisites.md index 9c3b6b2..9c92d52 100644 --- a/docs/quick-start/prerequisites.md +++ b/docs/quick-start/prerequisites.md @@ -52,22 +52,26 @@ Before proceeding, verify you have the following installed: ### Essential Tools - [ ] **Git** (v2.30+) + ```bash git --version ``` - [ ] **Node.js** (v16.0.0 or higher) + ```bash node --version npm --version ``` - [ ] **Go** (v1.22 or higher) + ```bash go version ``` - [ ] **Docker** (v20.10+) + ```bash docker --version docker compose version @@ -146,4 +150,3 @@ Custom applications are built using JavaScript or TypeScript. A good understandi ### PostgreSQL ODE uses PostgreSQL for data storage. Familiarity with SQL and PostgreSQL is useful for data management and analytics. - diff --git a/docs/quick-start/setup-environment.md b/docs/quick-start/setup-environment.md index 4473418..bd8a529 100644 --- a/docs/quick-start/setup-environment.md +++ b/docs/quick-start/setup-environment.md @@ -48,6 +48,7 @@ git remote -v ``` You should see: + ``` origin https://github.com/YOUR_USERNAME/ode.git (fetch) origin https://github.com/YOUR_USERNAME/ode.git (push) @@ -177,6 +178,7 @@ ls -la formulus/assets/webview/ ``` You should see: + - `FormulusInjectionScript.js` - `formulus-api.js` - `formulus-load.js` @@ -271,4 +273,3 @@ Once your environment is set up: 1. **Proceed to** [Synkronus Server Setup](/docs/quick-start/synkronus-server) to configure Docker and the database 2. **Or** continue with [Deploy Local Instance](/docs/quick-start/deploy-local-instance) - diff --git a/docs/quick-start/synkronus-server.md b/docs/quick-start/synkronus-server.md index a71dec4..3558f48 100644 --- a/docs/quick-start/synkronus-server.md +++ b/docs/quick-start/synkronus-server.md @@ -1,324 +1,330 @@ ---- -sidebar_position: 3 ---- - -# Synkronus Server Setup - -Set up the Synkronus server using Docker Compose, including PostgreSQL database and Nginx reverse proxy. - -## Overview - -The server setup uses Docker Compose to run three services: - -1. **PostgreSQL** - Database server -2. **Synkronus** - Go API server -3. **Nginx** - Reverse proxy (all traffic routes through nginx) - -All services communicate through Docker's internal network, with only Nginx exposed to the host. - -## Architecture - -``` -┌─────────────────────────────────────────┐ -│ Docker Network │ -│ │ -│ ┌──────────┐ ┌──────────────┐ │ -│ │ Nginx │──────▶│ Synkronus │ │ -│ │ :80 │ │ :8080 │ │ -│ └────┬─────┘ └──────┬──────┘ │ -│ │ │ │ -│ │ │ │ -│ │ ┌────────▼──────┐ │ -│ │ │ PostgreSQL │ │ -│ │ │ :5432 │ │ -│ │ └──────────────┘ │ -│ │ │ -└───────┼─────────────────────────────────┘ - │ - │ Port 80 (exposed) - │ - ┌────▼────┐ - │ Host │ - │ Machine │ - └─────────┘ -``` - -## Step 1: Navigate to Synkronus Directory - -```bash -cd synkronus -``` - -## Step 2: Create Docker Compose Configuration - -Copy the example configuration: - -```bash -cp docker-compose.example.yml docker-compose.yml -``` - -## Step 3: Configure Docker Compose - -Edit `docker-compose.yml` and update the following values: - -### Required Configuration - -1. **PostgreSQL Password** (line 78): - ```yaml - POSTGRES_PASSWORD: "YourSecurePassword" - ``` - -2. **Database Connection** (line 48): - ```yaml - DB_CONNECTION: "postgres://synkronus_user:YourPassword@postgres:5432/synkronus?sslmode=disable" - ``` - Replace `YourPassword` with the same password you'll use for the database user. - -3. **JWT Secret** (line 51): - ```yaml - JWT_SECRET: "YourRandom32CharacterString" - ``` - Generate a secure secret: - ```bash - openssl rand -base64 32 - ``` - -4. **Admin Password** (line 53): - ```yaml - ADMIN_PASSWORD: "YourAdminPassword" - ``` - -### Example Configuration - -```yaml -services: - postgres: - environment: - POSTGRES_PASSWORD: "Password" - - synkronus: - environment: - DB_CONNECTION: "postgres://synkronus_user:Password@postgres:5432/synkronus?sslmode=disable" - JWT_SECRET: "YourGeneratedSecretHere" - ADMIN_PASSWORD: "Password" -``` - -## Step 4: Start PostgreSQL - -Start the PostgreSQL container first: - -```bash -docker compose up -d postgres -``` - -Wait a few seconds for PostgreSQL to initialize: - -```bash -sleep 5 -``` - -## Step 5: Create Database and User - -Create the database user and database: - -```bash -# Create user (ignore error if already exists) -docker compose exec -T postgres psql -U postgres -c "CREATE ROLE synkronus_user LOGIN PASSWORD 'Password';" 2>&1 || echo "User may already exist" - -# Create database (ignore error if already exists) -docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE synkronus OWNER synkronus_user;" 2>&1 || echo "Database may already exist" -``` - -**Note:** Replace `Password` with the password you configured in `docker-compose.yml`. - -## Step 6: Start All Services - -Start all services (PostgreSQL, Synkronus, and Nginx): - -```bash -docker compose up -d -``` - -## Step 7: Verify Services - -Check that all services are running: - -```bash -docker compose ps -``` - -**Expected output:** - -``` -NAME STATUS -synkronus-nginx-1 Up (healthy) -synkronus-postgres-1 Up (healthy) -synkronus-synkronus-1 Up (healthy) -``` - -## Step 8: Test Server Health - -Test the health endpoint through nginx: - -```bash -curl http://localhost/health -``` - -**Expected output:** - -``` -OK -``` - -## Service Management - -### View All Services - -```bash -docker compose ps -``` - -### View Logs - -```bash -# All services -docker compose logs -f - -# Specific service -docker compose logs -f synkronus -docker compose logs -f nginx -docker compose logs -f postgres -``` - -### Restart Services - -```bash -# Restart all -docker compose restart - -# Restart specific service -docker compose restart synkronus -``` - -### Stop Services - -```bash -docker compose stop -``` - -### Start Services - -```bash -docker compose start -``` - -### Stop and Remove (Keep Data) - -```bash -docker compose down -``` - -### Stop and Remove Everything (Including Data) - -```bash -docker compose down -v -``` - -**⚠️ Warning:** The `-v` flag removes volumes, including your database data! - -## Network Configuration - -### Finding Your Local IP Address - -For connecting from mobile devices, you'll need your machine's IP address: - -```bash -# Linux -hostname -I | awk '{print $1}' - -# macOS -ifconfig | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | head -1 -``` - -**Example output:** - -``` -192.168.100.7 -``` - -### Accessing from Mobile Device - -The server will be accessible at: - -``` -http://YOUR_IP_ADDRESS -``` - -For example: - -``` -http://192.168.100.7 -``` - -## Troubleshooting - -### Issue: Port 80 already in use - -**Solution:** Stop the service using port 80: - -```bash -sudo lsof -i :80 -sudo kill -9 -``` - -Or change nginx port in `docker-compose.yml`: - -```yaml -ports: - - "8080:80" # Use port 8080 instead -``` - -### Issue: Database connection fails - -**Check:** - -1. PostgreSQL is running: `docker compose ps postgres` -2. Database exists: `docker compose exec postgres psql -U postgres -l` -3. Connection string matches: Check `DB_CONNECTION` in `docker-compose.yml` - -### Issue: Synkronus won't start - -**Check logs:** - -```bash -docker compose logs synkronus -``` - -**Common causes:** - -- Database not ready (wait a few seconds) -- Wrong database credentials -- Missing JWT_SECRET - -### Issue: Nginx returns 502 Bad Gateway - -**Check:** - -1. Synkronus is running: `docker compose ps synkronus` -2. Synkronus is healthy: `docker compose logs synkronus | tail -20` -3. Network connectivity: Services are on the same Docker network - -## Verification Checklist - -- [ ] All three services are running (`docker compose ps`) -- [ ] Health endpoint returns OK (`curl http://localhost/health`) -- [ ] No errors in logs (`docker compose logs`) -- [ ] Can access from localhost -- [ ] Know your local IP address for mobile access - -## Next Steps - -Now that your server is running: - -1. **Proceed to** [Formulus App Setup](/docs/quick-start/formulus-app) to configure and run the Android app -2. **Or** continue with [Synkronus CLI Setup](/docs/components/synkronus-cli/installation) for server management +--- +sidebar_position: 3 +--- + +# Synkronus Server Setup + +Set up the Synkronus server using Docker Compose, including PostgreSQL database and Nginx reverse proxy. + +## Overview + +The server setup uses Docker Compose to run three services: + +1. **PostgreSQL** - Database server +2. **Synkronus** - Go API server +3. **Nginx** - Reverse proxy (all traffic routes through nginx) + +All services communicate through Docker's internal network, with only Nginx exposed to the host. + +## Architecture + +``` +┌─────────────────────────────────────────┐ +│ Docker Network │ +│ │ +│ ┌──────────┐ ┌──────────────┐ │ +│ │ Nginx │──────▶│ Synkronus │ │ +│ │ :80 │ │ :8080 │ │ +│ └────┬─────┘ └──────┬──────┘ │ +│ │ │ │ +│ │ │ │ +│ │ ┌────────▼──────┐ │ +│ │ │ PostgreSQL │ │ +│ │ │ :5432 │ │ +│ │ └──────────────┘ │ +│ │ │ +└───────┼─────────────────────────────────┘ + │ + │ Port 80 (exposed) + │ + ┌────▼────┐ + │ Host │ + │ Machine │ + └─────────┘ +``` + +## Step 1: Navigate to Synkronus Directory + +```bash +cd synkronus +``` + +## Step 2: Create Docker Compose Configuration + +Copy the example configuration: + +```bash +cp docker-compose.example.yml docker-compose.yml +``` + +## Step 3: Configure Docker Compose + +Edit `docker-compose.yml` and update the following values: + +### Required Configuration + +1. **PostgreSQL Password** (line 78): + + ```yaml + POSTGRES_PASSWORD: "YourSecurePassword" + ``` + +2. **Database Connection** (line 48): + + ```yaml + DB_CONNECTION: "postgres://synkronus_user:YourPassword@postgres:5432/synkronus?sslmode=disable" + ``` + + Replace `YourPassword` with the same password you'll use for the database user. + +3. **JWT Secret** (line 51): + + ```yaml + JWT_SECRET: "YourRandom32CharacterString" + ``` + + Generate a secure secret: + + ```bash + openssl rand -base64 32 + ``` + +4. **Admin Password** (line 53): + ```yaml + ADMIN_PASSWORD: "YourAdminPassword" + ``` + +### Example Configuration + +```yaml +services: + postgres: + environment: + POSTGRES_PASSWORD: "Password" + + synkronus: + environment: + DB_CONNECTION: "postgres://synkronus_user:Password@postgres:5432/synkronus?sslmode=disable" + JWT_SECRET: "YourGeneratedSecretHere" + ADMIN_PASSWORD: "Password" +``` + +## Step 4: Start PostgreSQL + +Start the PostgreSQL container first: + +```bash +docker compose up -d postgres +``` + +Wait a few seconds for PostgreSQL to initialize: + +```bash +sleep 5 +``` + +## Step 5: Create Database and User + +Create the database user and database: + +```bash +# Create user (ignore error if already exists) +docker compose exec -T postgres psql -U postgres -c "CREATE ROLE synkronus_user LOGIN PASSWORD 'Password';" 2>&1 || echo "User may already exist" + +# Create database (ignore error if already exists) +docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE synkronus OWNER synkronus_user;" 2>&1 || echo "Database may already exist" +``` + +**Note:** Replace `Password` with the password you configured in `docker-compose.yml`. + +## Step 6: Start All Services + +Start all services (PostgreSQL, Synkronus, and Nginx): + +```bash +docker compose up -d +``` + +## Step 7: Verify Services + +Check that all services are running: + +```bash +docker compose ps +``` + +**Expected output:** + +``` +NAME STATUS +synkronus-nginx-1 Up (healthy) +synkronus-postgres-1 Up (healthy) +synkronus-synkronus-1 Up (healthy) +``` + +## Step 8: Test Server Health + +Test the health endpoint through nginx: + +```bash +curl http://localhost/health +``` + +**Expected output:** + +``` +OK +``` + +## Service Management + +### View All Services + +```bash +docker compose ps +``` + +### View Logs + +```bash +# All services +docker compose logs -f + +# Specific service +docker compose logs -f synkronus +docker compose logs -f nginx +docker compose logs -f postgres +``` + +### Restart Services + +```bash +# Restart all +docker compose restart + +# Restart specific service +docker compose restart synkronus +``` + +### Stop Services + +```bash +docker compose stop +``` + +### Start Services + +```bash +docker compose start +``` + +### Stop and Remove (Keep Data) + +```bash +docker compose down +``` + +### Stop and Remove Everything (Including Data) + +```bash +docker compose down -v +``` + +**⚠️ Warning:** The `-v` flag removes volumes, including your database data! + +## Network Configuration + +### Finding Your Local IP Address + +For connecting from mobile devices, you'll need your machine's IP address: + +```bash +# Linux +hostname -I | awk '{print $1}' + +# macOS +ifconfig | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | head -1 +``` + +**Example output:** + +``` +192.168.100.7 +``` + +### Accessing from Mobile Device + +The server will be accessible at: + +``` +http://YOUR_IP_ADDRESS +``` + +For example: + +``` +http://192.168.100.7 +``` + +## Troubleshooting + +### Issue: Port 80 already in use + +**Solution:** Stop the service using port 80: + +```bash +sudo lsof -i :80 +sudo kill -9 +``` + +Or change nginx port in `docker-compose.yml`: + +```yaml +ports: + - "8080:80" # Use port 8080 instead +``` + +### Issue: Database connection fails + +**Check:** + +1. PostgreSQL is running: `docker compose ps postgres` +2. Database exists: `docker compose exec postgres psql -U postgres -l` +3. Connection string matches: Check `DB_CONNECTION` in `docker-compose.yml` + +### Issue: Synkronus won't start + +**Check logs:** + +```bash +docker compose logs synkronus +``` + +**Common causes:** + +- Database not ready (wait a few seconds) +- Wrong database credentials +- Missing JWT_SECRET + +### Issue: Nginx returns 502 Bad Gateway + +**Check:** + +1. Synkronus is running: `docker compose ps synkronus` +2. Synkronus is healthy: `docker compose logs synkronus | tail -20` +3. Network connectivity: Services are on the same Docker network + +## Verification Checklist + +- [ ] All three services are running (`docker compose ps`) +- [ ] Health endpoint returns OK (`curl http://localhost/health`) +- [ ] No errors in logs (`docker compose logs`) +- [ ] Can access from localhost +- [ ] Know your local IP address for mobile access + +## Next Steps + +Now that your server is running: + +1. **Proceed to** [Formulus App Setup](/docs/quick-start/formulus-app) to configure and run the Android app +2. **Or** continue with [Synkronus CLI Setup](/docs/components/synkronus-cli/installation) for server management diff --git a/docs/quick-start/upload-test-data.md b/docs/quick-start/upload-test-data.md index 979a96e..6a94494 100644 --- a/docs/quick-start/upload-test-data.md +++ b/docs/quick-start/upload-test-data.md @@ -32,4 +32,3 @@ curl -X POST http://localhost:8080/api/v1/data \ - [Create Your First Form](/docs/build/forms/overview) - [Build a Custom App](/docs/build/custom-applications/overview) - diff --git a/docs/quick-start/verification-testing.md b/docs/quick-start/verification-testing.md index 8c86f7b..cdba31a 100644 --- a/docs/quick-start/verification-testing.md +++ b/docs/quick-start/verification-testing.md @@ -239,4 +239,3 @@ Once everything is verified: 2. **Explore** [Formulus Features](/docs/components/formulus/features) 3. **Learn** about [Forms and Observations](/docs/build/forms/overview) 4. **Deploy** your own [Custom Applications](/docs/build/custom-applications/overview) - diff --git a/docs/reference/_category_.json b/docs/reference/_category_.json index 09e8aa8..3ce2f2b 100644 --- a/docs/reference/_category_.json +++ b/docs/reference/_category_.json @@ -2,4 +2,3 @@ "label": "Reference", "position": 6 } - diff --git a/docs/reference/app-bundle-format.md b/docs/reference/app-bundle-format.md index 6935551..4077a9d 100644 --- a/docs/reference/app-bundle-format.md +++ b/docs/reference/app-bundle-format.md @@ -26,4 +26,3 @@ Technical specification for app bundle format. - [App Bundle Structure](/docs/build/custom-applications/app-bundle-structure) - [App Bundle API](/docs/reference/rest-api/app-bundle) - diff --git a/docs/reference/configuration/client.md b/docs/reference/configuration/client.md index 70cd8fa..60af90e 100644 --- a/docs/reference/configuration/client.md +++ b/docs/reference/configuration/client.md @@ -22,4 +22,3 @@ Configuration options for ODE clients. - [Formulus Configuration](/docs/components/formulus/configuration) - [Custom Applications](/docs/build/custom-applications/overview) - diff --git a/docs/reference/configuration/server.md b/docs/reference/configuration/server.md index af32c33..61d3c23 100644 --- a/docs/reference/configuration/server.md +++ b/docs/reference/configuration/server.md @@ -22,4 +22,3 @@ Configuration options for Synkronus server. - [Synkronus Configuration](/docs/components/synkronus/configuration) - [Production Deployment](/docs/host/synkronus-server/production) - diff --git a/docs/reference/form-specifications.md b/docs/reference/form-specifications.md index 21b8154..67e1f8a 100644 --- a/docs/reference/form-specifications.md +++ b/docs/reference/form-specifications.md @@ -26,4 +26,3 @@ Technical specifications for ODE forms. - [Form Design](/docs/build/forms/design/schema-definition) - [JSON Forms](/docs/technical-overview/concepts/json-forms) - diff --git a/docs/reference/index.md b/docs/reference/index.md index 9c3d8be..1e92dcd 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -32,4 +32,3 @@ Complete reference documentation for ODE APIs and configurations. subtitle="Technical specification for app bundle format" /> - diff --git a/docs/reference/rest-api/app-bundle.md b/docs/reference/rest-api/app-bundle.md index e28f585..8ac6abe 100644 --- a/docs/reference/rest-api/app-bundle.md +++ b/docs/reference/rest-api/app-bundle.md @@ -22,4 +22,3 @@ API endpoints for managing app bundles. - [REST API Overview](/docs/reference/rest-api/overview) - [App Bundle Structure](/docs/build/custom-applications/app-bundle-structure) - diff --git a/docs/reference/rest-api/attachments.md b/docs/reference/rest-api/attachments.md index 443f29b..682c26e 100644 --- a/docs/reference/rest-api/attachments.md +++ b/docs/reference/rest-api/attachments.md @@ -22,4 +22,3 @@ API endpoints for managing file attachments. - [REST API Overview](/docs/reference/rest-api/overview) - [Data Management](/docs/build/data-management/attachments) - diff --git a/docs/reference/rest-api/authentication.md b/docs/reference/rest-api/authentication.md index f4b008c..2a89558 100644 --- a/docs/reference/rest-api/authentication.md +++ b/docs/reference/rest-api/authentication.md @@ -22,4 +22,3 @@ API endpoints for authentication. - [REST API Overview](/docs/reference/rest-api/overview) - [Users & Authentication](/docs/build/users-authentication) - diff --git a/docs/reference/rest-api/overview.md b/docs/reference/rest-api/overview.md index 194fde8..476dd44 100644 --- a/docs/reference/rest-api/overview.md +++ b/docs/reference/rest-api/overview.md @@ -29,4 +29,3 @@ Complete REST API reference for Synkronus. - [OpenAPI Specification](/api) - [Synkronus API Reference](/docs/components/synkronus/api-reference) - diff --git a/docs/reference/rest-api/sync.md b/docs/reference/rest-api/sync.md index 78a7cf8..77aa715 100644 --- a/docs/reference/rest-api/sync.md +++ b/docs/reference/rest-api/sync.md @@ -22,4 +22,3 @@ API endpoints for data synchronization. - [REST API Overview](/docs/reference/rest-api/overview) - [Synchronization Protocol](/docs/build/synchronization/sync-protocol) - diff --git a/docs/technical-overview/_category_.json b/docs/technical-overview/_category_.json index 5d412ad..d5d53b3 100644 --- a/docs/technical-overview/_category_.json +++ b/docs/technical-overview/_category_.json @@ -2,4 +2,3 @@ "label": "Technical Overview", "position": 2 } - diff --git a/docs/technical-overview/architecture/components.md b/docs/technical-overview/architecture/components.md index 2ee54db..8df18d3 100644 --- a/docs/technical-overview/architecture/components.md +++ b/docs/technical-overview/architecture/components.md @@ -29,4 +29,3 @@ Web-based form renderer using JSON Forms. Command-line interface for server management. [Learn more about Synkronus CLI](/docs/components/synkronus-cli/overview) - diff --git a/docs/technical-overview/architecture/data-flow.md b/docs/technical-overview/architecture/data-flow.md index 63825d8..46d1c5c 100644 --- a/docs/technical-overview/architecture/data-flow.md +++ b/docs/technical-overview/architecture/data-flow.md @@ -25,4 +25,3 @@ How data flows through the ODE system. - [Synchronization Protocol](/docs/build/synchronization/overview) - [Database Schema](/docs/technical-overview/database/schema) - diff --git a/docs/technical-overview/architecture/overview.md b/docs/technical-overview/architecture/overview.md index 07c6157..c7b2387 100644 --- a/docs/technical-overview/architecture/overview.md +++ b/docs/technical-overview/architecture/overview.md @@ -27,4 +27,3 @@ ODE consists of several key components: - [Formulus Architecture](/docs/components/formulus/overview) - [Synkronus Architecture](/docs/components/synkronus/overview) - diff --git a/docs/technical-overview/concepts/app-bundles.md b/docs/technical-overview/concepts/app-bundles.md index d30882b..1c473af 100644 --- a/docs/technical-overview/concepts/app-bundles.md +++ b/docs/technical-overview/concepts/app-bundles.md @@ -22,4 +22,3 @@ Applications are packaged as bundles for deployment. - [App Bundle API](/docs/reference/rest-api/app-bundle) - [Custom Applications](/docs/build/custom-applications/overview) - diff --git a/docs/technical-overview/concepts/custom-apps.md b/docs/technical-overview/concepts/custom-apps.md index 611a887..38447cb 100644 --- a/docs/technical-overview/concepts/custom-apps.md +++ b/docs/technical-overview/concepts/custom-apps.md @@ -22,4 +22,3 @@ Build custom web applications that integrate with ODE. - [Building Custom Apps](/docs/build/custom-applications/building) - [Formulus Integration](/docs/components/formulus/integration) - diff --git a/docs/technical-overview/concepts/json-forms.md b/docs/technical-overview/concepts/json-forms.md index d5b74d5..e051460 100644 --- a/docs/technical-overview/concepts/json-forms.md +++ b/docs/technical-overview/concepts/json-forms.md @@ -22,4 +22,3 @@ ODE uses JSON Forms for flexible form rendering. - [Form Design](/docs/build/forms/design/schema-definition) - [JSON Forms Documentation](https://jsonforms.io) - diff --git a/docs/technical-overview/concepts/offline-first.md b/docs/technical-overview/concepts/offline-first.md index 563c077..072d7fc 100644 --- a/docs/technical-overview/concepts/offline-first.md +++ b/docs/technical-overview/concepts/offline-first.md @@ -24,4 +24,3 @@ ODE is designed to work seamlessly in offline environments. - [Synchronization](/docs/build/synchronization/overview) - [Formulus Offline Features](/docs/components/formulus/features) - diff --git a/docs/technical-overview/concepts/overview.md b/docs/technical-overview/concepts/overview.md index 142525b..c9f6020 100644 --- a/docs/technical-overview/concepts/overview.md +++ b/docs/technical-overview/concepts/overview.md @@ -29,4 +29,3 @@ Applications are packaged as bundles containing forms, schemas, and custom code. ODE supports custom web applications that integrate with Formulus. [Learn more about Custom Applications](/docs/technical-overview/concepts/custom-apps) - diff --git a/docs/technical-overview/database/overview.md b/docs/technical-overview/database/overview.md index f00f478..628ad34 100644 --- a/docs/technical-overview/database/overview.md +++ b/docs/technical-overview/database/overview.md @@ -26,4 +26,3 @@ ODE uses PostgreSQL for server-side data storage and WatermelonDB for client-sid - [Database Schema](/docs/technical-overview/database/schema) - [Data Synchronization](/docs/build/synchronization/overview) - diff --git a/docs/technical-overview/database/schema.md b/docs/technical-overview/database/schema.md index 2bb4417..caab4af 100644 --- a/docs/technical-overview/database/schema.md +++ b/docs/technical-overview/database/schema.md @@ -22,4 +22,3 @@ Structure of the ODE database. - [Database Overview](/docs/technical-overview/database/overview) - [Data Management](/docs/build/data-management/overview) - diff --git a/docs/technical-overview/index.md b/docs/technical-overview/index.md index 13ce79e..0d2571c 100644 --- a/docs/technical-overview/index.md +++ b/docs/technical-overview/index.md @@ -23,4 +23,3 @@ Overview and architecture of ODE components. subtitle="Learn about data storage, management, and synchronization in ODE" /> - diff --git a/docs/tutorials/_category_.json b/docs/tutorials/_category_.json index b56af20..6e052e4 100644 --- a/docs/tutorials/_category_.json +++ b/docs/tutorials/_category_.json @@ -2,4 +2,3 @@ "label": "Tutorials", "position": 7 } - diff --git a/docs/tutorials/advanced/complex-forms.md b/docs/tutorials/advanced/complex-forms.md index 93d40e7..f473eb0 100644 --- a/docs/tutorials/advanced/complex-forms.md +++ b/docs/tutorials/advanced/complex-forms.md @@ -22,4 +22,3 @@ Build complex forms with advanced features. - [Form Design](/docs/build/forms/design/schema-definition) - [Advanced Features](/docs/build/forms/advanced-features/multimedia) - diff --git a/docs/tutorials/advanced/custom-renderers.md b/docs/tutorials/advanced/custom-renderers.md index 1ab9d2d..a227c54 100644 --- a/docs/tutorials/advanced/custom-renderers.md +++ b/docs/tutorials/advanced/custom-renderers.md @@ -22,4 +22,3 @@ Create custom form renderers for JSON Forms. - [Custom Renderers](/docs/build/custom-applications/custom-renderers) - [JSON Forms](/docs/technical-overview/concepts/json-forms) - diff --git a/docs/tutorials/advanced/performance.md b/docs/tutorials/advanced/performance.md index 4b9a44e..c73122d 100644 --- a/docs/tutorials/advanced/performance.md +++ b/docs/tutorials/advanced/performance.md @@ -22,4 +22,3 @@ Optimize ODE application performance. - [Database Performance](/docs/technical-overview/database/overview) - [Synchronization](/docs/build/synchronization/overview) - diff --git a/docs/tutorials/getting-started/connecting-everything.md b/docs/tutorials/getting-started/connecting-everything.md index 89d1806..bd6ff43 100644 --- a/docs/tutorials/getting-started/connecting-everything.md +++ b/docs/tutorials/getting-started/connecting-everything.md @@ -26,4 +26,3 @@ Connect Formulus, Synkronus, and your custom application. - [Formulus Configuration](/docs/components/formulus/configuration) - [Synkronus Configuration](/docs/components/synkronus/configuration) - diff --git a/docs/tutorials/getting-started/first-custom-app.md b/docs/tutorials/getting-started/first-custom-app.md index 39e2a80..d7b8bd3 100644 --- a/docs/tutorials/getting-started/first-custom-app.md +++ b/docs/tutorials/getting-started/first-custom-app.md @@ -26,4 +26,3 @@ Build your first custom application for ODE. - [Custom Applications](/docs/build/custom-applications/building) - [Connecting Everything](/docs/tutorials/getting-started/connecting-everything) - diff --git a/docs/tutorials/getting-started/first-form.md b/docs/tutorials/getting-started/first-form.md index 2ccdbd4..c53b7c0 100644 --- a/docs/tutorials/getting-started/first-form.md +++ b/docs/tutorials/getting-started/first-form.md @@ -26,4 +26,3 @@ Create your first data collection form in ODE. - [Form Design](/docs/build/forms/design/schema-definition) - [Your First Custom App](/docs/tutorials/getting-started/first-custom-app) - diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md index 824afd1..b90c1a4 100644 --- a/docs/tutorials/index.md +++ b/docs/tutorials/index.md @@ -42,4 +42,3 @@ Learn ODE through hands-on tutorials. subtitle="Optimize ODE application performance" /> - diff --git a/docusaurus.config.ts b/docusaurus.config.ts index b0a771a..ca313f9 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -1,165 +1,165 @@ -import {themes as prismThemes} from 'prism-react-renderer'; -import type {Config} from '@docusaurus/types'; -import type * as Preset from '@docusaurus/preset-classic'; +import { themes as prismThemes } from "prism-react-renderer"; +import type { Config } from "@docusaurus/types"; +import type * as Preset from "@docusaurus/preset-classic"; const config: Config = { - title: 'ODE - Open Data Ensemble', - tagline: 'A symphony of data instruments to support your data collection and analysis.', - favicon: 'img/favicon.ico', + title: "ODE - Open Data Ensemble", + tagline: "A symphony of data instruments to support your data collection and analysis.", + favicon: "img/favicon.ico", - url: 'https://docs.opendataensemble.org', - baseUrl: '/', + url: "https://docs.opendataensemble.org", + baseUrl: "/", - organizationName: 'opendataensemble', - projectName: 'docs', + organizationName: "opendataensemble", + projectName: "docs", - onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', + onBrokenLinks: "throw", + onBrokenMarkdownLinks: "warn", i18n: { - defaultLocale: 'en', - locales: ['en'], + defaultLocale: "en", + locales: ["en"], }, presets: [ [ - 'classic', + "classic", { docs: { - sidebarPath: './sidebars.ts', - editUrl: 'https://github.com/opendataensemble/docs/tree/main/', + sidebarPath: "./sidebars.ts", + editUrl: "https://github.com/opendataensemble/docs/tree/main/", }, pages: { remarkPlugins: [], rehypePlugins: [], }, theme: { - customCss: './src/css/custom.css', + customCss: "./src/css/custom.css", }, } satisfies Preset.Options, ], [ - 'redocusaurus', + "redocusaurus", { specs: [ { - id: 'synkronus-api', - spec: 'synkronus.yaml', - route: '/api', + id: "synkronus-api", + spec: "synkronus.yaml", + route: "/api", }, ], theme: { - primaryColor: '#3f51b5', + primaryColor: "#3f51b5", }, }, ], ], themeConfig: { - image: 'img/docusaurus-social-card.jpg', + image: "img/docusaurus-social-card.jpg", navbar: { - title: 'ODE', + title: "ODE", logo: { - alt: 'ODE Logo', - src: 'img/ode-logo-clear.png', + alt: "ODE Logo", + src: "img/ode-logo-clear.png", }, hideOnScroll: false, items: [ { - type: 'doc', - docId: 'ODE', - label: 'Documentation', - position: 'right', + type: "doc", + docId: "ODE", + label: "Documentation", + position: "right", }, { - label: 'Product', - position: 'right', + label: "Product", + position: "right", items: [ { - type: 'doc', - docId: 'documentation/synkronus/synkronus', - label: 'Synkronus', + type: "doc", + docId: "documentation/synkronus/synkronus", + label: "Synkronus", }, { - type: 'doc', - docId: 'documentation/formulus/formulus', - label: 'Formulus', + type: "doc", + docId: "documentation/formulus/formulus", + label: "Formulus", }, { - type: 'doc', - docId: 'documentation/synkronus-cli/cli', - label: 'Synkronus CLI', + type: "doc", + docId: "documentation/synkronus-cli/cli", + label: "Synkronus CLI", }, ], }, { - label: 'Community', - position: 'right', + label: "Community", + position: "right", items: [ { - label: 'Forum', - href: 'https://forum.opendataensemble.org', + label: "Forum", + href: "https://forum.opendataensemble.org", }, { - label: 'Stack Overflow', - href: 'https://stackoverflow.com/questions/tagged/opendataensemble', + label: "Stack Overflow", + href: "https://stackoverflow.com/questions/tagged/opendataensemble", }, { - label: 'GitHub', - href: 'https://github.com/opendataensemble', + label: "GitHub", + href: "https://github.com/opendataensemble", }, ], }, { - label: 'About Us', - position: 'right', + label: "About Us", + position: "right", items: [ { - type: 'doc', - docId: 'ODE', - label: 'Overview', + type: "doc", + docId: "ODE", + label: "Overview", }, { - type: 'doc', - docId: 'quick-start/index', - label: 'Quick Start', + type: "doc", + docId: "quick-start/index", + label: "Quick Start", }, { - type: 'doc', - docId: 'For-developers/docusaurus/intro', - label: 'For Developers', + type: "doc", + docId: "For-developers/docusaurus/intro", + label: "For Developers", }, ], }, ], }, footer: { - style: 'dark', + style: "dark", links: [ { - title: 'Documentation', + title: "Documentation", items: [ { - label: 'Overview', - to: '/docs/ODE', + label: "Overview", + to: "/docs/ODE", }, { - label: 'API Reference', - to: '/api', + label: "API Reference", + to: "/api", }, ], }, { - title: 'Community', + title: "Community", items: [ { - label: 'Forum', - href: 'https://forum.opendataensemble.org', + label: "Forum", + href: "https://forum.opendataensemble.org", }, ], }, { - title: 'Contact', + title: "Contact", items: [ { html: '', diff --git a/package-lock.json b/package-lock.json index a7e0ad4..cede22b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,13 @@ "@docusaurus/tsconfig": "^3.8.0", "@docusaurus/types": "^3.8.0", "@types/node": "^20.0.0", + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-react": "^7.34.0", + "eslint-plugin-react-hooks": "^4.6.0", + "prettier": "^3.2.0", "ts-node": "^10.9.2", "tsx": "^4.20.6", "typescript": "~5.6.2" @@ -4316,6 +4323,122 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@exodus/schemasafe": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", @@ -4337,6 +4460,44 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -5388,6 +5549,225 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", @@ -5857,12 +6237,52 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -5872,15 +6292,123 @@ "node": ">=8" } }, - "node_modules/astring": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", - "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, "license": "MIT", - "bin": { + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { "astring": "bin/astring" } }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/autoprefixer": { "version": "10.4.21", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", @@ -5918,6 +6446,22 @@ "postcss": "^8.1.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/babel-loader": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", @@ -7521,6 +8065,60 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -7598,6 +8196,13 @@ "node": ">=4.0.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -7769,6 +8374,19 @@ "node": ">=6" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/docusaurus-plugin-redoc": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/docusaurus-plugin-redoc/-/docusaurus-plugin-redoc-2.2.3.tgz", @@ -8148,6 +8766,75 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -8166,6 +8853,34 @@ "node": ">= 0.4" } }, + "node_modules/es-iterator-helpers": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz", + "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.1", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", @@ -8184,6 +8899,53 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es6-promise": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", @@ -8303,39 +9065,441 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "license": "BSD-2-Clause", + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=8.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", + "node_modules/eslint-config-prettier": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz", + "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", + "dev": true, + "license": "MIT", "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "eslint-config-prettier": "bin/cli.js" }, - "engines": { - "node": ">=4" + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "license": "BSD-2-Clause", + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" }, "engines": { "node": ">=4.0" @@ -8676,6 +9840,13 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "license": "MIT" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", @@ -8786,6 +9957,19 @@ "node": ">=0.8.0" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-loader": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", @@ -8941,6 +10125,28 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -8961,6 +10167,22 @@ } } }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/foreach": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", @@ -9064,6 +10286,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -9137,6 +10400,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-tsconfig": { "version": "4.13.0", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", @@ -9228,6 +10509,23 @@ "node": ">=4" } }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -9303,6 +10601,13 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -9361,6 +10666,19 @@ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "license": "MIT" }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -9382,6 +10700,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -9394,6 +10728,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-yarn": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", @@ -10076,6 +11426,21 @@ "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", "license": "MIT" }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -10100,30 +11465,84 @@ "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", "license": "MIT", "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, "license": "MIT", "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "license": "MIT" - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -10136,6 +11555,36 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-ci": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", @@ -10163,6 +11612,41 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-decimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", @@ -10206,6 +11690,22 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -10215,6 +11715,26 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -10253,6 +11773,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-npm": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", @@ -10274,6 +11820,23 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -10292,57 +11855,202 @@ "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "license": "MIT" - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -10385,6 +12093,24 @@ "node": ">=0.10.0" } }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -10520,6 +12246,13 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -10544,6 +12277,22 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -10605,6 +12354,20 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lilconfig": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", @@ -10686,6 +12449,13 @@ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -13272,6 +15042,13 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/negotiator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", @@ -13617,6 +15394,60 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -13705,6 +15536,42 @@ "opener": "bin/opener-bin.js" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", @@ -14077,6 +15944,16 @@ "node": ">=10" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", @@ -15542,6 +17419,32 @@ "postcss": "^8.4.31" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -16106,6 +18009,29 @@ "@docusaurus/utils": "^3.6.0" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/reftools": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", @@ -16133,6 +18059,27 @@ "node": ">=4" } }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexpu-core": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", @@ -16657,6 +18604,33 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -16677,6 +18651,48 @@ ], "license": "MIT" }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -16983,6 +18999,37 @@ "node": ">= 0.4" } }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -17383,6 +19430,20 @@ "resolved": "https://registry.npmjs.org/stickyfill/-/stickyfill-1.1.1.tgz", "integrity": "sha512-GCp7vHAfpao+Qh/3Flh9DXEJ/qSi0KJwJw6zYlZOtRYXWUIpMM6mC2rIep/dK8RQqwW0KxGJIllmjPIBOGN8AA==" }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -17436,6 +19497,104 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -17807,6 +19966,13 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -17890,6 +20056,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -17967,6 +20146,19 @@ "fsevents": "~2.3.3" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", @@ -18013,6 +20205,84 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -18036,6 +20306,25 @@ "node": ">=14.17" } }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -18975,6 +21264,102 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", @@ -18996,6 +21381,16 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "license": "MIT" }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", diff --git a/package.json b/package.json index e9182f7..dd7aae8 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "docusaurus": "docusaurus", - "start": "docusaurus start --no-open", + "start": "docusaurus start", "build": "docusaurus build", "test": "tsx scripts/validate-docs.ts", "validate": "npm run test && npm run build", @@ -14,7 +14,11 @@ "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", - "typecheck": "tsc" + "typecheck": "tsc", + "lint": "eslint . --ext .ts,.tsx --report-unused-disable-directives --max-warnings 0", + "lint:fix": "eslint . --ext .ts,.tsx --fix", + "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,mdx,css}\"", + "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,mdx,css}\"" }, "dependencies": { "@docusaurus/core": "^3.8.0", @@ -31,6 +35,13 @@ "@docusaurus/tsconfig": "^3.8.0", "@docusaurus/types": "^3.8.0", "@types/node": "^20.0.0", + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-react": "^7.34.0", + "eslint-plugin-react-hooks": "^4.6.0", + "prettier": "^3.2.0", "ts-node": "^10.9.2", "tsx": "^4.20.6", "typescript": "~5.6.2" diff --git a/scripts/validate-docs.ts b/scripts/validate-docs.ts index bc5d3e9..51aa05e 100644 --- a/scripts/validate-docs.ts +++ b/scripts/validate-docs.ts @@ -1,7 +1,7 @@ #!/usr/bin/env tsx -import * as fs from 'fs'; -import * as path from 'path'; +import * as fs from "fs"; +import * as path from "path"; interface ValidationResult { errors: string[]; @@ -9,30 +9,31 @@ interface ValidationResult { } function getAllDocFiles(): string[] { - const docsDir = path.join(process.cwd(), 'docs'); + const docsDir = path.join(process.cwd(), "docs"); const files: string[] = []; - + if (!fs.existsSync(docsDir)) { return files; } - + function walkDir(dir: string) { const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { - if (entry.name.startsWith('.')) continue; - + if (entry.name.startsWith(".")) continue; + const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { walkDir(fullPath); - } else if (entry.isFile() && entry.name.endsWith('.md')) { - const relativePath = path.relative(docsDir, fullPath) - .replace(/\\/g, '/') - .replace(/\.md$/, ''); + } else if (entry.isFile() && entry.name.endsWith(".md")) { + const relativePath = path + .relative(docsDir, fullPath) + .replace(/\\/g, "/") + .replace(/\.md$/, ""); files.push(relativePath); } } } - + walkDir(docsDir); return files; } @@ -40,52 +41,52 @@ function getAllDocFiles(): string[] { function docFileExists(docId: string, docFiles: string[]): boolean { if (docFiles.includes(docId)) return true; if (docFiles.includes(`${docId}/index`)) return true; - + // Check if there's a file with the same name as the directory (e.g., formulus/formulus.md) const dirName = path.basename(docId); if (docFiles.includes(`${docId}/${dirName}`)) return true; - - const categoryPath = path.join(process.cwd(), 'docs', docId, '_category_.json'); + + const categoryPath = path.join(process.cwd(), "docs", docId, "_category_.json"); if (fs.existsSync(categoryPath)) return true; - - const parentDir = path.dirname(path.join(process.cwd(), 'docs', docId)); + + const parentDir = path.dirname(path.join(process.cwd(), "docs", docId)); if (fs.existsSync(parentDir) && fs.statSync(parentDir).isDirectory()) { - const categoryJson = path.join(parentDir, '_category_.json'); + const categoryJson = path.join(parentDir, "_category_.json"); if (fs.existsSync(categoryJson)) return true; } - + return false; } function extractDocIdsFromConfig(): string[] { - const configPath = path.join(process.cwd(), 'docusaurus.config.ts'); + const configPath = path.join(process.cwd(), "docusaurus.config.ts"); if (!fs.existsSync(configPath)) return []; - - const content = fs.readFileSync(configPath, 'utf-8'); + + const content = fs.readFileSync(configPath, "utf-8"); const docIds: string[] = []; const docIdRegex = /docId:\s*['"]([^'"]+)['"]/g; let match; - + while ((match = docIdRegex.exec(content)) !== null) { docIds.push(match[1]); } - + return docIds; } function extractDocPathsFromConfig(): string[] { - const configPath = path.join(process.cwd(), 'docusaurus.config.ts'); + const configPath = path.join(process.cwd(), "docusaurus.config.ts"); if (!fs.existsSync(configPath)) return []; - - const content = fs.readFileSync(configPath, 'utf-8'); + + const content = fs.readFileSync(configPath, "utf-8"); const paths: string[] = []; const toPathRegex = /to:\s*['"](\/docs\/[^'"]+)['"]/g; let match; - + while ((match = toPathRegex.exec(content)) !== null) { paths.push(match[1]); } - + return paths; } @@ -99,96 +100,103 @@ function validateConfigDocIds(docFiles: string[], result: ValidationResult): voi function validateConfigPaths(docFiles: string[], result: ValidationResult): void { for (const docPath of extractDocPathsFromConfig()) { - if (docPath.startsWith('/api')) continue; - - const relativePath = docPath.replace(/^\/docs\//, '').replace(/\/$/, ''); - if (!docFileExists(relativePath, docFiles) && !docFileExists(`${relativePath}/index`, docFiles)) { - result.warnings.push(`Path "${docPath}" in docusaurus.config.ts may not exist (verify manually)`); + if (docPath.startsWith("/api")) continue; + + const relativePath = docPath.replace(/^\/docs\//, "").replace(/\/$/, ""); + if ( + !docFileExists(relativePath, docFiles) && + !docFileExists(`${relativePath}/index`, docFiles) + ) { + result.warnings.push( + `Path "${docPath}" in docusaurus.config.ts may not exist (verify manually)` + ); } } } function validateMarkdownLinks(docFiles: string[], result: ValidationResult): void { - const docsDir = path.join(process.cwd(), 'docs'); + const docsDir = path.join(process.cwd(), "docs"); if (!fs.existsSync(docsDir)) return; - + function walkDir(dir: string) { const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { - if (entry.name.startsWith('.')) continue; - + if (entry.name.startsWith(".")) continue; + const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { walkDir(fullPath); - } else if (entry.isFile() && entry.name.endsWith('.md')) { - const content = fs.readFileSync(fullPath, 'utf-8'); - const relativePath = path.relative(docsDir, fullPath).replace(/\\/g, '/'); + } else if (entry.isFile() && entry.name.endsWith(".md")) { + const content = fs.readFileSync(fullPath, "utf-8"); + const relativePath = path.relative(docsDir, fullPath).replace(/\\/g, "/"); const linkRegex = /\[([^\]]+)\]\((\/docs\/[^\)]+)\)/g; let match; - + while ((match = linkRegex.exec(content)) !== null) { const linkPath = match[2]; const linkText = match[1]; - - if (linkPath.startsWith('http') || linkPath.startsWith('/api')) continue; - - const docPath = linkPath.replace(/^\/docs\//, '').replace(/\/$/, ''); + + if (linkPath.startsWith("http") || linkPath.startsWith("/api")) continue; + + const docPath = linkPath.replace(/^\/docs\//, "").replace(/\/$/, ""); if (!docFileExists(docPath, docFiles) && !docFileExists(`${docPath}/index`, docFiles)) { - result.warnings.push(`${relativePath}: Link "${linkText}" points to "${linkPath}" which may not exist`); + result.warnings.push( + `${relativePath}: Link "${linkText}" points to "${linkPath}" which may not exist` + ); } } } } } - + walkDir(docsDir); } function printResults(result: ValidationResult): void { if (result.warnings.length > 0) { - console.log('⚠️ Warnings:'); - result.warnings.forEach(w => console.log(` ${w}`)); - console.log(''); + console.log("⚠️ Warnings:"); + result.warnings.forEach((w) => console.log(` ${w}`)); + console.log(""); } - + if (result.errors.length > 0) { - console.log('❌ Errors found:'); - result.errors.forEach(e => console.log(` ${e}`)); - console.log('\n💡 Fix the errors above before pushing.'); + console.log("❌ Errors found:"); + result.errors.forEach((e) => console.log(` ${e}`)); + console.log("\n💡 Fix the errors above before pushing."); console.log('💡 Run "npm run build" for full validation.\n'); return; } - + if (result.warnings.length === 0) { - console.log('✅ All validation checks passed!'); + console.log("✅ All validation checks passed!"); } else { - console.log('✅ No critical errors found.'); - console.log('⚠️ Review warnings above.'); + console.log("✅ No critical errors found."); + console.log("⚠️ Review warnings above."); } console.log('💡 Run "npm run build" for full validation.\n'); } function main(): void { - console.log('🔍 Running fast documentation validation...\n'); - + console.log("🔍 Running fast documentation validation...\n"); + const result: ValidationResult = { errors: [], warnings: [] }; - const docsDir = path.join(process.cwd(), 'docs'); - + const docsDir = path.join(process.cwd(), "docs"); + if (!fs.existsSync(docsDir)) { - result.errors.push('docs/ directory not found'); + result.errors.push("docs/ directory not found"); printResults(result); process.exit(1); } - + const docFiles = getAllDocFiles(); console.log(`📄 Found ${docFiles.length} documentation files\n`); - + validateConfigDocIds(docFiles, result); validateConfigPaths(docFiles, result); validateMarkdownLinks(docFiles, result); - + printResults(result); - + if (result.errors.length > 0) { process.exit(1); } diff --git a/sidebars-api.ts b/sidebars-api.ts index 531de57..eb75976 100644 --- a/sidebars-api.ts +++ b/sidebars-api.ts @@ -1,9 +1,9 @@ -export default { - openapi: [ - { - type: 'category', - label: 'Synkronus API', - items: [{type: 'autogenerated', dirName: '.'}], - }, - ], -}; \ No newline at end of file +export default { + openapi: [ + { + type: "category", + label: "Synkronus API", + items: [{ type: "autogenerated", dirName: "." }], + }, + ], +}; diff --git a/sidebars.ts b/sidebars.ts index 2d33f95..07c01e6 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -1,320 +1,303 @@ -import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; +import type { SidebarsConfig } from "@docusaurus/plugin-content-docs"; /** * Sidebar configuration for ODE Documentation */ const sidebars: SidebarsConfig = { docs: [ - 'ODE', + "ODE", { - type: 'category', - label: 'Quick Start', + type: "category", + label: "Quick Start", items: [ - 'quick-start/index', - 'quick-start/prerequisites', - 'quick-start/setup-environment', - 'quick-start/deploy-local-instance', - 'quick-start/upload-test-data', + "quick-start/index", + "quick-start/prerequisites", + "quick-start/setup-environment", + "quick-start/deploy-local-instance", + "quick-start/upload-test-data", { - type: 'category', - label: 'Installation', + type: "category", + label: "Installation", items: [ - 'quick-start/formulus-app', - 'quick-start/formulus-prerelease-android', - 'quick-start/synkronus-server', - 'quick-start/custom-app', + "quick-start/formulus-app", + "quick-start/formulus-prerelease-android", + "quick-start/synkronus-server", + "quick-start/custom-app", ], }, - 'quick-start/faq', + "quick-start/faq", ], }, { - type: 'category', - label: 'Technical Overview', + type: "category", + label: "Technical Overview", items: [ - 'technical-overview/index', + "technical-overview/index", { - type: 'category', - label: 'Architecture', + type: "category", + label: "Architecture", items: [ - 'technical-overview/architecture/overview', - 'technical-overview/architecture/components', - 'technical-overview/architecture/data-flow', + "technical-overview/architecture/overview", + "technical-overview/architecture/components", + "technical-overview/architecture/data-flow", ], }, { - type: 'category', - label: 'Concepts', + type: "category", + label: "Concepts", items: [ - 'technical-overview/concepts/overview', - 'technical-overview/concepts/offline-first', - 'technical-overview/concepts/json-forms', - 'technical-overview/concepts/app-bundles', - 'technical-overview/concepts/custom-apps', + "technical-overview/concepts/overview", + "technical-overview/concepts/offline-first", + "technical-overview/concepts/json-forms", + "technical-overview/concepts/app-bundles", + "technical-overview/concepts/custom-apps", ], }, { - type: 'category', - label: 'Database', - items: [ - 'technical-overview/database/overview', - 'technical-overview/database/schema', - ], + type: "category", + label: "Database", + items: ["technical-overview/database/overview", "technical-overview/database/schema"], }, ], }, { - type: 'category', - label: 'Build', + type: "category", + label: "Build", items: [ - 'build/index', + "build/index", { - type: 'category', - label: 'Forms', + type: "category", + label: "Forms", items: [ - 'build/forms/overview', + "build/forms/overview", { - type: 'category', - label: 'Form Design', + type: "category", + label: "Form Design", items: [ - 'build/forms/design/schema-definition', - 'build/forms/design/ui-schema', - 'build/forms/design/validation', - 'build/forms/design/conditional-logic', + "build/forms/design/schema-definition", + "build/forms/design/ui-schema", + "build/forms/design/validation", + "build/forms/design/conditional-logic", ], }, { - type: 'category', - label: 'Advanced Features', + type: "category", + label: "Advanced Features", items: [ - 'build/forms/advanced-features/multimedia', - 'build/forms/advanced-features/location', - 'build/forms/advanced-features/attachments', + "build/forms/advanced-features/multimedia", + "build/forms/advanced-features/location", + "build/forms/advanced-features/attachments", ], }, - 'build/forms/versioning', + "build/forms/versioning", ], }, { - type: 'category', - label: 'Custom Applications', + type: "category", + label: "Custom Applications", items: [ - 'build/custom-applications/overview', - 'build/custom-applications/building', - 'build/custom-applications/app-bundle-structure', - 'build/custom-applications/deployment', - 'build/custom-applications/custom-renderers', + "build/custom-applications/overview", + "build/custom-applications/building", + "build/custom-applications/app-bundle-structure", + "build/custom-applications/deployment", + "build/custom-applications/custom-renderers", ], }, { - type: 'category', - label: 'Data Management', + type: "category", + label: "Data Management", items: [ - 'build/data-management/overview', - 'build/data-management/observations', - 'build/data-management/attachments', - 'build/data-management/export', - 'build/data-management/import', + "build/data-management/overview", + "build/data-management/observations", + "build/data-management/attachments", + "build/data-management/export", + "build/data-management/import", ], }, { - type: 'category', - label: 'Synchronization', + type: "category", + label: "Synchronization", items: [ - 'build/synchronization/overview', - 'build/synchronization/sync-protocol', - 'build/synchronization/conflict-resolution', - 'build/synchronization/troubleshooting', + "build/synchronization/overview", + "build/synchronization/sync-protocol", + "build/synchronization/conflict-resolution", + "build/synchronization/troubleshooting", ], }, - 'build/users-authentication', - 'build/translations', - 'build/branding', + "build/users-authentication", + "build/translations", + "build/branding", ], }, { - type: 'category', - label: 'Components', + type: "category", + label: "Components", items: [ { - type: 'category', - label: 'Formulus', + type: "category", + label: "Formulus", items: [ - 'components/formulus/overview', - 'components/formulus/installation', - 'components/formulus/configuration', - 'components/formulus/features', - 'components/formulus/troubleshooting', - 'components/formulus/integration', + "components/formulus/overview", + "components/formulus/installation", + "components/formulus/configuration", + "components/formulus/features", + "components/formulus/troubleshooting", + "components/formulus/integration", ], }, { - type: 'category', - label: 'Synkronus', + type: "category", + label: "Synkronus", items: [ - 'components/synkronus/overview', - 'components/synkronus/installation', - 'components/synkronus/configuration', - 'components/synkronus/api-reference', + "components/synkronus/overview", + "components/synkronus/installation", + "components/synkronus/configuration", + "components/synkronus/api-reference", ], }, { - type: 'category', - label: 'Synkronus CLI', + type: "category", + label: "Synkronus CLI", items: [ - 'components/synkronus-cli/overview', - 'components/synkronus-cli/installation', - 'components/synkronus-cli/commands-reference', + "components/synkronus-cli/overview", + "components/synkronus-cli/installation", + "components/synkronus-cli/commands-reference", ], }, { - type: 'category', - label: 'Formplayer', - items: [ - 'components/formplayer/overview', - 'components/formplayer/integration', - ], + type: "category", + label: "Formplayer", + items: ["components/formplayer/overview", "components/formplayer/integration"], }, { - type: 'category', - label: 'Documentation', + type: "category", + label: "Documentation", items: [ - 'documentation/formulus/formulus', - 'documentation/synkronus/synkronus', - 'documentation/synkronus/app-bundle', - 'documentation/synkronus-cli/cli', + "documentation/formulus/formulus", + "documentation/synkronus/synkronus", + "documentation/synkronus/app-bundle", + "documentation/synkronus-cli/cli", ], }, ], }, { - type: 'category', - label: 'Host', + type: "category", + label: "Host", items: [ - 'host/index', + "host/index", { - type: 'category', - label: 'Synkronus Server', + type: "category", + label: "Synkronus Server", items: [ - 'host/synkronus-server/overview', - 'host/synkronus-server/requirements', - 'host/synkronus-server/production', - 'host/synkronus-server/docker', - 'host/synkronus-server/kubernetes', - 'host/synkronus-server/cloud', - 'host/synkronus-server/monitoring', - 'host/synkronus-server/backups', + "host/synkronus-server/overview", + "host/synkronus-server/requirements", + "host/synkronus-server/production", + "host/synkronus-server/docker", + "host/synkronus-server/kubernetes", + "host/synkronus-server/cloud", + "host/synkronus-server/monitoring", + "host/synkronus-server/backups", ], }, { - type: 'category', - label: 'Monitoring & Alerting', + type: "category", + label: "Monitoring & Alerting", items: [ - 'host/monitoring/overview', - 'host/monitoring/setup', - 'host/monitoring/production', + "host/monitoring/overview", + "host/monitoring/setup", + "host/monitoring/production", ], }, - 'host/data-management', - 'host/security', + "host/data-management", + "host/security", ], }, { - type: 'category', - label: 'Reference', + type: "category", + label: "Reference", items: [ - 'reference/index', + "reference/index", { - type: 'category', - label: 'REST API', + type: "category", + label: "REST API", items: [ - 'reference/rest-api/overview', - 'reference/rest-api/authentication', - 'reference/rest-api/app-bundle', - 'reference/rest-api/sync', - 'reference/rest-api/attachments', + "reference/rest-api/overview", + "reference/rest-api/authentication", + "reference/rest-api/app-bundle", + "reference/rest-api/sync", + "reference/rest-api/attachments", ], }, { - type: 'category', - label: 'Configuration', - items: [ - 'reference/configuration/server', - 'reference/configuration/client', - ], + type: "category", + label: "Configuration", + items: ["reference/configuration/server", "reference/configuration/client"], }, - 'reference/form-specifications', - 'reference/app-bundle-format', + "reference/form-specifications", + "reference/app-bundle-format", ], }, { - type: 'category', - label: 'Tutorials', + type: "category", + label: "Tutorials", items: [ - 'tutorials/index', + "tutorials/index", { - type: 'category', - label: 'Getting Started', + type: "category", + label: "Getting Started", items: [ - 'tutorials/getting-started/first-form', - 'tutorials/getting-started/first-custom-app', - 'tutorials/getting-started/connecting-everything', + "tutorials/getting-started/first-form", + "tutorials/getting-started/first-custom-app", + "tutorials/getting-started/connecting-everything", ], }, { - type: 'category', - label: 'Advanced Topics', + type: "category", + label: "Advanced Topics", items: [ - 'tutorials/advanced/complex-forms', - 'tutorials/advanced/custom-renderers', - 'tutorials/advanced/performance', + "tutorials/advanced/complex-forms", + "tutorials/advanced/custom-renderers", + "tutorials/advanced/performance", ], }, ], }, { - type: 'category', - label: 'Community', + type: "category", + label: "Community", items: [ - 'community/index', + "community/index", { - type: 'category', - label: 'Contribute', + type: "category", + label: "Contribute", items: [ - 'community/contribute/about', - 'community/contribute/first-time', - 'community/contribute/code-of-conduct', + "community/contribute/about", + "community/contribute/first-time", + "community/contribute/code-of-conduct", ], }, { - type: 'category', - label: 'Support', - items: [ - 'community/support/getting-help', - 'community/support/reporting-issues', - ], + type: "category", + label: "Support", + items: ["community/support/getting-help", "community/support/reporting-issues"], }, { - type: 'category', - label: 'Resources', - items: [ - 'community/resources/examples', - 'community/resources/projects', - ], + type: "category", + label: "Resources", + items: ["community/resources/examples", "community/resources/projects"], }, ], }, { - type: 'category', - label: 'For Developers', + type: "category", + label: "For Developers", items: [ - 'For-developers/docusaurus/intro', + "For-developers/docusaurus/intro", { - type: 'category', - label: 'Tutorial Extras', - items: [ - 'For-developers/docusaurus/tutorial-extras/manage-docs-versions', - ], + type: "category", + label: "Tutorial Extras", + items: ["For-developers/docusaurus/tutorial-extras/manage-docs-versions"], }, ], }, diff --git a/src/components/AnnouncementBanner/index.tsx b/src/components/AnnouncementBanner/index.tsx index 97e0775..0ccd82a 100644 --- a/src/components/AnnouncementBanner/index.tsx +++ b/src/components/AnnouncementBanner/index.tsx @@ -1,25 +1,20 @@ -import React from 'react'; -import Link from '@docusaurus/Link'; -import styles from './styles.module.css'; +import React from "react"; +import Link from "@docusaurus/Link"; +import styles from "./styles.module.css"; export default function AnnouncementBanner(): React.ReactElement { return (
- Birdie
NEW - - Try the Formulus Android app pre-release! - - + Try the Formulus Android app pre-release! + Install Now →
diff --git a/src/components/AnnouncementBanner/styles.module.css b/src/components/AnnouncementBanner/styles.module.css index 37e3547..06420ec 100644 --- a/src/components/AnnouncementBanner/styles.module.css +++ b/src/components/AnnouncementBanner/styles.module.css @@ -8,7 +8,7 @@ } .banner::before { - content: ''; + content: ""; position: absolute; top: -50%; right: -10%; @@ -20,7 +20,7 @@ } .banner::after { - content: ''; + content: ""; position: absolute; bottom: -30%; left: -5%; @@ -32,7 +32,8 @@ } @keyframes float { - 0%, 100% { + 0%, + 100% { transform: translateY(0) translateX(0); } 50% { @@ -59,7 +60,8 @@ } @keyframes bounce { - 0%, 100% { + 0%, + 100% { transform: translateY(0) rotate(-5deg); } 50% { @@ -116,16 +118,16 @@ .banner { padding: 0.75rem 0; } - + .birdie { width: 40px; height: 40px; } - + .text { font-size: 0.9rem; } - + .content { gap: 0.5rem; } @@ -136,7 +138,7 @@ flex-direction: column; gap: 0.5rem; } - + .text { font-size: 0.85rem; text-align: center; diff --git a/src/components/Card/index.tsx b/src/components/Card/index.tsx index 5c69c25..3afa440 100644 --- a/src/components/Card/index.tsx +++ b/src/components/Card/index.tsx @@ -1,7 +1,7 @@ -import type { ReactNode } from 'react'; -import Link from '@docusaurus/Link'; -import clsx from 'clsx'; -import styles from './styles.module.css'; +import type { ReactNode } from "react"; +import Link from "@docusaurus/Link"; +import clsx from "clsx"; +import styles from "./styles.module.css"; interface CardProps { title: string; @@ -42,11 +42,11 @@ export default function Card({ if (href) { to = href; } else if (link) { - to = link.startsWith('/') ? link : link; + to = link.startsWith("/") ? link : link; } else { - to = '#'; + to = "#"; } - + return ( {content} @@ -56,4 +56,3 @@ export default function Card({ return content; } - diff --git a/src/components/Card/styles.module.css b/src/components/Card/styles.module.css index c58e7b9..6c4c867 100644 --- a/src/components/Card/styles.module.css +++ b/src/components/Card/styles.module.css @@ -2,7 +2,9 @@ text-decoration: none; color: inherit; display: block; - transition: transform 0.2s ease, box-shadow 0.2s ease; + transition: + transform 0.2s ease, + box-shadow 0.2s ease; } .cardLink:hover { @@ -25,7 +27,9 @@ border: 1px solid var(--ifm-color-emphasis-200); border-radius: 8px; height: 100%; - transition: border-color 0.2s ease, box-shadow 0.2s ease; + transition: + border-color 0.2s ease, + box-shadow 0.2s ease; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); } @@ -34,12 +38,12 @@ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } -[data-theme='dark'] .card { +[data-theme="dark"] .card { background: var(--ifm-background-surface-color); border-color: var(--ifm-color-emphasis-300); } -[data-theme='dark'] .cardLink:hover .card { +[data-theme="dark"] .cardLink:hover .card { border-color: var(--ifm-color-primary); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); } @@ -97,4 +101,3 @@ font-size: 0.9rem; } } - diff --git a/src/components/Cards/index.tsx b/src/components/Cards/index.tsx index dd2a867..58050d7 100644 --- a/src/components/Cards/index.tsx +++ b/src/components/Cards/index.tsx @@ -1,6 +1,6 @@ -import type { ReactNode } from 'react'; -import clsx from 'clsx'; -import styles from './styles.module.css'; +import type { ReactNode } from "react"; +import clsx from "clsx"; +import styles from "./styles.module.css"; interface CardsProps { children: ReactNode; @@ -8,10 +8,5 @@ interface CardsProps { } export default function Cards({ children, className }: CardsProps): ReactNode { - return ( -
- {children} -
- ); + return
{children}
; } - diff --git a/src/components/Cards/styles.module.css b/src/components/Cards/styles.module.css index 2dfe0fc..ad8eb24 100644 --- a/src/components/Cards/styles.module.css +++ b/src/components/Cards/styles.module.css @@ -11,4 +11,3 @@ gap: 1rem; } } - diff --git a/src/components/HomepageFeatures/index.tsx b/src/components/HomepageFeatures/index.tsx index 62a02b2..515187e 100644 --- a/src/components/HomepageFeatures/index.tsx +++ b/src/components/HomepageFeatures/index.tsx @@ -1,7 +1,7 @@ -import type { ReactNode } from 'react'; -import clsx from 'clsx'; -import Heading from '@theme/Heading'; -import styles from './styles.module.css'; +import type { ReactNode } from "react"; +import clsx from "clsx"; +import Heading from "@theme/Heading"; +import styles from "./styles.module.css"; type FeatureItem = { title: string; @@ -11,29 +11,27 @@ type FeatureItem = { const FeatureList: FeatureItem[] = [ { - title: 'Great for longitudinal field studies', - image: require('@site/static/img/fieldworder_scenery.png').default, - description: ( - <> - ODE is a platform for building sophisticated data collection instruments. - - ), + title: "Great for longitudinal field studies", + image: require("@site/static/img/fieldworder_scenery.png").default, + description: <>ODE is a platform for building sophisticated data collection instruments., }, { - title: 'Focus on what matters', - image: require('@site/static/img/planner_scenery.png').default, + title: "Focus on what matters", + image: require("@site/static/img/planner_scenery.png").default, description: ( <> - Spend your time designing your data collection instruments instead of building the infrastructure for it. + Spend your time designing your data collection instruments instead of building the + infrastructure for it. ), }, { - title: 'Cross platform & open source', - image: require('@site/static/img/developer_scenery.png').default, + title: "Cross platform & open source", + image: require("@site/static/img/developer_scenery.png").default, description: ( <> - ODE is available for Android and iOS. It is 100% FLOSS (Free (Libre) Open Source Software) and focused on providing great DX + ODE is available for Android and iOS. It is 100% FLOSS (Free (Libre) Open Source Software) + and focused on providing great DX ), }, @@ -41,7 +39,7 @@ const FeatureList: FeatureItem[] = [ function Feature({ title, image, description }: FeatureItem) { return ( -
+
{title}
diff --git a/src/components/HomepageFeatures/styles.module.css b/src/components/HomepageFeatures/styles.module.css index f582a15..784f0da 100644 --- a/src/components/HomepageFeatures/styles.module.css +++ b/src/components/HomepageFeatures/styles.module.css @@ -18,7 +18,7 @@ .features { padding: 1.5rem 0; } - + .featureSvg { height: 160px; width: 160px; @@ -29,7 +29,7 @@ .features { padding: 1.25rem 0; } - + .featureSvg { height: 140px; width: 140px; @@ -40,7 +40,7 @@ .features { padding: 1rem 0; } - + .featureSvg { height: 120px; width: 120px; diff --git a/src/components/Newsletter/index.tsx b/src/components/Newsletter/index.tsx index c66b0c3..117c90f 100644 --- a/src/components/Newsletter/index.tsx +++ b/src/components/Newsletter/index.tsx @@ -1,16 +1,16 @@ -import type { ReactNode } from 'react'; -import { useState, useEffect } from 'react'; -import styles from './styles.module.css'; -import Heading from '@theme/Heading'; +import type { ReactNode } from "react"; +import { useState, useEffect } from "react"; +import styles from "./styles.module.css"; +import Heading from "@theme/Heading"; export default function Newsletter(): ReactNode { const [isSignupComplete, setIsSignupComplete] = useState(false); useEffect(() => { // Check if the URL contains ?signup_complete - if (typeof window !== 'undefined') { + if (typeof window !== "undefined") { const urlParams = new URLSearchParams(window.location.search); - setIsSignupComplete(urlParams.has('signup_complete')); + setIsSignupComplete(urlParams.has("signup_complete")); } }, []); return ( @@ -23,7 +23,8 @@ export default function Newsletter(): ReactNode { Stay Updated on ODE's Launch

- Be the first to know when OpenDataEnsemble becomes available. Get updates on features and release dates + Be the first to know when OpenDataEnsemble becomes available. Get updates on + features and release dates

{isSignupComplete ? ( @@ -31,27 +32,29 @@ export default function Newsletter(): ReactNode {

Yay! 🎉 Thanks for signing up!

- Please remember to confirm your subscription by clicking the link in the verification email we just sent you. + Please remember to confirm your subscription by clicking the link in the + verification email we just sent you.

- Hint: If you don't receive the verification email, please check your spam folder! + Hint: If you don't receive the verification email, please + check your spam folder!

) : ( -
-
+
- @@ -59,7 +62,7 @@ export default function Newsletter(): ReactNode { Subscribe
- +

We respect your privacy. Unsubscribe at any time.

@@ -68,11 +71,11 @@ export default function Newsletter(): ReactNode { )}
- +
- Giraffe reading a newsletter
diff --git a/src/components/Newsletter/styles.module.css b/src/components/Newsletter/styles.module.css index 08e056b..188a7ac 100644 --- a/src/components/Newsletter/styles.module.css +++ b/src/components/Newsletter/styles.module.css @@ -167,28 +167,28 @@ .newsletter { padding: 2.5rem 0; } - + .newsletterGrid { grid-template-columns: 1fr; gap: 2rem; } - + .newsletterLeft { text-align: center; } - + .newsletterTitle { font-size: 2rem; } - + .newsletterSubtitle { font-size: 1.1rem; } - + .giraffeImage { max-width: 300px; } - + .formContent { padding: 1.5rem; } @@ -198,45 +198,45 @@ .newsletter { padding: 2rem 0; } - + .newsletterGrid { gap: 1.5rem; } - + .newsletterTitle { font-size: 1.75rem; margin-bottom: 0.75rem; } - + .newsletterSubtitle { font-size: 1rem; margin-bottom: 1.5rem; } - + .newsletterForm { margin-top: 1.5rem; } - + .form { max-width: 100%; } - + .formContent { padding: 1.25rem; } - + .formHeader h3 { font-size: 1.25rem; } - + .giraffeImage { max-width: 250px; } - + .thankYouContent { padding: 1.5rem; } - + .thankYouTitle { font-size: 1.25rem; } @@ -246,46 +246,46 @@ .newsletter { padding: 1.5rem 0; } - + .newsletterTitle { font-size: 1.5rem; } - + .newsletterSubtitle { font-size: 0.95rem; } - + .formContent { padding: 1rem; } - + .emailInput { font-size: 0.9rem; padding: 0.625rem 0.875rem; } - + .submitButton { font-size: 0.9rem; padding: 0.625rem 1.5rem; width: 100%; } - + .formFields { gap: 0.75rem; } - + .giraffeImage { max-width: 200px; } - + .thankYouContent { padding: 1.25rem; } - + .thankYouTitle { font-size: 1.125rem; } - + .thankYouText { font-size: 0.9rem; } diff --git a/src/css/custom.css b/src/css/custom.css index bc0ba02..3137785 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -13,14 +13,15 @@ --ifm-code-font-size: 95%; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); --navbar-height: 72px; - --navbar-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + --navbar-font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --navbar-text-color: #333; --navbar-text-color-light: #666; --navbar-border-top: #333; --navbar-border-bottom: var(--ifm-color-primary); } -[data-theme='dark'] { +[data-theme="dark"] { --ifm-color-primary: #25c2a0; --ifm-color-primary-dark: #21af90; --ifm-color-primary-darker: #1fa588; @@ -167,7 +168,7 @@ } .navbar__item--dropdown .dropdown::before { - content: ''; + content: ""; position: absolute; top: 100%; left: 0; @@ -212,7 +213,7 @@ background-color: rgba(0, 0, 0, 0.03); } -[data-theme='dark'] .dropdown__link:hover { +[data-theme="dark"] .dropdown__link:hover { background-color: rgba(255, 255, 255, 0.1); } @@ -229,7 +230,7 @@ border-radius: 4px; } -[data-theme='dark'] .navbar__toggle:hover { +[data-theme="dark"] .navbar__toggle:hover { background-color: rgba(255, 255, 255, 0.1); } @@ -238,7 +239,7 @@ box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1); } -[data-theme='dark'] .navbar-sidebar { +[data-theme="dark"] .navbar-sidebar { background-color: #1e1e1e; } @@ -247,7 +248,7 @@ border-bottom: 1px solid rgba(0, 0, 0, 0.1); } -[data-theme='dark'] .navbar-sidebar__brand { +[data-theme="dark"] .navbar-sidebar__brand { border-bottom: 1px solid rgba(255, 255, 255, 0.1); } @@ -267,7 +268,7 @@ background-color: rgba(0, 0, 0, 0.05); } -[data-theme='dark'] .navbar-sidebar__link:hover { +[data-theme="dark"] .navbar-sidebar__link:hover { background-color: rgba(255, 255, 255, 0.1); } @@ -278,7 +279,7 @@ font-weight: 500; } -[data-theme='dark'] .navbar-sidebar__link--active { +[data-theme="dark"] .navbar-sidebar__link--active { background-color: rgba(255, 255, 255, 0.1); } @@ -304,7 +305,7 @@ padding: 0.5rem 0; } -[data-theme='dark'] .navbar-sidebar__dropdown { +[data-theme="dark"] .navbar-sidebar__dropdown { background-color: rgba(255, 255, 255, 0.05); } @@ -317,24 +318,24 @@ .navbar__inner { padding: 0 1.5rem 0 1rem; } - + .navbar__brand { gap: 0.5rem; margin-right: 0; } - + .navbar__logo { height: 44px; } - + .navbar__title::before { font-size: 1.1rem; } - + .navbar__items { margin-left: 1rem; } - + .navbar__link { font-size: 0.85rem; padding: 0.75rem; @@ -345,12 +346,12 @@ .navbar { min-height: 60px; } - + .navbar__inner { padding: 0 1rem; min-height: 60px; } - + .navbar__brand { gap: 0.5rem; margin-left: -0.25rem; @@ -358,19 +359,19 @@ min-width: 0; max-width: calc(100% - 60px); } - + .navbar__logo { height: 40px; flex-shrink: 0; } - + .navbar__title::before { font-size: 1rem; white-space: nowrap; overflow: visible; max-width: none; } - + .navbar__items { margin-left: 0; flex: 1 1 auto; @@ -380,14 +381,14 @@ .navbar__items--right { display: none; } - + .navbar__item:has(.navbar__link[href*="/docs/ODE"]), .navbar__link[href*="/docs/ODE"], .navbar__item a[href="/docs/ODE"] { display: none !important; visibility: hidden !important; } - + .navbar__toggle { display: flex; align-items: center; @@ -407,34 +408,34 @@ .navbar { min-height: 56px; } - + .navbar__inner { padding: 0 0.75rem; min-height: 56px; } - + .navbar__brand { gap: 0.375rem; margin-left: -0.25rem; max-width: calc(100% - 50px); } - + .navbar__logo { height: 36px; } - + .navbar__title::before { font-size: 0.95rem; letter-spacing: 0.01em; } - + .navbar__item:has(.navbar__link[href*="/docs/ODE"]), .navbar__link[href*="/docs/ODE"], .navbar__item a[href="/docs/ODE"] { display: none !important; visibility: hidden !important; } - + .navbar__toggle { width: 36px; height: 36px; @@ -448,7 +449,7 @@ padding: 1.5rem 0 1rem; } -[data-theme='dark'] .footer { +[data-theme="dark"] .footer { background-color: #0d1117; } @@ -522,7 +523,7 @@ margin-top: 1rem; } -[data-theme='dark'] .footer__copyright { +[data-theme="dark"] .footer__copyright { color: rgba(255, 255, 255, 0.5); } @@ -530,11 +531,11 @@ .footer__container { padding: 0 1.5rem; } - + .footer__links { grid-template-columns: repeat(2, 1fr); } - + .footer { padding: 1.5rem 0 0.75rem; } @@ -544,25 +545,25 @@ .footer__container { padding: 0 1rem; } - + .footer__links { gap: 1.25rem; margin-bottom: 1.25rem; } - + .footer__title { font-size: 0.9rem; margin-bottom: 0.625rem; } - + .footer__link { font-size: 0.85rem; } - + .footer__item { margin-bottom: 0.375rem; } - + .footer__copyright { font-size: 0.8rem; padding-top: 0.875rem; @@ -574,33 +575,33 @@ .footer__container { padding: 0 0.75rem; } - + .footer__links { grid-template-columns: 1fr; gap: 1.5rem; margin-bottom: 1rem; } - + .footer__title { font-size: 0.875rem; margin-bottom: 0.5rem; } - + .footer__link, .footer__social-link { font-size: 0.8rem; } - + .footer { padding: 1.25rem 0 0.625rem; } - + .footer__copyright { font-size: 0.75rem; padding-top: 0.75rem; margin-top: 0.75rem; } - + .footer__social-link svg { width: 16px; height: 16px; diff --git a/src/pages/index.module.css b/src/pages/index.module.css index 273f2b2..ca5e087 100644 --- a/src/pages/index.module.css +++ b/src/pages/index.module.css @@ -10,7 +10,7 @@ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); } -[data-theme='dark'] .heroBanner { +[data-theme="dark"] .heroBanner { background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); } @@ -22,7 +22,7 @@ line-height: 1.2; } -[data-theme='dark'] .heroTitle { +[data-theme="dark"] .heroTitle { color: #ffffff; } @@ -33,7 +33,7 @@ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } -[data-theme='dark'] .featureImg { +[data-theme="dark"] .featureImg { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); } @@ -54,10 +54,10 @@ background: #ffffff; } -[data-theme='dark'] .mainSection, -[data-theme='dark'] .featuresSection, -[data-theme='dark'] .opensourceSection, -[data-theme='dark'] .newsletterSection { +[data-theme="dark"] .mainSection, +[data-theme="dark"] .featuresSection, +[data-theme="dark"] .opensourceSection, +[data-theme="dark"] .newsletterSection { background: #1e1e1e; } @@ -67,9 +67,9 @@ background: #f8f9fa; } -[data-theme='dark'] .showcaseSection, -[data-theme='dark'] .communitySection, -[data-theme='dark'] .getInvolvedSection { +[data-theme="dark"] .showcaseSection, +[data-theme="dark"] .communitySection, +[data-theme="dark"] .getInvolvedSection { background: #252525; } @@ -81,7 +81,7 @@ text-align: center; } -[data-theme='dark'] .sectionTitle { +[data-theme="dark"] .sectionTitle { color: #ffffff; } @@ -98,7 +98,7 @@ margin-bottom: 1.5rem; } -[data-theme='dark'] .descriptionText { +[data-theme="dark"] .descriptionText { color: #e2e8f0; } @@ -107,7 +107,7 @@ text-decoration: underline; } -[data-theme='dark'] .descriptionText a { +[data-theme="dark"] .descriptionText a { color: var(--ifm-color-primary-light); } @@ -148,7 +148,7 @@ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } -[data-theme='dark'] .involvedCard { +[data-theme="dark"] .involvedCard { background: #2a2a2a; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); } @@ -160,7 +160,7 @@ margin-bottom: 1rem; } -[data-theme='dark'] .cardTitle { +[data-theme="dark"] .cardTitle { color: #ffffff; } @@ -177,7 +177,7 @@ border-bottom: 1px solid #e2e8f0; } -[data-theme='dark'] .involvedList li { +[data-theme="dark"] .involvedList li { color: #e2e8f0; border-bottom: 1px solid #3a3a3a; } @@ -204,11 +204,11 @@ .heroBanner { padding: 4rem 2rem 2rem; } - + .heroTitle { font-size: 2rem; } - + .mainSection, .showcaseSection, .featuresSection, @@ -218,20 +218,20 @@ .newsletterSection { padding: 3.5rem 0; } - + .sectionTitle { font-size: 1.875rem; } - + .descriptionText { font-size: 1rem; } - + .showcaseGrid, .communityGrid { gap: 2.5rem; } - + .involvedGrid { gap: 1.5rem; } @@ -241,11 +241,11 @@ .heroBanner { padding: 3rem 1.5rem 1.5rem; } - + .heroTitle { font-size: 1.75rem; } - + .mainSection, .showcaseSection, .featuresSection, @@ -255,48 +255,48 @@ .newsletterSection { padding: 3rem 0; } - + .sectionTitle { font-size: 1.75rem; margin-bottom: 1.25rem; } - + .descriptionText { font-size: 0.95rem; line-height: 1.7; margin-bottom: 1.25rem; } - + .showcaseGrid, .communityGrid { grid-template-columns: 1fr; gap: 2rem; } - + .showcaseImage, .communityImage { order: -1; } - + .involvedGrid { grid-template-columns: 1fr; gap: 1.25rem; margin-top: 1.5rem; } - + .involvedCard { padding: 1.5rem; } - + .cardTitle { font-size: 1.25rem; } - + .communityLinks { flex-direction: column; gap: 0.75rem; } - + .communityLinks .button { width: 100%; justify-content: center; @@ -307,11 +307,11 @@ .heroBanner { padding: 2.5rem 1rem 1rem; } - + .heroTitle { font-size: 1.5rem; } - + .mainSection, .showcaseSection, .featuresSection, @@ -321,31 +321,31 @@ .newsletterSection { padding: 2.5rem 0; } - + .sectionTitle { font-size: 1.5rem; margin-bottom: 1rem; } - + .descriptionText { font-size: 0.9rem; line-height: 1.6; margin-bottom: 1rem; } - + .showcaseGrid, .communityGrid { gap: 1.5rem; } - + .involvedCard { padding: 1.25rem; } - + .cardTitle { font-size: 1.125rem; } - + .involvedList li { padding: 0.5rem 0; font-size: 0.875rem; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index a6d9ed3..e69e727 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,24 +1,28 @@ -import type {ReactNode} from 'react'; -import clsx from 'clsx'; -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import Layout from '@theme/Layout'; -import HomepageFeatures from '@site/src/components/HomepageFeatures'; -import Newsletter from '@site/src/components/Newsletter'; -import AnnouncementBanner from '@site/src/components/AnnouncementBanner'; -import Heading from '@theme/Heading'; +import type { ReactNode } from "react"; +import clsx from "clsx"; +import Link from "@docusaurus/Link"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import Layout from "@theme/Layout"; +import HomepageFeatures from "@site/src/components/HomepageFeatures"; +import Newsletter from "@site/src/components/Newsletter"; +import AnnouncementBanner from "@site/src/components/AnnouncementBanner"; +import Heading from "@theme/Heading"; -import styles from './index.module.css'; +import styles from "./index.module.css"; function HomepageHeader() { - const {siteConfig} = useDocusaurusContext(); + const { siteConfig } = useDocusaurusContext(); return (
{siteConfig.tagline} - + Get Started
@@ -27,7 +31,7 @@ function HomepageHeader() { } export default function Home(): ReactNode { - const {siteConfig} = useDocusaurusContext(); + const { siteConfig } = useDocusaurusContext(); return ( @@ -41,11 +45,12 @@ export default function Home(): ReactNode {

- The Open Data Ensemble (ODE) is a comprehensive platform for building sophisticated data collection - instruments. It provides a collection of open source technologies and resources that help you build and - deploy digital tools for mobile data collection. Together, we envision a world where data collection is - seamless, efficient, and accessible to everyone, enabling better decision-making through high-quality - data. + The Open Data Ensemble (ODE) is a comprehensive platform for building sophisticated + data collection instruments. It provides a collection of open source technologies + and resources that help you build and deploy digital tools for mobile data + collection. Together, we envision a world where data collection is seamless, + efficient, and accessible to everyone, enabling better decision-making through + high-quality data.

@@ -60,9 +65,9 @@ export default function Home(): ReactNode { ODE Platform Demo

- ODE is flexible by design, and applications built using the ODE framework support an exceptional range - of features and data collection scenarios. Explore our platform to see sample configurations, data - collection workflows, and more! + ODE is flexible by design, and applications built using the ODE framework support + an exceptional range of features and data collection scenarios. Explore our + platform to see sample configurations, data collection workflows, and more!

- The ODE Community is a space for developers, data scientists, researchers, and innovators to share - knowledge, provide technical assistance to other users, and explore new opportunities for learning and - collaboration. + The ODE Community is a space for developers, data scientists, researchers, and + innovators to share knowledge, provide technical assistance to other users, and + explore new opportunities for learning and collaboration.

- It features product updates and roadmaps, discussions about the resources included in ODE, and more. - We invite you to join us and introduce yourself! + It features product updates and roadmaps, discussions about the resources included + in ODE, and more. We invite you to join us and introduce yourself!

Join the Community - + View on GitHub
@@ -139,9 +147,10 @@ export default function Home(): ReactNode {

- Developers and designers in our open source community work together to build and expand the technical - components that power applications built with the Open Data Ensemble, explore new integrations, and - create reference applications that serve as templates for the creation of new data collection tools. + Developers and designers in our open source community work together to build and + expand the technical components that power applications built with the Open Data + Ensemble, explore new integrations, and create reference applications that serve as + templates for the creation of new data collection tools.

Want to join us or build a new integration? Check out our{" "} @@ -173,7 +182,10 @@ export default function Home(): ReactNode { Help us improve the ODE documentation

  • - Share a new idea or question on GitHub + + Share a new idea or question + {" "} + on GitHub
  • Contribute to open source components
  • @@ -184,7 +196,8 @@ export default function Home(): ReactNode {
    • - Share your expertise on the Forum + Share your expertise on the + Forum
    • Sign up for the ODE newsletter to get the latest updates
    • Provide feedback on features and workflows
    • diff --git a/src/theme/MDXComponents.tsx b/src/theme/MDXComponents.tsx index efede48..1b67a10 100644 --- a/src/theme/MDXComponents.tsx +++ b/src/theme/MDXComponents.tsx @@ -1,6 +1,6 @@ -import type { MDXComponents } from 'mdx/types'; -import Cards from '../components/Cards'; -import Card from '../components/Card'; +import type { MDXComponents } from "mdx/types"; +import Cards from "../components/Cards"; +import Card from "../components/Card"; export default function useMDXComponents(components: MDXComponents): MDXComponents { return { @@ -9,4 +9,3 @@ export default function useMDXComponents(components: MDXComponents): MDXComponen ...components, }; } -