├── .cargo └── config.toml ├── .dockerignore ├── .github └── workflows │ ├── release.yml │ └── test.yml ├── .gitignore ├── .gitmodules ├── .pre-commit-config.yaml ├── .rustfmt.toml ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── assets ├── colors.svg ├── favicon.svg ├── logo.svg └── logo_104.webp ├── client ├── testfixture │ ├── .gitignore │ ├── Makefile │ ├── config.textproto │ ├── migrations │ │ ├── U1725019360__create_admin_user.sql │ │ ├── U1725019361__add_users.sql │ │ ├── U1727439999__create_simple_strict_table.sql │ │ ├── U1727956148__create_more_tables.sql │ │ ├── U1728458183__create_virtual_table.sql │ │ ├── U1728810800__create_table_movies.sql │ │ ├── U1728810810__create_blog_example_tables.sql │ │ └── U1739526748__create_comment_table_for_blog_example.sql │ ├── scripts │ │ └── index.ts │ └── secrets │ │ └── secrets.textproto ├── trailbase-dart │ ├── .gitignore │ ├── .pubignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── client.dart │ │ │ ├── pkce.dart │ │ │ └── sse.dart │ │ └── trailbase.dart │ ├── pubspec.yaml │ └── test │ │ └── trailbase_test.dart ├── trailbase-dotnet │ ├── .editorconfig │ ├── .gitignore │ ├── docs │ │ ├── docfx.json │ │ ├── images │ │ │ ├── favicon.svg │ │ │ └── logo_48.svg │ │ ├── index.md │ │ └── toc.yml │ ├── src │ │ ├── Client.cs │ │ ├── README.md │ │ ├── RecordApi.cs │ │ └── TrailBase.csproj │ └── test │ │ ├── ClientTest.cs │ │ └── TrailBase.Tests.csproj ├── trailbase-py │ ├── .gitignore │ ├── README.md │ ├── poetry.toml │ ├── pyproject.toml │ ├── tests │ │ ├── __init__.py │ │ └── test_client.py │ └── trailbase │ │ └── __init__.py ├── trailbase-rs │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── integration_test.rs ├── trailbase-swift │ ├── .gitignore │ ├── Package.resolved │ ├── Package.swift │ ├── Sources │ │ └── TrailBase │ │ │ └── TrailBase.swift │ └── Tests │ │ └── TrailBaseTests │ │ └── TrailBaseTests.swift └── trailbase-ts ├── deploy ├── docker-compose.yml └── k8s │ ├── README.md │ ├── trailbase-deployment.yml │ └── trailbase-service.yml ├── docs ├── .dockerignore ├── .gitignore ├── .prettierignore ├── .prettierrc.mjs ├── Dockerfile ├── README.md ├── astro.config.mjs ├── docker-compose.yml ├── eslint.config.mjs ├── examples │ ├── record_api_curl │ │ ├── create.sh │ │ ├── delete.sh │ │ ├── list.sh │ │ ├── login.sh │ │ ├── read.sh │ │ └── update.sh │ ├── record_api_dart │ │ ├── .gitignore │ │ ├── analysis_options.yaml │ │ ├── lib │ │ │ ├── record_api.dart │ │ │ └── src │ │ │ │ ├── create.dart │ │ │ │ ├── delete.dart │ │ │ │ ├── list.dart │ │ │ │ ├── read.dart │ │ │ │ ├── subscribe.dart │ │ │ │ └── update.dart │ │ ├── pubspec.lock │ │ ├── pubspec.yaml │ │ └── test │ │ │ └── record_api_test.dart │ ├── record_api_dotnet │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── Create.cs │ │ ├── Delete.cs │ │ ├── ExamplesTest.cs │ │ ├── List.cs │ │ ├── Read.cs │ │ ├── Subscribe.cs │ │ ├── Update.cs │ │ └── record_api_dotnet.csproj │ ├── record_api_py │ │ ├── .gitignore │ │ ├── poetry.lock │ │ ├── pyproject.toml │ │ ├── record_api_py │ │ │ ├── __init__.py │ │ │ ├── create.py │ │ │ ├── delete.py │ │ │ ├── list.py │ │ │ ├── read.py │ │ │ └── update.py │ │ └── tests │ │ │ ├── __init__.py │ │ │ └── test_record_api.py │ ├── record_api_rs │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── create.rs │ │ │ ├── delete.rs │ │ │ ├── lib.rs │ │ │ ├── list.rs │ │ │ ├── read.rs │ │ │ ├── subscribe.rs │ │ │ └── update.rs │ ├── record_api_swift │ │ ├── .gitignore │ │ ├── Package.swift │ │ ├── Sources │ │ │ └── RecordApiDocs │ │ │ │ ├── Create.swift │ │ │ │ ├── Delete.swift │ │ │ │ ├── List.swift │ │ │ │ ├── Read.swift │ │ │ │ ├── RecordApiDocs.swift │ │ │ │ └── Update.swift │ │ └── Tests │ │ │ └── RecordApiDocsTests │ │ │ └── RecordApiDocsTests.swift │ └── record_api_ts │ │ ├── eslint.config.mjs │ │ ├── package.json │ │ ├── src │ │ ├── create.ts │ │ ├── delete.ts │ │ ├── list.ts │ │ ├── read.ts │ │ ├── subscribe.ts │ │ └── update.ts │ │ ├── tests │ │ └── basic.test.ts │ │ └── tsconfig.json ├── nginx.conf ├── package.json ├── public │ └── favicon.svg ├── src │ ├── assets │ │ ├── dotnet_logo.svg │ │ ├── flutter_logo.svg │ │ ├── logo_512.webp │ │ ├── nut.svg │ │ ├── python_logo.svg │ │ ├── rust_unofficial_logo.svg │ │ ├── shelve.svg │ │ ├── shelve.webp │ │ ├── swift_logo.svg │ │ └── ts_logo.svg │ ├── components │ │ ├── BarChart.tsx │ │ ├── Footer.astro │ │ ├── LineChart.tsx │ │ ├── ScatterChart.tsx │ │ └── SplitCard.astro │ ├── content │ │ ├── config.ts │ │ └── docs │ │ │ ├── _roadmap.md │ │ │ ├── comparison │ │ │ ├── pocketbase.mdx │ │ │ └── supabase.mdx │ │ │ ├── contact.mdx │ │ │ ├── documentation │ │ │ ├── APIs │ │ │ │ ├── _record_apis.ts │ │ │ │ ├── js_apis.mdx │ │ │ │ └── record_apis.mdx │ │ │ ├── _auth.svg │ │ │ ├── _relations.svg │ │ │ ├── auth.mdx │ │ │ ├── extending.mdx │ │ │ ├── models_and_relations.mdx │ │ │ ├── production.mdx │ │ │ └── type_safety.mdx │ │ │ ├── getting-started │ │ │ ├── _getting_trailbase.md │ │ │ ├── first-cli-app.mdx │ │ │ ├── first-realtime-app.mdx │ │ │ ├── first-ui-app.mdx │ │ │ ├── goals.mdx │ │ │ └── starting-up.mdx │ │ │ ├── index.mdx │ │ │ ├── license.md │ │ │ └── reference │ │ │ ├── _benchmarks │ │ │ ├── benchmarks.tsx │ │ │ ├── fib_pb.json │ │ │ ├── fib_tb.json │ │ │ ├── insert_pb_2025-02-05.json │ │ │ ├── insert_tb.json │ │ │ ├── insert_tb_2025-04-03.json │ │ │ └── supabase_utilization.ts │ │ │ ├── benchmarks.mdx │ │ │ ├── faq.mdx │ │ │ └── roadmap.mdx │ ├── env.d.ts │ ├── lib │ │ ├── darkmode.ts │ │ └── utils.ts │ └── styles │ │ └── global.css └── tsconfig.json ├── examples ├── README.md ├── blog │ ├── .dockerignore │ ├── Caddyfile │ ├── Dockerfile │ ├── Makefile │ ├── README.md │ ├── caddy │ │ ├── config │ │ │ └── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── docker-compose.yml │ ├── flutter │ │ ├── .gitignore │ │ ├── .metadata │ │ ├── analysis_options.yaml │ │ ├── android │ │ │ ├── .gitignore │ │ │ ├── app │ │ │ │ ├── build.gradle │ │ │ │ └── src │ │ │ │ │ ├── debug │ │ │ │ │ └── AndroidManifest.xml │ │ │ │ │ ├── main │ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ │ ├── kotlin │ │ │ │ │ │ └── com │ │ │ │ │ │ │ └── example │ │ │ │ │ │ │ └── trailbase_blog │ │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ │ └── res │ │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── values-night │ │ │ │ │ │ └── styles.xml │ │ │ │ │ │ └── values │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── profile │ │ │ │ │ └── AndroidManifest.xml │ │ │ ├── build.gradle │ │ │ ├── gradle.properties │ │ │ ├── gradle │ │ │ │ └── wrapper │ │ │ │ │ └── gradle-wrapper.properties │ │ │ └── settings.gradle │ │ ├── ios │ │ │ ├── .gitignore │ │ │ ├── Flutter │ │ │ │ ├── AppFrameworkInfo.plist │ │ │ │ ├── Debug.xcconfig │ │ │ │ └── Release.xcconfig │ │ │ ├── Runner.xcodeproj │ │ │ │ ├── project.pbxproj │ │ │ │ ├── project.xcworkspace │ │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ │ └── xcshareddata │ │ │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ │ └── xcshareddata │ │ │ │ │ └── xcschemes │ │ │ │ │ └── Runner.xcscheme │ │ │ ├── Runner.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ ├── Runner │ │ │ │ ├── AppDelegate.swift │ │ │ │ ├── Assets.xcassets │ │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ │ ├── Contents.json │ │ │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ │ │ └── LaunchImage.imageset │ │ │ │ │ │ ├── Contents.json │ │ │ │ │ │ ├── LaunchImage.png │ │ │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ │ │ └── README.md │ │ │ │ ├── Base.lproj │ │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ │ └── Main.storyboard │ │ │ │ ├── Info.plist │ │ │ │ └── Runner-Bridging-Header.h │ │ │ └── RunnerTests │ │ │ │ └── RunnerTests.swift │ │ ├── lib │ │ │ ├── main.dart │ │ │ ├── src │ │ │ │ └── login.dart │ │ │ └── types │ │ │ │ ├── article.dart │ │ │ │ ├── new_profile.dart │ │ │ │ └── profile.dart │ │ ├── linux │ │ │ ├── .gitignore │ │ │ ├── CMakeLists.txt │ │ │ ├── flutter │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── generated_plugin_registrant.cc │ │ │ │ ├── generated_plugin_registrant.h │ │ │ │ └── generated_plugins.cmake │ │ │ ├── main.cc │ │ │ ├── my_application.cc │ │ │ └── my_application.h │ │ ├── macos │ │ │ ├── .gitignore │ │ │ ├── Flutter │ │ │ │ ├── Flutter-Debug.xcconfig │ │ │ │ ├── Flutter-Release.xcconfig │ │ │ │ └── GeneratedPluginRegistrant.swift │ │ │ ├── Runner.xcodeproj │ │ │ │ ├── project.pbxproj │ │ │ │ ├── project.xcworkspace │ │ │ │ │ └── xcshareddata │ │ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ │ └── xcshareddata │ │ │ │ │ └── xcschemes │ │ │ │ │ └── Runner.xcscheme │ │ │ ├── Runner.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ ├── Runner │ │ │ │ ├── AppDelegate.swift │ │ │ │ ├── Assets.xcassets │ │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ │ ├── Contents.json │ │ │ │ │ │ ├── app_icon_1024.png │ │ │ │ │ │ ├── app_icon_128.png │ │ │ │ │ │ ├── app_icon_16.png │ │ │ │ │ │ ├── app_icon_256.png │ │ │ │ │ │ ├── app_icon_32.png │ │ │ │ │ │ ├── app_icon_512.png │ │ │ │ │ │ └── app_icon_64.png │ │ │ │ ├── Base.lproj │ │ │ │ │ └── MainMenu.xib │ │ │ │ ├── Configs │ │ │ │ │ ├── AppInfo.xcconfig │ │ │ │ │ ├── Debug.xcconfig │ │ │ │ │ ├── Release.xcconfig │ │ │ │ │ └── Warnings.xcconfig │ │ │ │ ├── DebugProfile.entitlements │ │ │ │ ├── Info.plist │ │ │ │ ├── MainFlutterWindow.swift │ │ │ │ └── Release.entitlements │ │ │ └── RunnerTests │ │ │ │ └── RunnerTests.swift │ │ ├── pubspec.lock │ │ ├── pubspec.yaml │ │ ├── web │ │ │ ├── auth.html │ │ │ ├── favicon.png │ │ │ ├── icons │ │ │ │ ├── Icon-192.png │ │ │ │ ├── Icon-512.png │ │ │ │ ├── Icon-maskable-192.png │ │ │ │ └── Icon-maskable-512.png │ │ │ ├── index.html │ │ │ └── manifest.json │ │ └── windows │ │ │ ├── .gitignore │ │ │ ├── CMakeLists.txt │ │ │ ├── flutter │ │ │ ├── CMakeLists.txt │ │ │ ├── generated_plugin_registrant.cc │ │ │ ├── generated_plugin_registrant.h │ │ │ └── generated_plugins.cmake │ │ │ └── runner │ │ │ ├── CMakeLists.txt │ │ │ ├── Runner.rc │ │ │ ├── flutter_window.cpp │ │ │ ├── flutter_window.h │ │ │ ├── main.cpp │ │ │ ├── resource.h │ │ │ ├── resources │ │ │ └── app_icon.ico │ │ │ ├── runner.exe.manifest │ │ │ ├── utils.cpp │ │ │ ├── utils.h │ │ │ ├── win32_window.cpp │ │ │ └── win32_window.h │ ├── package.json │ ├── schema │ │ ├── new_profile.json │ │ └── profile.json │ ├── screenshots │ │ ├── screenshot_flutter.png │ │ └── screenshot_web.png │ ├── traildepot │ │ ├── .gitignore │ │ ├── config.textproto │ │ ├── migrations │ │ │ ├── U1725019361__create_profiles.sql │ │ │ ├── U1725019362__create_articles.sql │ │ │ ├── U1725019363__create_editor_group.sql │ │ │ ├── U1725019371__add_admin_user.sql │ │ │ ├── U1725019372__add_users.sql │ │ │ └── U1725019381__add_article.sql │ │ └── uploads │ │ │ ├── 0328bc95-9622-42e7-a609-625769a797c2 │ │ │ └── 40e8d2a2-b025-435e-9aa0-4cb6b895ab2a │ └── web │ │ ├── .gitignore │ │ ├── .prettierignore │ │ ├── .prettierrc.mjs │ │ ├── astro.config.mjs │ │ ├── eslint.config.mjs │ │ ├── package.json │ │ ├── public │ │ ├── default.svg │ │ ├── image.png │ │ └── image.svg │ │ ├── src │ │ ├── assets │ │ │ └── default.jpg │ │ ├── components │ │ │ ├── ArticleComposeButton.tsx │ │ │ ├── ArticleList.tsx │ │ │ ├── ArticlePage.tsx │ │ │ ├── Auth.tsx │ │ │ ├── PublishDate.tsx │ │ │ ├── Tag.tsx │ │ │ └── general │ │ │ │ ├── Footer.astro │ │ │ │ ├── HamburgerButton.astro │ │ │ │ ├── Header.astro │ │ │ │ ├── ModeSwitch.astro │ │ │ │ ├── Navigation.astro │ │ │ │ └── Tag.astro │ │ ├── css │ │ │ └── style.css │ │ ├── env.d.ts │ │ ├── layouts │ │ │ └── Base.astro │ │ ├── lib │ │ │ ├── article.ts │ │ │ ├── client.ts │ │ │ └── profile.ts │ │ └── pages │ │ │ ├── article.astro │ │ │ ├── compose.astro │ │ │ └── index.astro │ │ ├── tailwind.config.mjs │ │ ├── tsconfig.json │ │ └── types │ │ ├── article.ts │ │ ├── new_profile.ts │ │ └── profile.ts ├── coffee-vector-search │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── README.md │ ├── arabica_data_cleaned.csv │ ├── assets │ │ └── screenshot.png │ ├── eslint.config.js │ ├── import.sql │ ├── index.html │ ├── package.json │ ├── screenshots │ │ └── screenshot0.png │ ├── src │ │ ├── App.css │ │ ├── App.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── traildepot │ │ ├── .gitignore │ │ ├── config.textproto │ │ ├── migrations │ │ │ └── U1732092075__crate_coffee_table.sql │ │ └── scripts │ │ │ └── main.ts │ ├── tsconfig.json │ └── vite.config.ts ├── collab-clicker-ssr │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── eslint.config.mjs │ ├── index.html │ ├── package.json │ ├── pnpm-lock.yaml │ ├── screenshots │ │ └── screenshot0.png │ ├── server.js │ ├── src │ │ ├── App.tsx │ │ ├── entry-client.tsx │ │ ├── entry-server.tsx │ │ ├── index.css │ │ └── vite-env.d.ts │ ├── tailwind.config.ts │ ├── traildepot │ │ ├── .gitignore │ │ ├── config.textproto │ │ ├── migrations │ │ │ ├── U1725019360__create_admin_user.sql │ │ │ └── U1737638313__create_table_counter.sql │ │ └── scripts │ │ │ └── main.ts │ ├── tsconfig.json │ └── vite.config.ts ├── custom-binary │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── data-cli-tutorial │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── data │ │ ├── README.md │ │ └── Top_1000_IMDb_movies_New_version.csv │ ├── eslint.config.mjs │ ├── package.json │ ├── schema │ │ └── movie.json │ ├── src │ │ ├── fill.ts │ │ └── index.ts │ ├── traildepot │ │ ├── .gitignore │ │ ├── config.textproto │ │ └── migrations │ │ │ ├── U1725019360__add_admin_user.sql │ │ │ └── U1728810800__create_table_movies.sql │ ├── tsconfig.json │ └── types │ │ └── movie.ts └── local-first │ └── traildepot │ ├── trailbase.d.ts │ └── trailbase.js ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── trailbase-apalis ├── Cargo.toml ├── migrations │ └── V1__initial.sql └── src │ ├── context.rs │ ├── from_row.rs │ ├── lib.rs │ └── sqlite.rs ├── trailbase-assets ├── Cargo.toml ├── askama.toml ├── build.rs ├── js │ ├── admin │ │ ├── .gitignore │ │ ├── .prettierignore │ │ ├── .prettierrc │ │ ├── README.md │ │ ├── eslint.config.mjs │ │ ├── index.html │ │ ├── package.json │ │ ├── postcss.config.mjs │ │ ├── proto │ │ │ ├── config.ts │ │ │ ├── config_api.ts │ │ │ ├── google │ │ │ │ └── protobuf │ │ │ │ │ └── descriptor.ts │ │ │ └── vault.ts │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── assets │ │ │ │ ├── countries-110m.json │ │ │ │ ├── favicon.svg │ │ │ │ └── logo_104.webp │ │ │ ├── components │ │ │ │ ├── DestructiveActionButton.tsx │ │ │ │ ├── ErdGraph.tsx │ │ │ │ ├── ErrorBoundary.tsx │ │ │ │ ├── FilterBar.tsx │ │ │ │ ├── FormFields.tsx │ │ │ │ ├── Header.tsx │ │ │ │ ├── IconButton.tsx │ │ │ │ ├── IndexPage.tsx │ │ │ │ ├── NavBar.tsx │ │ │ │ ├── SafeSheet.tsx │ │ │ │ ├── Spinner.tsx │ │ │ │ ├── SplitView.tsx │ │ │ │ ├── Table.tsx │ │ │ │ ├── Version.tsx │ │ │ │ ├── accounts │ │ │ │ │ ├── AccountsPage.tsx │ │ │ │ │ └── AddUser.tsx │ │ │ │ ├── auth │ │ │ │ │ ├── AuthButton.tsx │ │ │ │ │ └── LoginPage.tsx │ │ │ │ ├── editor │ │ │ │ │ └── EditorPage.tsx │ │ │ │ ├── erd │ │ │ │ │ └── ErdPage.tsx │ │ │ │ ├── logs │ │ │ │ │ └── LogsPage.tsx │ │ │ │ ├── settings │ │ │ │ │ ├── AuthSettings.tsx │ │ │ │ │ ├── EmailSettings.tsx │ │ │ │ │ ├── JobSettings.tsx │ │ │ │ │ ├── SchemaSettings.tsx │ │ │ │ │ └── SettingsPage.tsx │ │ │ │ ├── tables │ │ │ │ │ ├── CreateAlterColumnForm.tsx │ │ │ │ │ ├── CreateAlterIndex.tsx │ │ │ │ │ ├── CreateAlterTable.tsx │ │ │ │ │ ├── InsertUpdateRow.tsx │ │ │ │ │ ├── RecordApiSettings.tsx │ │ │ │ │ ├── SchemaDownload.tsx │ │ │ │ │ ├── TablePane.tsx │ │ │ │ │ └── TablesPage.tsx │ │ │ │ └── ui │ │ │ │ │ ├── accordion.tsx │ │ │ │ │ ├── badge.tsx │ │ │ │ │ ├── button.tsx │ │ │ │ │ ├── card.tsx │ │ │ │ │ ├── checkbox.tsx │ │ │ │ │ ├── dialog.tsx │ │ │ │ │ ├── hover-card.tsx │ │ │ │ │ ├── label.tsx │ │ │ │ │ ├── resizable.tsx │ │ │ │ │ ├── select.tsx │ │ │ │ │ ├── separator.tsx │ │ │ │ │ ├── sheet.tsx │ │ │ │ │ ├── switch.tsx │ │ │ │ │ ├── table.tsx │ │ │ │ │ ├── tabs.tsx │ │ │ │ │ ├── text-field.tsx │ │ │ │ │ ├── toast.tsx │ │ │ │ │ ├── toggle.tsx │ │ │ │ │ └── tooltip.tsx │ │ │ ├── index.tsx │ │ │ └── lib │ │ │ │ ├── config.ts │ │ │ │ ├── convert.ts │ │ │ │ ├── fetch.ts │ │ │ │ ├── fexpr.ts │ │ │ │ ├── info.ts │ │ │ │ ├── jobs.ts │ │ │ │ ├── list.ts │ │ │ │ ├── logs.ts │ │ │ │ ├── name.ts │ │ │ │ ├── parse.ts │ │ │ │ ├── row.ts │ │ │ │ ├── schema.ts │ │ │ │ ├── table.ts │ │ │ │ ├── user.ts │ │ │ │ └── utils.ts │ │ ├── tailwind.config.ts │ │ ├── tests │ │ │ ├── form.test.tsx │ │ │ └── util.test.ts │ │ ├── tsconfig.json │ │ ├── ui.config.json │ │ └── vite.config.mts │ ├── auth │ │ ├── .gitignore │ │ ├── .prettierignore │ │ ├── .prettierrc.mjs │ │ ├── astro.config.mjs │ │ ├── eslint.config.mjs │ │ ├── package.json │ │ ├── src │ │ │ ├── assets │ │ │ │ └── favicon.svg │ │ │ ├── components │ │ │ │ ├── AlertBox.astro │ │ │ │ ├── Button.astro │ │ │ │ ├── Card.astro │ │ │ │ ├── ErrorBoundary.tsx │ │ │ │ ├── Form.astro │ │ │ │ ├── ListOauthProviders.tsx │ │ │ │ ├── Profile.tsx │ │ │ │ ├── TextFieldInput.astro │ │ │ │ ├── TextFieldLabel.astro │ │ │ │ └── ui │ │ │ │ │ ├── button.tsx │ │ │ │ │ ├── card.tsx │ │ │ │ │ ├── dialog.tsx │ │ │ │ │ ├── label.tsx │ │ │ │ │ ├── text-field.tsx │ │ │ │ │ └── toast.tsx │ │ │ ├── env.d.ts │ │ │ ├── layouts │ │ │ │ └── BaseLayout.astro │ │ │ ├── lib │ │ │ │ ├── constants.ts │ │ │ │ └── utils.ts │ │ │ └── pages │ │ │ │ ├── change_email.astro │ │ │ │ ├── change_password.astro │ │ │ │ ├── login.astro │ │ │ │ ├── profile.astro │ │ │ │ ├── register.astro │ │ │ │ └── reset_password │ │ │ │ ├── request.astro │ │ │ │ └── update.astro │ │ ├── tailwind.config.ts │ │ ├── tsconfig.json │ │ └── ui.config.json │ ├── bindings │ │ ├── AlterIndexRequest.ts │ │ ├── AlterTableRequest.ts │ │ ├── AuthCodeToTokenRequest.ts │ │ ├── ChangeEmailRequest.ts │ │ ├── ChangePasswordRequest.ts │ │ ├── Check.ts │ │ ├── Column.ts │ │ ├── ColumnDataType.ts │ │ ├── ColumnOption.ts │ │ ├── ColumnOrder.ts │ │ ├── ConfiguredOAuthProvidersResponse.ts │ │ ├── ConflictResolution.ts │ │ ├── CreateIndexRequest.ts │ │ ├── CreateIndexResponse.ts │ │ ├── CreateTableRequest.ts │ │ ├── CreateTableResponse.ts │ │ ├── CreateUserRequest.ts │ │ ├── DeleteRowRequest.ts │ │ ├── DeleteRowsRequest.ts │ │ ├── DeleteUserRequest.ts │ │ ├── DropIndexRequest.ts │ │ ├── DropTableRequest.ts │ │ ├── ForeignKey.ts │ │ ├── GeneratedExpressionMode.ts │ │ ├── GeoipCity.ts │ │ ├── InfoResponse.ts │ │ ├── InsertRowRequest.ts │ │ ├── Job.ts │ │ ├── JsonSchema.ts │ │ ├── ListJobsResponse.ts │ │ ├── ListJsonSchemasResponse.ts │ │ ├── ListLogsResponse.ts │ │ ├── ListRowsResponse.ts │ │ ├── ListSchemasResponse.ts │ │ ├── ListUsersResponse.ts │ │ ├── LogJson.ts │ │ ├── LoginRequest.ts │ │ ├── LoginResponse.ts │ │ ├── LoginStatusResponse.ts │ │ ├── LogoutRequest.ts │ │ ├── Mode.ts │ │ ├── OAuthProviderEntry.ts │ │ ├── OAuthProviderResponse.ts │ │ ├── ParseRequest.ts │ │ ├── ParseResponse.ts │ │ ├── QualifiedName.ts │ │ ├── QueryRequest.ts │ │ ├── QueryResponse.ts │ │ ├── ReadFilesRequest.ts │ │ ├── ReferentialAction.ts │ │ ├── RefreshRequest.ts │ │ ├── RefreshResponse.ts │ │ ├── RunJobRequest.ts │ │ ├── RunJobResponse.ts │ │ ├── Stats.ts │ │ ├── Table.ts │ │ ├── TableIndex.ts │ │ ├── TableTrigger.ts │ │ ├── UniqueConstraint.ts │ │ ├── UpdateJsonSchemaRequest.ts │ │ ├── UpdateRowRequest.ts │ │ ├── UpdateUserRequest.ts │ │ ├── UserJson.ts │ │ ├── View.ts │ │ └── serde_json │ │ │ └── JsonValue.ts │ ├── client │ │ ├── .gitignore │ │ ├── README.md │ │ ├── eslint.config.mjs │ │ ├── package.json │ │ ├── src │ │ │ └── index.ts │ │ ├── tests │ │ │ ├── base64.test.ts │ │ │ ├── encoding.bench.ts │ │ │ ├── integration │ │ │ │ ├── auth_integration.test.ts │ │ │ │ ├── client_integration.test.ts │ │ │ │ └── v8_integration.test.ts │ │ │ └── integration_test_runner.ts │ │ ├── tsconfig.json │ │ └── vitest.config.ts │ └── shared │ │ ├── assets │ │ └── oauth2 │ │ │ ├── discord.svg │ │ │ ├── facebook.svg │ │ │ ├── gitlab.svg │ │ │ ├── google.svg │ │ │ ├── microsoft.svg │ │ │ └── oidc.svg │ │ ├── global.css │ │ └── kobalte.css └── src │ ├── assets.rs │ ├── auth.rs │ ├── lib.rs │ └── version.rs ├── trailbase-build ├── Cargo.toml └── src │ └── lib.rs ├── trailbase-cli ├── Cargo.toml └── src │ ├── args.rs │ ├── bin │ └── trail.rs │ └── lib.rs ├── trailbase-core ├── .gitignore ├── Cargo.toml ├── benches │ └── benchmark.rs ├── build.rs ├── migrations │ ├── logs │ │ ├── V1__initial.sql │ │ └── V2__user_id.sql │ └── main │ │ ├── U2__file_deletions.sql │ │ └── V1__initial.sql ├── proto │ ├── config.proto │ ├── config_api.proto │ └── vault.proto ├── src │ ├── admin │ │ ├── config │ │ │ ├── get_config.rs │ │ │ ├── mod.rs │ │ │ └── update_config.rs │ │ ├── error.rs │ │ ├── info.rs │ │ ├── jobs │ │ │ ├── list_jobs.rs │ │ │ ├── mod.rs │ │ │ └── run_job.rs │ │ ├── json_schema │ │ │ ├── get_api_json_schema.rs │ │ │ └── mod.rs │ │ ├── jwt.rs │ │ ├── list_logs.rs │ │ ├── mod.rs │ │ ├── oauth_providers.rs │ │ ├── parse.rs │ │ ├── query.rs │ │ ├── rows │ │ │ ├── delete_rows.rs │ │ │ ├── insert_row.rs │ │ │ ├── list_rows.rs │ │ │ ├── mod.rs │ │ │ ├── read_files.rs │ │ │ └── update_row.rs │ │ ├── table │ │ │ ├── alter_index.rs │ │ │ ├── alter_table.rs │ │ │ ├── create_index.rs │ │ │ ├── create_table.rs │ │ │ ├── drop_index.rs │ │ │ ├── drop_table.rs │ │ │ ├── list_tables.rs │ │ │ └── mod.rs │ │ ├── user │ │ │ ├── create_user.rs │ │ │ ├── delete_user.rs │ │ │ ├── list_users.rs │ │ │ ├── mod.rs │ │ │ └── update_user.rs │ │ └── util.rs │ ├── app_state.rs │ ├── auth │ │ ├── api │ │ │ ├── avatar.rs │ │ │ ├── change_email.rs │ │ │ ├── change_password.rs │ │ │ ├── delete.rs │ │ │ ├── login.rs │ │ │ ├── logout.rs │ │ │ ├── mod.rs │ │ │ ├── refresh.rs │ │ │ ├── register.rs │ │ │ ├── reset_password.rs │ │ │ ├── token.rs │ │ │ └── verify_email.rs │ │ ├── auth_test.rs │ │ ├── error.rs │ │ ├── jwt.rs │ │ ├── mod.rs │ │ ├── oauth │ │ │ ├── callback.rs │ │ │ ├── list_providers.rs │ │ │ ├── login.rs │ │ │ ├── mod.rs │ │ │ ├── oauth_test.rs │ │ │ ├── provider.rs │ │ │ ├── providers │ │ │ │ ├── discord.rs │ │ │ │ ├── facebook.rs │ │ │ │ ├── gitlab.rs │ │ │ │ ├── google.rs │ │ │ │ ├── microsoft.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── oidc.rs │ │ │ │ └── test.rs │ │ │ └── state.rs │ │ ├── options.rs │ │ ├── password.rs │ │ ├── tokens.rs │ │ ├── ui │ │ │ └── mod.rs │ │ ├── user.rs │ │ └── util.rs │ ├── config.rs │ ├── connection.rs │ ├── constants.rs │ ├── data_dir.rs │ ├── email.rs │ ├── extract │ │ ├── either.rs │ │ ├── mod.rs │ │ └── multipart.rs │ ├── js │ │ ├── mod.rs │ │ └── runtime.rs │ ├── lib.rs │ ├── listing.rs │ ├── logging.rs │ ├── migrations.rs │ ├── queue.rs │ ├── records │ │ ├── create_record.rs │ │ ├── delete_record.rs │ │ ├── error.rs │ │ ├── files.rs │ │ ├── json_schema.rs │ │ ├── list_records.rs │ │ ├── mod.rs │ │ ├── params.rs │ │ ├── query_builder.rs │ │ ├── read_record.rs │ │ ├── record_api.rs │ │ ├── sql_to_json.rs │ │ ├── subscribe.rs │ │ ├── test_utils.rs │ │ ├── update_record.rs │ │ └── validate.rs │ ├── scheduler.rs │ ├── schema_metadata.rs │ ├── server │ │ ├── init.rs │ │ ├── mod.rs │ │ └── serve.rs │ ├── test.rs │ ├── transaction.rs │ ├── util.rs │ └── value_notifier.rs ├── templates │ ├── create_record_access_query.sql │ ├── create_record_query.sql │ ├── list_record_query.sql │ ├── read_record_query.sql │ ├── read_record_query_expanded.sql │ ├── subscription_record_read.sql │ ├── update_record_access_query.sql │ └── update_record_query.sql └── tests │ ├── admin_permissions_test.rs │ ├── integration_test.rs │ └── tls_test.rs ├── trailbase-extension ├── Cargo.toml ├── src │ ├── geoip.rs │ ├── jsonschema.rs │ ├── lib.rs │ ├── password.rs │ ├── regex.rs │ ├── uuid.rs │ └── validators.rs └── testdata │ └── GeoIP2-City-Test.mmdb ├── trailbase-js ├── Cargo.toml ├── assets │ └── runtime │ │ ├── .gitignore │ │ ├── eslint.config.mjs │ │ ├── package.json │ │ ├── src │ │ ├── deno.ts │ │ ├── index.ts │ │ ├── trailbase.ts │ │ └── util.ts │ │ ├── tests │ │ └── runtime.test.ts │ │ ├── tsconfig.json │ │ └── vite.config.ts ├── build.rs └── src │ ├── import_provider.rs │ ├── lib.rs │ ├── runtime.rs │ └── util.rs ├── trailbase-qs ├── Cargo.toml └── src │ ├── column_rel_value.rs │ ├── filter.rs │ ├── lib.rs │ ├── query.rs │ ├── util.rs │ └── value.rs ├── trailbase-refinery ├── Cargo.toml ├── src │ ├── drivers │ │ ├── mod.rs │ │ └── rusqlite.rs │ ├── error.rs │ ├── lib.rs │ ├── runner.rs │ ├── traits │ │ ├── async.rs │ │ ├── mod.rs │ │ └── sync.rs │ └── util.rs └── tests │ ├── migrations │ ├── V1-2 │ │ ├── V1__initial.rs │ │ └── V2__add_cars_and_motos_table.sql │ ├── V3 │ │ └── V3__add_brand_to_cars_table.sql │ └── V4__add_year_to_motos_table.rs │ └── migrations_unversioned │ └── U0__merge_out_of_order.sql ├── trailbase-schema ├── Cargo.toml ├── bindings │ ├── Check.ts │ ├── Column.ts │ ├── ColumnDataType.ts │ ├── ColumnOption.ts │ ├── ConflictResolution.ts │ ├── ForeignKey.ts │ ├── GeneratedExpressionMode.ts │ ├── ReferentialAction.ts │ ├── Table.ts │ └── UniqueConstraint.ts └── src │ ├── error.rs │ ├── file.rs │ ├── json_schema.rs │ ├── lib.rs │ ├── metadata.rs │ ├── registry.rs │ └── sqlite.rs ├── trailbase-sqlite ├── Cargo.toml ├── benches │ ├── benchmark.rs │ ├── connection.rs │ └── error.rs ├── examples │ └── uuid.rs └── src │ ├── connection.rs │ ├── error.rs │ ├── lib.rs │ ├── params.rs │ ├── rows.rs │ └── tests.rs └── vendor └── sqlean ├── Cargo.toml ├── LICENSE ├── README.md ├── bindings.h ├── build.rs └── src └── lib.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | # Use mold linker. Found not to make a big difference for build times. 2 | # Link time is minuscule compared to code-generation. 3 | # 4 | # [target.x86_64-unknown-linux-gnu] 5 | # linker = "clang" 6 | # rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold"] 7 | 8 | # Build static binary by default. We specify this explicitly as part of the 9 | # Docker (see Dockerfile) and Github (see workflows) release flows. 10 | # Static binaries are really only a Linux thing with other OSs lacking a stable 11 | # syscall API. 12 | # 13 | # rustflags = ["-C", "target-feature=+crt-static"] 14 | 15 | [env] 16 | TS_RS_EXPORT_DIR = { value = "./trailbase-assets/js/bindings", relative = true } 17 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | target/ 2 | traildepot/ 3 | **/traildepot/ 4 | **/target/ 5 | **/target/ 6 | **/node_modules/ 7 | **/dist/ 8 | 9 | client 10 | !client/trailbase-rs 11 | deploy/ 12 | docs/ 13 | !docs/examples/record_api_rs 14 | examples/ 15 | !examples/custom-binary 16 | 17 | Dockerfile* 18 | .docker* 19 | 20 | # Include parts of the .git/ folder needed to bake version info into the 21 | # binary. 22 | .git* 23 | !.git/ 24 | .git/modules 25 | 26 | .hooks/ 27 | .cargo/ 28 | *.image 29 | .rustfmt.toml 30 | .env 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build artifacts 2 | target/ 3 | node_modules/ 4 | 5 | # macOS-specific files 6 | .DS_Store 7 | 8 | # jetbrains setting folder 9 | .idea/ 10 | 11 | # Dev artifacts 12 | public/ 13 | 14 | # Avoid `pnpm-lock.yaml` files when not in the root. They are produced when 15 | # building with `--ignore-worspace`. 16 | **/pnpm-lock.yaml 17 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/sqlean/bundled/sqlean"] 2 | path = vendor/sqlean/bundled/sqlean 3 | url = https://github.com/trailbaseio/sqlean 4 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | # Docs: https://rust-lang.github.io/rustfmt/ 2 | edition = "2021" 3 | brace_style = "SameLineWhere" 4 | empty_item_single_line = true 5 | max_width = 100 6 | comment_width = 100 7 | wrap_comments = true 8 | tab_spaces = 2 9 | -------------------------------------------------------------------------------- /assets/logo_104.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/assets/logo_104.webp -------------------------------------------------------------------------------- /client/testfixture/.gitignore: -------------------------------------------------------------------------------- 1 | backups/ 2 | data/ 3 | secrets/ 4 | uploads/ 5 | 6 | trailbase.d.ts 7 | trailbase.js 8 | 9 | *.mmdb 10 | -------------------------------------------------------------------------------- /client/testfixture/Makefile: -------------------------------------------------------------------------------- 1 | clean: 2 | rm -rf data/ uploads/ 3 | 4 | .PHONY: clean 5 | -------------------------------------------------------------------------------- /client/testfixture/migrations/U1725019360__create_admin_user.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO _user 2 | (id, email, password_hash, verified, admin) 3 | VALUES 4 | (uuid_v7(), 'admin@localhost', (hash_password('secret')), TRUE, TRUE); 5 | -------------------------------------------------------------------------------- /client/testfixture/migrations/U1728810800__create_table_movies.sql: -------------------------------------------------------------------------------- 1 | -- A table schema to hold the IMDB test dataset from: 2 | -- https://www.kaggle.com/datasets/inductiveanks/top-1000-imdb-movies-dataset/data 3 | -- 4 | -- The only TrailBase API requirements are: "STRICT" typing and a INTEGER (or 5 | -- UUIDv7) PRIMARY KEY column. 6 | CREATE TABLE IF NOT EXISTS movies ( 7 | rank INTEGER PRIMARY KEY, 8 | name TEXT NOT NULL, 9 | year ANY NOT NULL, 10 | watch_time INTEGER NOT NULL, 11 | rating REAL NOT NULL, 12 | metascore ANY, 13 | gross ANY, 14 | votes TEXT NOT NULL, 15 | description TEXT NOT NULL 16 | ) STRICT; 17 | -------------------------------------------------------------------------------- /client/testfixture/secrets/secrets.textproto: -------------------------------------------------------------------------------- 1 | # Auto-generated config.Vault textproto 2 | secrets: [ 3 | { 4 | key: "TRAIL_AUTH_OAUTH_PROVIDERS_DISCORD_CLIENT_SECRET" 5 | value: "invalid_discord_password" 6 | }, 7 | { 8 | key: "TRAIL_AUTH_OAUTH_PROVIDERS_OIDC0_CLIENT_SECRET" 9 | value: "invalid_oidc_password" 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /client/trailbase-dart/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | 5 | # Avoid committing pubspec.lock for library packages; see 6 | # https://dart.dev/guides/libraries/private-files#pubspeclock. 7 | pubspec.lock 8 | -------------------------------------------------------------------------------- /client/trailbase-dart/.pubignore: -------------------------------------------------------------------------------- 1 | test 2 | analysis_options.yaml 3 | -------------------------------------------------------------------------------- /client/trailbase-dart/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.4.0 4 | 5 | - More powerful, nested list filters intrdocued with TrailBase v0.12.0. 6 | 7 | ## 0.3.0 8 | 9 | - Add `count` parameter to RecordApi.list to retrieve `total_count` at extra cost. 10 | Requires TB >= v0.6.0. 11 | - Add `expand` parameter for RecordApi.(list|get) to expand foreign records. 12 | Requires TB >= v0.6.0. 13 | 14 | ## 0.2.1 15 | 16 | - Fix heartbeat decoding issue with record subscriptions. 17 | 18 | ## 0.2.0 19 | 20 | - Return ListResponse from RecordApi::list. 21 | 22 | ## 0.1.2 23 | 24 | - Add support for "realtime" subscriptions to listen for record changes: 25 | insertions, updates, deletions. 26 | 27 | ## 0.1.0 28 | 29 | ### Features 30 | 31 | - Initial client release including support for authentication and record APIs. 32 | -------------------------------------------------------------------------------- /client/trailbase-dart/LICENSE: -------------------------------------------------------------------------------- 1 | ../../LICENSE -------------------------------------------------------------------------------- /client/trailbase-dart/README.md: -------------------------------------------------------------------------------- 1 | # TrailBase Client 2 | 3 | TrailBase is a [blazingly](https://trailbase.io/reference/benchmarks/) fast, 4 | open-source application server with type-safe APIs, built-in JS/ES6/TS runtime, 5 | realtime, auth, and admin UI built on Rust, SQLite & V8. 6 | 7 | For more context, documentation, and an online demo, check out the website: 8 | [trailbase.io](https://trailbase.io). 9 | 10 | This is the first-party client for hooking up your Flutter or Dart applications 11 | with TrailBase. 12 | While we're working on better documentation, an example Flutter app can be 13 | found in the repository under: 14 | [`/examples/blog/flutter`](https://github.com/trailbaseio/trailbase/tree/main/examples/blog/flutter). 15 | -------------------------------------------------------------------------------- /client/trailbase-dart/lib/trailbase.dart: -------------------------------------------------------------------------------- 1 | library; 2 | 3 | export 'src/client.dart'; 4 | export 'src/pkce.dart'; 5 | export 'src/sse.dart'; 6 | -------------------------------------------------------------------------------- /client/trailbase-dart/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: trailbase 2 | description: Thing client library for TrailBase. 3 | homepage: https://trailbase.io 4 | repository: https://github.com/trailbaseio/trailbase 5 | version: 0.4.0 6 | 7 | environment: 8 | sdk: ^3.5.3 9 | 10 | dependencies: 11 | crypto: ^3.0.6 12 | dio: ^5.8.0+1 13 | jwt_decoder: ^2.0.1 14 | logging: ^1.3.0 15 | 16 | dev_dependencies: 17 | lints: ^5.1.1 18 | test: ^1.25.15 19 | -------------------------------------------------------------------------------- /client/trailbase-dotnet/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | 4 | # docfx documentation. 5 | _site/ 6 | api/ 7 | -------------------------------------------------------------------------------- /client/trailbase-dotnet/docs/images/favicon.svg: -------------------------------------------------------------------------------- 1 | ../../../../assets/favicon.svg -------------------------------------------------------------------------------- /client/trailbase-dotnet/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | _layout: landing 3 | --- 4 | 5 | # TrailBase Client 6 | 7 | Auto-generate reference documentation. 8 | -------------------------------------------------------------------------------- /client/trailbase-dotnet/docs/toc.yml: -------------------------------------------------------------------------------- 1 | - name: API 2 | href: api/ 3 | -------------------------------------------------------------------------------- /client/trailbase-dotnet/src/README.md: -------------------------------------------------------------------------------- 1 | # TrailBase Client 2 | 3 | TrailBase is a [blazingly](https://trailbase.io/reference/benchmarks/) fast, 4 | open-source application server with type-safe APIs, built-in JS/ES6/TS runtime, 5 | realtime, auth, and admin UI built on Rust, SQLite & V8. 6 | 7 | For more context, documentation, and an online demo, check out our website: 8 | [trailbase.io](https://trailbase.io). 9 | -------------------------------------------------------------------------------- /client/trailbase-py/.gitignore: -------------------------------------------------------------------------------- 1 | **/__pycache__/ 2 | poetry.lock 3 | dist/ 4 | 5 | Makefile 6 | -------------------------------------------------------------------------------- /client/trailbase-py/README.md: -------------------------------------------------------------------------------- 1 | # TrailBase Client 2 | 3 | TrailBase is a [blazingly](https://trailbase.io/reference/benchmarks/) fast, 4 | open-source application server with type-safe APIs, built-in JS/ES6/TS runtime, 5 | realtime, auth, and admin UI built on Rust, SQLite & V8. 6 | 7 | For more context, documentation, and an online demo, check out our website: 8 | [trailbase.io](https://trailbase.io). 9 | -------------------------------------------------------------------------------- /client/trailbase-py/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | create = true 4 | -------------------------------------------------------------------------------- /client/trailbase-py/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/client/trailbase-py/tests/__init__.py -------------------------------------------------------------------------------- /client/trailbase-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trailbase-client" 3 | version = "0.5.0" 4 | edition = "2024" 5 | license = "OSL-3.0" 6 | description = "Client for accessing TrailBase's record APIs" 7 | homepage = "https://trailbase.io" 8 | repository = "https://github.com/trailbaseio/trailbase" 9 | readme = "../../README.md" 10 | exclude = [ 11 | "tests", 12 | ] 13 | 14 | [dependencies] 15 | eventsource-stream = "0.2.3" 16 | futures = "0.3.31" 17 | jsonwebtoken = { version = "9.3.0", default-features = false } 18 | parking_lot = "0.12.3" 19 | reqwest = { version = "0.12.8", features = ["stream"] } 20 | serde = { version = "1.0.217", features = ["derive"] } 21 | serde_json = "1.0.135" 22 | thiserror = "2.0.12" 23 | tracing = "0.1.41" 24 | url = "2.5.4" 25 | 26 | [dev-dependencies] 27 | tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] } 28 | -------------------------------------------------------------------------------- /client/trailbase-swift/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /client/trailbase-swift/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "originHash" : "f178e8cc250f0464a9dbb351c0d4ce7859ce76516acf66e503459441d4892791", 3 | "pins" : [ 4 | { 5 | "identity" : "swift-subprocess", 6 | "kind" : "remoteSourceControl", 7 | "location" : "https://github.com/swiftlang/swift-subprocess.git", 8 | "state" : { 9 | "branch" : "main", 10 | "revision" : "288df8180ce5d8221a40b57f2ac43a4d1870ece5" 11 | } 12 | }, 13 | { 14 | "identity" : "swift-system", 15 | "kind" : "remoteSourceControl", 16 | "location" : "https://github.com/apple/swift-system", 17 | "state" : { 18 | "revision" : "a34201439c74b53f0fd71ef11741af7e7caf01e1", 19 | "version" : "1.4.2" 20 | } 21 | } 22 | ], 23 | "version" : 3 24 | } 25 | -------------------------------------------------------------------------------- /client/trailbase-ts: -------------------------------------------------------------------------------- 1 | ../trailbase-assets/js/client/ -------------------------------------------------------------------------------- /deploy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | trail: 4 | image: docker.io/trailbase/trailbase:latest 5 | # build: . 6 | ports: 7 | - "${PORT:-4000}:4000" 8 | restart: unless-stopped 9 | volumes: 10 | - ${DATA_DIR:-.}/traildepot:/app/traildepot 11 | environment: 12 | # Override the default env-logger. 13 | # RUST_LOG: "info,refinery_core=warn" 14 | RUST_BACKTRACE: "1" 15 | command: "/app/trail --data-dir /app/traildepot run --address 0.0.0.0:4000" 16 | -------------------------------------------------------------------------------- /deploy/k8s/trailbase-service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: trailbase-service 5 | spec: 6 | selector: 7 | app: trailbase 8 | ports: 9 | - protocol: TCP 10 | port: 4000 11 | targetPort: 4000 12 | -------------------------------------------------------------------------------- /docs/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | .git* 4 | *.log 5 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /docs/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore files for PNPM, NPM and YARN 2 | pnpm-lock.yaml 3 | package-lock.json 4 | yarn.lock 5 | 6 | src/components/ui 7 | 8 | # Prettier breaks {/* */} comments in MDX files :/ 9 | **/*.mdx 10 | -------------------------------------------------------------------------------- /docs/.prettierrc.mjs: -------------------------------------------------------------------------------- 1 | // .prettierrc.mjs 2 | /** @type {import("prettier").Config} */ 3 | export default { 4 | plugins: ["prettier-plugin-astro", "prettier-plugin-tailwindcss"], 5 | overrides: [ 6 | { 7 | files: "*.astro", 8 | options: { 9 | parser: "astro", 10 | }, 11 | }, 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /docs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:mainline-alpine AS runner 2 | 3 | COPY ./nginx.conf /etc/nginx/conf.d/default.conf 4 | COPY ./dist /usr/share/nginx/html 5 | 6 | EXPOSE 80 7 | 8 | HEALTHCHECK CMD curl --fail http://localhost:80 || exit 1 9 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # TrailBase Website & Documentation 2 | 3 | This directory contains the https://trailbase.io site. 4 | -------------------------------------------------------------------------------- /docs/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | trailbase-docs: 3 | container_name: trailbase-docs 4 | build: . 5 | ports: 6 | - "127.0.0.1:3036:80/tcp" 7 | restart: unless-stopped 8 | 9 | # By default containers get 1024 cpu shares. Setting it to 512 means half 10 | # the resources compared to a default container. And 2048 double, 11 | # respectively. 12 | cpu_shares: 1024 13 | mem_limit: 128m 14 | oom_score_adj: -200 15 | -------------------------------------------------------------------------------- /docs/examples/record_api_curl/create.sh: -------------------------------------------------------------------------------- 1 | curl \ 2 | --header "Content-Type: application/json" \ 3 | --header "Authorization: Bearer ${AUTH_TOKEN}" \ 4 | --request POST \ 5 | --data '{"text_not_null": "test"}' \ 6 | http://localhost:4000/api/records/v1/simple_strict_table 7 | -------------------------------------------------------------------------------- /docs/examples/record_api_curl/delete.sh: -------------------------------------------------------------------------------- 1 | curl \ 2 | --header "Content-Type: application/json" \ 3 | --header "Authorization: Bearer ${AUTH_TOKEN}" \ 4 | --request DELETE \ 5 | http://localhost:4000/api/records/v1/simple_strict_table/${RECORD_ID} 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_curl/list.sh: -------------------------------------------------------------------------------- 1 | curl --globoff \ 2 | --header "Content-Type: application/json" \ 3 | --header "Authorization: Bearer ${AUTH_TOKEN}" \ 4 | --request GET \ 5 | 'http://localhost:4000/api/records/v1/movies?limit=3&order=rank&filter[watch_time][$lt]=120&filter[description][$like]=%love%' 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_curl/login.sh: -------------------------------------------------------------------------------- 1 | set -x 2 | 3 | curl \ 4 | --header "Content-Type: application/json" \ 5 | --request POST \ 6 | --data '{"email": "admin@localhost", "password": "secret"}' \ 7 | http://localhost:4000/api/auth/v1/login 8 | -------------------------------------------------------------------------------- /docs/examples/record_api_curl/read.sh: -------------------------------------------------------------------------------- 1 | curl \ 2 | --header "Content-Type: application/json" \ 3 | --header "Authorization: Bearer ${AUTH_TOKEN}" \ 4 | http://localhost:4000/api/records/v1/simple_strict_table/${RECORD_ID} 5 | -------------------------------------------------------------------------------- /docs/examples/record_api_curl/update.sh: -------------------------------------------------------------------------------- 1 | curl \ 2 | --header "Content-Type: application/json" \ 3 | --header "Authorization: Bearer ${AUTH_TOKEN}" \ 4 | --request PATCH \ 5 | --data '{"text_not_null": "updated"}' \ 6 | http://localhost:4000/api/records/v1/simple_strict_table/${RECORD_ID} 7 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | linter: 4 | rules: 5 | prefer_single_quotes: true 6 | unnecessary_brace_in_string_interps: false 7 | unawaited_futures: true 8 | sort_child_properties_last: false 9 | # analyzer: 10 | # exclude: 11 | # - path/to/excluded/files/** 12 | 13 | # For more information about the core and recommended set of lints, see 14 | # https://dart.dev/go/core-lints 15 | 16 | # For additional information about configuring this file, see 17 | # https://dart.dev/guides/language/analysis-options 18 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/lib/record_api.dart: -------------------------------------------------------------------------------- 1 | export 'src/create.dart'; 2 | export 'src/delete.dart'; 3 | export 'src/list.dart'; 4 | export 'src/read.dart'; 5 | export 'src/subscribe.dart'; 6 | export 'src/update.dart'; 7 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/lib/src/create.dart: -------------------------------------------------------------------------------- 1 | import 'package:trailbase/trailbase.dart'; 2 | 3 | Future create(Client client) async => await client 4 | .records('simple_strict_table') 5 | .create({'text_not_null': 'test'}); 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/lib/src/delete.dart: -------------------------------------------------------------------------------- 1 | import 'package:trailbase/trailbase.dart'; 2 | 3 | Future delete(Client client, RecordId id) async => 4 | await client.records('simple_strict_table').delete(id); 5 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/lib/src/list.dart: -------------------------------------------------------------------------------- 1 | import 'package:trailbase/trailbase.dart'; 2 | 3 | Future list(Client client) async => 4 | await client.records('movies').list( 5 | pagination: Pagination(limit: 3), 6 | order: ['rank'], 7 | filters: [ 8 | Filter( 9 | column: 'watch_time', 10 | op: CompareOp.lessThan, 11 | value: '120', 12 | ), 13 | Filter( 14 | column: 'description', 15 | op: CompareOp.like, 16 | value: '%love%', 17 | ), 18 | ], 19 | ); 20 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/lib/src/read.dart: -------------------------------------------------------------------------------- 1 | import 'package:trailbase/trailbase.dart'; 2 | 3 | Future> read(Client client, RecordId id) async => 4 | await client.records('simple_strict_table').read(id); 5 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/lib/src/subscribe.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:trailbase/trailbase.dart'; 4 | 5 | Future> subscribe(Client client, RecordId id) async => 6 | await client.records('simple_strict_table').subscribe(id); 7 | 8 | Future> subscribeAll(Client client) async => 9 | await client.records('simple_strict_table').subscribeAll(); 10 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/lib/src/update.dart: -------------------------------------------------------------------------------- 1 | import 'package:trailbase/trailbase.dart'; 2 | 3 | Future update(Client client, RecordId id) async => await client 4 | .records('simple_strict_table') 5 | .update(id, {'text_not_null': 'updated'}); 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_dart/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: record_api 2 | description: Example uses of record APIs for documentation purposes. 3 | version: 0.0.1 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ^3.6.1 8 | 9 | dependencies: 10 | trailbase: 11 | path: ../../../client/trailbase-dart 12 | 13 | dev_dependencies: 14 | lints: ^5.0.0 15 | test: ^1.24.0 16 | -------------------------------------------------------------------------------- /docs/examples/record_api_dotnet/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | -------------------------------------------------------------------------------- /docs/examples/record_api_dotnet/Create.cs: -------------------------------------------------------------------------------- 1 | using TrailBase; 2 | using System.Text.Json.Nodes; 3 | 4 | public partial class Examples { 5 | public static async Task Create(Client client) => 6 | await client.Records("simple_strict_table").Create( 7 | new JsonObject { ["text_not_null"] = "test" }); 8 | } 9 | -------------------------------------------------------------------------------- /docs/examples/record_api_dotnet/Delete.cs: -------------------------------------------------------------------------------- 1 | using TrailBase; 2 | 3 | public partial class Examples { 4 | public static async Task Delete(Client client, RecordId id) => 5 | await client.Records("simple_strict_table").Delete(id); 6 | } 7 | -------------------------------------------------------------------------------- /docs/examples/record_api_dotnet/List.cs: -------------------------------------------------------------------------------- 1 | using TrailBase; 2 | using System.Text.Json.Nodes; 3 | 4 | public partial class Examples { 5 | public static async Task> List(Client client) => 6 | await client.Records("movies").List( 7 | pagination: new Pagination(limit: 3), 8 | order: ["rank"], 9 | filters: [ 10 | new Filter(column:"watch_time", op:CompareOp.LessThan, value:"120"), 11 | new Filter(column:"description", op:CompareOp.Like, value:"%love%"), 12 | ]); 13 | } 14 | -------------------------------------------------------------------------------- /docs/examples/record_api_dotnet/Read.cs: -------------------------------------------------------------------------------- 1 | using TrailBase; 2 | using System.Text.Json.Nodes; 3 | 4 | public partial class Examples { 5 | public static async Task Read(Client client, RecordId id) => 6 | await client.Records("simple_strict_table").Read(id); 7 | } 8 | -------------------------------------------------------------------------------- /docs/examples/record_api_dotnet/Subscribe.cs: -------------------------------------------------------------------------------- 1 | using TrailBase; 2 | 3 | public partial class Examples { 4 | public static async Task> Subscribe(Client client, RecordId id) => 5 | await client.Records("simple_strict_table").Subscribe(id); 6 | 7 | public static async Task> SubscribeAll(Client client) => 8 | await client.Records("simple_strict_table").SubscribeAll(); 9 | } 10 | -------------------------------------------------------------------------------- /docs/examples/record_api_dotnet/Update.cs: -------------------------------------------------------------------------------- 1 | using TrailBase; 2 | using System.Text.Json.Nodes; 3 | 4 | public partial class Examples { 5 | public static async Task Update(Client client, RecordId id) => 6 | await client.Records("simple_strict_table").Update( 7 | id, new JsonObject { ["text_not_null"] = "updated" }); 8 | } 9 | -------------------------------------------------------------------------------- /docs/examples/record_api_dotnet/record_api_dotnet.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | all 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/examples/record_api_py/.gitignore: -------------------------------------------------------------------------------- 1 | **/__pycache__/ 2 | dist/ 3 | 4 | Makefile 5 | -------------------------------------------------------------------------------- /docs/examples/record_api_py/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "record-api-py" 3 | version = "0.1.0" 4 | description = "" 5 | authors = [ 6 | {name = "TrailBase", email = "contact@trailbase.io"} 7 | ] 8 | license = "OSL-3.0" 9 | requires-python = "^3.12" 10 | requires-poetry = "^2.0" 11 | 12 | [tool.poetry.dependencies] 13 | trailbase = { path = "../../../client/trailbase-py" } 14 | 15 | [tool.poetry.group.dev.dependencies] 16 | black = "^24.10.0" 17 | pyright = "^1.1.389" 18 | pytest = "^8.3.5" 19 | 20 | [build-system] 21 | requires = ["poetry-core>=2.0.0,<3.0.0"] 22 | build-backend = "poetry.core.masonry.api" 23 | 24 | [tool.black] 25 | line-length = 108 26 | 27 | [tool.pyright] 28 | venvPath = "." 29 | venv = ".venv" 30 | typeCheckingMode = "strict" 31 | useLibraryCodeForTypes = true 32 | verboseOutput = true 33 | reportMissingTypeStubs = "warning" 34 | extraPaths = ["../../../client/trailbase-py/"] 35 | -------------------------------------------------------------------------------- /docs/examples/record_api_py/record_api_py/__init__.py: -------------------------------------------------------------------------------- 1 | from .create import create as create 2 | from .delete import delete as delete 3 | from .list import list_movies as list_movies 4 | from .read import read as read 5 | from .update import update as update 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_py/record_api_py/create.py: -------------------------------------------------------------------------------- 1 | from trailbase import Client, RecordId 2 | 3 | 4 | def create(client: Client) -> RecordId: 5 | return client.records("simple_strict_table").create({"text_not_null": "test"}) 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_py/record_api_py/delete.py: -------------------------------------------------------------------------------- 1 | from trailbase import Client, RecordId 2 | 3 | 4 | def delete(client: Client, id: RecordId): 5 | client.records("simple_strict_table").delete(id) 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_py/record_api_py/list.py: -------------------------------------------------------------------------------- 1 | from trailbase import Client, Filter, CompareOp, JSON_OBJECT 2 | 3 | 4 | def list_movies(client: Client) -> list[JSON_OBJECT]: 5 | response = client.records("movies").list( 6 | limit=3, 7 | order=["rank"], 8 | filters=[ 9 | Filter(column="watch_time", value="120", op=CompareOp.LESS_THAN), 10 | Filter(column="description", value="%love%", op=CompareOp.LIKE), 11 | ], 12 | ) 13 | 14 | return response.records 15 | -------------------------------------------------------------------------------- /docs/examples/record_api_py/record_api_py/read.py: -------------------------------------------------------------------------------- 1 | from trailbase import Client, RecordId, JSON_OBJECT 2 | 3 | 4 | def read(client: Client, id: RecordId) -> JSON_OBJECT: 5 | return client.records("simple_strict_table").read(id) 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_py/record_api_py/update.py: -------------------------------------------------------------------------------- 1 | from trailbase import Client, RecordId 2 | 3 | 4 | def update(client: Client, id: RecordId): 5 | client.records("simple_strict_table").update( 6 | id, 7 | { 8 | "text_not_null": "updated", 9 | }, 10 | ) 11 | -------------------------------------------------------------------------------- /docs/examples/record_api_py/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/docs/examples/record_api_py/tests/__init__.py -------------------------------------------------------------------------------- /docs/examples/record_api_py/tests/test_record_api.py: -------------------------------------------------------------------------------- 1 | from trailbase import Client 2 | from record_api_py import create, delete, list_movies, read, update 3 | 4 | 5 | def test_record_api(): 6 | client = Client("http://localhost:4000") 7 | client.login("admin@localhost", "secret") 8 | 9 | id = create(client) 10 | json = read(client, id) 11 | 12 | assert json["text_not_null"] == "test" 13 | 14 | update(client, id) 15 | updated_json = read(client, id) 16 | 17 | assert updated_json["text_not_null"] == "updated" 18 | 19 | delete(client, id) 20 | 21 | movies = list_movies(client) 22 | assert len(movies) == 3 23 | -------------------------------------------------------------------------------- /docs/examples/record_api_rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "record_api_rs" 3 | version = "0.1.0" 4 | edition = "2024" 5 | publish = false 6 | 7 | [dependencies] 8 | anyhow = "1.0.95" 9 | futures = "0.3.31" 10 | serde_json = "1.0.137" 11 | tokio = { workspace = true } 12 | trailbase-client = { path = "../../../client/trailbase-rs/" } 13 | -------------------------------------------------------------------------------- /docs/examples/record_api_rs/src/create.rs: -------------------------------------------------------------------------------- 1 | use trailbase_client::Client; 2 | 3 | pub async fn create(client: &Client) -> anyhow::Result { 4 | Ok( 5 | client 6 | .records("simple_strict_table") 7 | .create(serde_json::json!({ 8 | "text_not_null": "test", 9 | })) 10 | .await?, 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /docs/examples/record_api_rs/src/delete.rs: -------------------------------------------------------------------------------- 1 | use trailbase_client::{Client, RecordId}; 2 | 3 | pub async fn delete(client: &Client, id: impl RecordId<'_>) -> anyhow::Result<()> { 4 | Ok(client.records("simple_strict_table").delete(id).await?) 5 | } 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_rs/src/list.rs: -------------------------------------------------------------------------------- 1 | use trailbase_client::{Client, CompareOp, Filter, ListArguments, ListResponse, Pagination}; 2 | 3 | pub async fn list(client: &Client) -> anyhow::Result> { 4 | Ok( 5 | client 6 | .records("movies") 7 | .list( 8 | ListArguments::new() 9 | .with_pagination(Pagination::new().with_limit(3)) 10 | .with_order(["rank"]) 11 | .with_filters([ 12 | Filter::new("watch_time", CompareOp::LessThan, "120"), 13 | Filter::new("description", CompareOp::Like, "%love%"), 14 | ]), 15 | ) 16 | .await?, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /docs/examples/record_api_rs/src/read.rs: -------------------------------------------------------------------------------- 1 | use trailbase_client::{Client, RecordId}; 2 | 3 | pub async fn read(client: &Client, id: impl RecordId<'_>) -> anyhow::Result { 4 | Ok(client.records("simple_strict_table").read(id).await?) 5 | } 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_rs/src/subscribe.rs: -------------------------------------------------------------------------------- 1 | use trailbase_client::{Client, DbEvent, RecordId, Stream}; 2 | 3 | pub async fn subscribe( 4 | client: &Client, 5 | id: impl RecordId<'_>, 6 | ) -> anyhow::Result> { 7 | Ok(client.records("simple_strict_table").subscribe(id).await?) 8 | } 9 | 10 | pub async fn subscribe_all(client: &Client) -> anyhow::Result> { 11 | Ok(client.records("simple_strict_table").subscribe("*").await?) 12 | } 13 | -------------------------------------------------------------------------------- /docs/examples/record_api_rs/src/update.rs: -------------------------------------------------------------------------------- 1 | use trailbase_client::{Client, RecordId}; 2 | 3 | pub async fn update(client: &Client, id: impl RecordId<'_>) -> anyhow::Result<()> { 4 | Ok( 5 | client 6 | .records("simple_strict_table") 7 | .update( 8 | id, 9 | serde_json::json!({ 10 | "text_not_null": "updated", 11 | }), 12 | ) 13 | .await?, 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /docs/examples/record_api_swift/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /docs/examples/record_api_swift/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 6.1 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "RecordApiDocs", 8 | products: [ 9 | .library( 10 | name: "RecordApiDocs", 11 | targets: ["RecordApiDocs"]) 12 | ], 13 | dependencies: [ 14 | .package(path: "../../../client/trailbase-swift") 15 | ], 16 | targets: [ 17 | .target( 18 | name: "RecordApiDocs", 19 | dependencies: [ 20 | .product(name: "TrailBase", package: "trailbase-swift") 21 | ] 22 | ), 23 | .testTarget( 24 | name: "RecordApiDocsTests", 25 | dependencies: ["RecordApiDocs"] 26 | ), 27 | ], 28 | ) 29 | -------------------------------------------------------------------------------- /docs/examples/record_api_swift/Sources/RecordApiDocs/Create.swift: -------------------------------------------------------------------------------- 1 | import TrailBase 2 | 3 | func create(client: Client) async throws -> RecordId { 4 | try await client.records("simple_strict_table").create( 5 | record: ["text_not_null": "test"]) 6 | } 7 | -------------------------------------------------------------------------------- /docs/examples/record_api_swift/Sources/RecordApiDocs/Delete.swift: -------------------------------------------------------------------------------- 1 | import TrailBase 2 | 3 | func delete(client: Client, id: RecordId) async throws { 4 | try await client.records("simple_strict_table").delete(recordId: id) 5 | } 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_swift/Sources/RecordApiDocs/List.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import TrailBase 3 | 4 | func list(client: Client) async throws -> ListResponse { 5 | try await client 6 | .records("movies") 7 | .list( 8 | pagination: Pagination(limit: 3), 9 | order: ["rank"], 10 | filters: [ 11 | .Filter(column: "watch_time", op: .LessThan, value: "120"), 12 | .Filter(column: "description", op: .Like, value: "%love%"), 13 | ] 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /docs/examples/record_api_swift/Sources/RecordApiDocs/Read.swift: -------------------------------------------------------------------------------- 1 | import TrailBase 2 | 3 | func read(client: Client, id: RecordId) async throws -> SimpleStrict { 4 | try await client.records("simple_strict_table").read(recordId: id) 5 | } 6 | -------------------------------------------------------------------------------- /docs/examples/record_api_swift/Sources/RecordApiDocs/RecordApiDocs.swift: -------------------------------------------------------------------------------- 1 | struct Movie: Codable, Equatable { 2 | var name: String 3 | } 4 | 5 | struct SimpleStrict: Codable, Equatable { 6 | var id: String? = nil 7 | 8 | var text_null: String? = nil 9 | var text_default: String? = nil 10 | let text_not_null: String 11 | } 12 | -------------------------------------------------------------------------------- /docs/examples/record_api_swift/Sources/RecordApiDocs/Update.swift: -------------------------------------------------------------------------------- 1 | import TrailBase 2 | 3 | func update(client: Client, id: RecordId) async throws { 4 | try await client.records("simple_strict_table").update( 5 | recordId: id, record: ["text_not_null": "updated"]) 6 | } 7 | -------------------------------------------------------------------------------- /docs/examples/record_api_ts/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import pluginJs from "@eslint/js"; 2 | import tseslint from "typescript-eslint"; 3 | 4 | export default [ 5 | pluginJs.configs.recommended, 6 | ...tseslint.configs.recommended, 7 | { 8 | ignores: ["dist/", "node_modules/", "types"], 9 | }, 10 | { 11 | files: ["scripts/*.{js,mjs,cjs,mts,ts,tsx,jsx}"], 12 | rules: { 13 | // https://typescript-eslint.io/rules/no-explicit-any/ 14 | "@typescript-eslint/no-explicit-any": "warn", 15 | // http://eslint.org/docs/rules/no-unused-vars 16 | "@typescript-eslint/no-unused-vars": [ 17 | "error", 18 | { 19 | vars: "all", 20 | args: "after-used", 21 | argsIgnorePattern: "^_", 22 | varsIgnorePattern: "^_", 23 | }, 24 | ], 25 | "no-empty": ["error", { allowEmptyCatch: true }], 26 | }, 27 | }, 28 | ]; 29 | -------------------------------------------------------------------------------- /docs/examples/record_api_ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "record_api_ts", 3 | "version": "1.0.0", 4 | "description": "Example uses of record APIs for documentation purposes.", 5 | "scripts": { 6 | "check": "tsc --noEmit --skipLibCheck && eslint", 7 | "manual-test": "vitest run # Not hermetic, don't run @CI" 8 | }, 9 | "devDependencies": { 10 | "@eslint/js": "^9.27.0", 11 | "@types/node": "^22.15.21", 12 | "eslint": "^9.27.0", 13 | "prettier": "^3.5.3", 14 | "typescript": "^5.8.3", 15 | "typescript-eslint": "^8.32.1", 16 | "vitest": "^3.1.4" 17 | }, 18 | "dependencies": { 19 | "trailbase": "workspace:*" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /docs/examples/record_api_ts/src/create.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "trailbase"; 2 | 3 | export const create = async (client: Client): Promise => 4 | await client.records("simple_strict_table").create({ text_not_null: "test" }); 5 | -------------------------------------------------------------------------------- /docs/examples/record_api_ts/src/delete.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "trailbase"; 2 | 3 | export const remove = async (client: Client, id: string | number) => 4 | await client.records("simple_strict_table").delete(id); 5 | -------------------------------------------------------------------------------- /docs/examples/record_api_ts/src/list.ts: -------------------------------------------------------------------------------- 1 | import { Client, type ListResponse } from "trailbase"; 2 | 3 | export const list = async (client: Client): Promise> => 4 | await client.records("movies").list({ 5 | pagination: { 6 | limit: 3, 7 | }, 8 | order: ["rank"], 9 | filters: [ 10 | { 11 | column: "watch_time", 12 | op: "lessThan", 13 | value: "120", 14 | }, 15 | { 16 | column: "description", 17 | op: "like", 18 | value: "%love%", 19 | }, 20 | ], 21 | }); 22 | -------------------------------------------------------------------------------- /docs/examples/record_api_ts/src/read.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "trailbase"; 2 | 3 | export const read = async (client: Client, id: string | number) => 4 | await client.records("simple_strict_table").read(id); 5 | -------------------------------------------------------------------------------- /docs/examples/record_api_ts/src/subscribe.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "trailbase"; 2 | 3 | export const subscribe = async (client: Client, id: string | number) => 4 | await client.records("simple_strict_table").subscribe(id); 5 | 6 | export const subscribeAll = async (client: Client) => 7 | await client.records("simple_strict_table").subscribe("*"); 8 | -------------------------------------------------------------------------------- /docs/examples/record_api_ts/src/update.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "trailbase"; 2 | 3 | export const update = async ( 4 | client: Client, 5 | id: string | number, 6 | record: object, 7 | ) => await client.records("simple_strict_table").update(id, record); 8 | -------------------------------------------------------------------------------- /docs/examples/record_api_ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "strictNullChecks": true, 5 | "forceConsistentCasingInFileNames": true, 6 | "esModuleInterop": false, 7 | "moduleResolution": "bundler", 8 | "target": "ESNext", 9 | "module": "ESNext", 10 | "noEmit": true, 11 | "paths": { 12 | "@/*": ["./src/*"], 13 | "@bindings/*": ["../../../trailbase-assets/js/bindings/*"] 14 | } 15 | }, 16 | "include": ["src/**/*"], 17 | "exclude": ["dist", "node_modules"] 18 | } 19 | -------------------------------------------------------------------------------- /docs/public/favicon.svg: -------------------------------------------------------------------------------- 1 | ../../assets/favicon.svg -------------------------------------------------------------------------------- /docs/src/assets/logo_512.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/docs/src/assets/logo_512.webp -------------------------------------------------------------------------------- /docs/src/assets/nut.svg: -------------------------------------------------------------------------------- 1 | ../../public/favicon.svg -------------------------------------------------------------------------------- /docs/src/assets/shelve.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/docs/src/assets/shelve.webp -------------------------------------------------------------------------------- /docs/src/components/SplitCard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Card } from "@astrojs/starlight/components"; 3 | import { type StarlightIcon } from "@astrojs/starlight/types"; 4 | 5 | export interface Props { 6 | title: string; 7 | icon?: StarlightIcon; 8 | reverse?: boolean; 9 | } 10 | 11 | const { title, icon, reverse } = Astro.props as Props; 12 | --- 13 | 14 | 15 |
24 |
25 | 26 |
27 | 28 |
29 | 30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /docs/src/content/config.ts: -------------------------------------------------------------------------------- 1 | import { defineCollection } from "astro:content"; 2 | import { docsSchema } from "@astrojs/starlight/schema"; 3 | 4 | export const collections = { 5 | docs: defineCollection({ schema: docsSchema() }), 6 | }; 7 | -------------------------------------------------------------------------------- /docs/src/content/docs/contact.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Contact 3 | template: splash 4 | --- 5 | 6 |
7 | Sebastian 8 | contact [at] trailbase.io 9 | 10 | 8047 Zurich, Switzerland 11 |
12 | -------------------------------------------------------------------------------- /docs/src/content/docs/documentation/APIs/_record_apis.ts: -------------------------------------------------------------------------------- 1 | type ApiOptions = { 2 | name: string; 3 | suffix?: string; 4 | prefix?: string; 5 | }; 6 | 7 | export const recordApiNamePlaceholder = ""; 8 | export const recordApiIdPlaceholder = ""; 9 | 10 | export function apiPath(opts: ApiOptions): string { 11 | const apiBase = "/api/records/v1"; 12 | const suffix = opts.suffix ? `/${opts.suffix}` : ""; 13 | return `${opts.prefix ?? ""}${apiBase}/${opts.name}${suffix}`; 14 | } 15 | -------------------------------------------------------------------------------- /docs/src/content/docs/getting-started/_getting_trailbase.md: -------------------------------------------------------------------------------- 1 | You can download the latest pre-built `trail` binary for Mac, Windows and Linux 2 | from [GitHub](https://github.com/trailbaseio/trailbase/releases/). 3 | 4 | Alternatively, you can use a Docker image from DockerHub: 5 | 6 | ```bash 7 | $ alias trail="docker run \ 8 | -p 4000:4000 \ 9 | --mount type=bind,source=$PWD/traildepot,target=/app/traildepot \ 10 | trailbase/trailbase /app/trail" 11 | $ mkdir traildepot # pre-create mount point for Docker 12 | $ trail run 13 | ``` 14 | 15 | or compile from [source](https://github.com/trailbaseio/trailbase). 16 | -------------------------------------------------------------------------------- /docs/src/content/docs/reference/roadmap.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Roadmap 3 | --- 4 | 5 | import Roadmap from "../_roadmap.md"; 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /docs/src/lib/darkmode.ts: -------------------------------------------------------------------------------- 1 | import { createSignal, onCleanup, onMount } from "solid-js"; 2 | import type { Accessor } from "solid-js"; 3 | 4 | export function createDarkMode(): Accessor { 5 | const isDark = () => document.documentElement.dataset["theme"] === "dark"; 6 | 7 | const [darkMode, setDarkMode] = createSignal(isDark()); 8 | 9 | let observer: MutationObserver | undefined; 10 | 11 | onMount(() => { 12 | observer = new MutationObserver((mutations) => { 13 | mutations.forEach((mu) => { 14 | if (mu.type === "attributes" && mu.attributeName === "data-theme") { 15 | setDarkMode(isDark()); 16 | } 17 | }); 18 | }); 19 | observer.observe(document.documentElement, { attributes: true }); 20 | }); 21 | onCleanup(() => observer?.disconnect()); 22 | 23 | return darkMode; 24 | } 25 | -------------------------------------------------------------------------------- /docs/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict", 3 | "compilerOptions": { 4 | "jsx": "preserve", 5 | "jsxImportSource": "solid-js", 6 | "baseUrl": "./", 7 | "paths": { 8 | "@/*": ["./src/*"], 9 | "@assets/*": ["../assets/*"], 10 | "@examples/*": ["./examples/*"], 11 | "@root/*": ["../*"] 12 | } 13 | }, 14 | "exclude": ["dist", "node_modules", "public"] 15 | } 16 | -------------------------------------------------------------------------------- /examples/blog/.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules/ 2 | **/dist/ 3 | 4 | Dockerfile* 5 | .docker* 6 | 7 | .git/ 8 | .git* 9 | 10 | *.image 11 | .env 12 | -------------------------------------------------------------------------------- /examples/blog/Caddyfile: -------------------------------------------------------------------------------- 1 | localhost 2 | encode gzip zstd 3 | reverse_proxy blog:4000 4 | -------------------------------------------------------------------------------- /examples/blog/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-slim AS builder 2 | 3 | RUN npm install -g pnpm 4 | RUN pnpm --version 5 | 6 | COPY web /app 7 | WORKDIR /app 8 | 9 | RUN pnpm install --no-frozen-lockfile 10 | RUN pnpm build 11 | 12 | 13 | FROM trailbase/trailbase:latest AS base 14 | 15 | WORKDIR /app 16 | 17 | COPY --from=builder /app/dist /app/public 18 | COPY --chown=trailbase traildepot /app/traildepot 19 | 20 | USER trailbase 21 | 22 | EXPOSE 4000 23 | ENTRYPOINT ["tini", "--"] 24 | CMD ["/app/trail", "--data-dir", "/app/traildepot", "run", "--address", "0.0.0.0:4000", "--public-dir", "/app/public"] 25 | 26 | HEALTHCHECK CMD curl --fail http://localhost:4000/api/healthcheck || exit 1 27 | -------------------------------------------------------------------------------- /examples/blog/caddy/config/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /examples/blog/caddy/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /examples/blog/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | blog: 4 | build: . 5 | restart: unless-stopped 6 | volumes: 7 | - ./traildepot:/app/traildepot 8 | 9 | caddy: 10 | image: caddy:2.8-alpine 11 | restart: unless-stopped 12 | cap_add: 13 | - NET_ADMIN 14 | ports: 15 | - "80:80" 16 | - "443:443" 17 | - "443:443/udp" 18 | volumes: 19 | - ./Caddyfile:/etc/caddy/Caddyfile 20 | - ./caddy/data:/data 21 | - ./caddy/config:/config 22 | -------------------------------------------------------------------------------- /examples/blog/flutter/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | analyzer: 13 | exclude: 14 | - lib/types/** 15 | 16 | linter: 17 | rules: 18 | prefer_single_quotes: true 19 | unnecessary_brace_in_string_interps: false 20 | unawaited_futures: true 21 | sort_child_properties_last: false 22 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/to/reference-keystore 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/main/kotlin/com/example/trailbase_blog/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.trailbase_blog 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/blog/flutter/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = "../build" 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(":app") 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip 6 | -------------------------------------------------------------------------------- /examples/blog/flutter/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.1.0" apply false 22 | id "org.jetbrains.kotlin.android" version "1.8.22" apply false 23 | } 24 | 25 | include ":app" 26 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. 6 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /examples/blog/flutter/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /examples/blog/flutter/linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /examples/blog/flutter/linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /examples/blog/flutter/linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /examples/blog/flutter/linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @main 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = trailbase_blog 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/blog/flutter/macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /examples/blog/flutter/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: trailbase_blog 2 | description: "TrailBase Example Blog Reader" 3 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 4 | version: 0.0.1+1 5 | 6 | environment: 7 | sdk: ^3.5.3 8 | 9 | dependencies: 10 | cupertino_icons: ^1.0.8 11 | flutter: 12 | sdk: flutter 13 | flutter_web_auth_2: ^4.0.0 14 | logging: ^1.2.0 15 | shared_preferences: ^2.3.2 16 | trailbase: 17 | path: ../../../client/trailbase-dart 18 | 19 | dev_dependencies: 20 | flutter_test: 21 | sdk: flutter 22 | 23 | flutter_lints: ^5.0.0 24 | 25 | flutter: 26 | uses-material-design: true 27 | -------------------------------------------------------------------------------- /examples/blog/flutter/web/auth.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Authentication complete 5 | 6 |

Authentication is complete. If this does not happen automatically, please close the window.

7 | 8 | 27 | -------------------------------------------------------------------------------- /examples/blog/flutter/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/web/favicon.png -------------------------------------------------------------------------------- /examples/blog/flutter/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/web/icons/Icon-192.png -------------------------------------------------------------------------------- /examples/blog/flutter/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/web/icons/Icon-512.png -------------------------------------------------------------------------------- /examples/blog/flutter/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /examples/blog/flutter/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /examples/blog/flutter/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /examples/blog/flutter/windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | void RegisterPlugins(flutter::PluginRegistry* registry) { 14 | DesktopWebviewWindowPluginRegisterWithRegistrar( 15 | registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); 16 | UrlLauncherWindowsRegisterWithRegistrar( 17 | registry->GetRegistrarForPlugin("UrlLauncherWindows")); 18 | WindowToFrontPluginRegisterWithRegistrar( 19 | registry->GetRegistrarForPlugin("WindowToFrontPlugin")); 20 | } 21 | -------------------------------------------------------------------------------- /examples/blog/flutter/windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /examples/blog/flutter/windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /examples/blog/flutter/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/flutter/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /examples/blog/flutter/windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/blog/flutter/windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /examples/blog/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trailbase-example-blog-typegen", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "types": "make --always-make types" 7 | }, 8 | "devDependencies": { 9 | "quicktype": "^23.0.170" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/blog/schema/new_profile.json: -------------------------------------------------------------------------------- 1 | { 2 | "$defs": {}, 3 | "properties": { 4 | "created": { 5 | "type": "integer" 6 | }, 7 | "updated": { 8 | "type": "integer" 9 | }, 10 | "user": { 11 | "type": "string" 12 | }, 13 | "username": { 14 | "type": "string" 15 | } 16 | }, 17 | "required": [ 18 | "user", 19 | "username" 20 | ], 21 | "title": "profiles", 22 | "type": "object" 23 | } 24 | -------------------------------------------------------------------------------- /examples/blog/schema/profile.json: -------------------------------------------------------------------------------- 1 | { 2 | "$defs": {}, 3 | "properties": { 4 | "avatar_url": { 5 | "type": "string" 6 | }, 7 | "created": { 8 | "type": "integer" 9 | }, 10 | "is_editor": { 11 | "type": "boolean" 12 | }, 13 | "updated": { 14 | "type": "integer" 15 | }, 16 | "user": { 17 | "type": "string" 18 | }, 19 | "username": { 20 | "type": "string" 21 | } 22 | }, 23 | "required": [ 24 | "user", 25 | "username", 26 | "created", 27 | "updated" 28 | ], 29 | "title": "profiles_view", 30 | "type": "object" 31 | } 32 | -------------------------------------------------------------------------------- /examples/blog/screenshots/screenshot_flutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/screenshots/screenshot_flutter.png -------------------------------------------------------------------------------- /examples/blog/screenshots/screenshot_web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/screenshots/screenshot_web.png -------------------------------------------------------------------------------- /examples/blog/traildepot/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | backups/ 3 | data/ 4 | secrets/ 5 | uploads/ 6 | 7 | !migrations/ 8 | 9 | trailbase.js 10 | trailbase.d.ts 11 | -------------------------------------------------------------------------------- /examples/blog/traildepot/migrations/U1725019362__create_articles.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE articles ( 2 | id BLOB PRIMARY KEY NOT NULL CHECK(is_uuid_v7(id)) DEFAULT (uuid_v7()), 3 | author BLOB NOT NULL REFERENCES _user(id) ON DELETE CASCADE, 4 | 5 | title TEXT NOT NULL, 6 | intro TEXT NOT NULL, 7 | tag TEXT NOT NULL, 8 | body TEXT NOT NULL, 9 | 10 | image TEXT CHECK(jsonschema('std.FileUpload', image, 'image/png, image/jpeg')), 11 | 12 | created INTEGER DEFAULT (UNIXEPOCH()) NOT NULL 13 | ) STRICT; 14 | 15 | -- Join articles with user profiles to get the username. 16 | CREATE VIEW articles_view AS SELECT a.*, p.username FROM articles AS a LEFT JOIN profiles AS p ON p.user = a.author; 17 | -------------------------------------------------------------------------------- /examples/blog/traildepot/migrations/U1725019363__create_editor_group.sql: -------------------------------------------------------------------------------- 1 | -- Create a group that is used to gate write access to articles. Members of 2 | -- this group can author articles. 3 | CREATE TABLE editors ( 4 | user BLOB NOT NULL, 5 | 6 | FOREIGN KEY(user) REFERENCES _user(id) ON DELETE CASCADE 7 | ) STRICT; 8 | 9 | -- Create an "is_editor" query api. 10 | CREATE VIRTUAL TABLE _is_editor USING define((SELECT EXISTS (SELECT * FROM editors WHERE user = $1) AS is_editor)); 11 | -------------------------------------------------------------------------------- /examples/blog/traildepot/migrations/U1725019371__add_admin_user.sql: -------------------------------------------------------------------------------- 1 | -- Create admin user with "secret" password. 2 | INSERT INTO _user 3 | (email, password_hash, verified, admin) 4 | VALUES 5 | ('admin@localhost', (hash_password('secret')), TRUE, TRUE); 6 | 7 | -- Set a username for the admin user. 8 | INSERT INTO profiles (user, username) 9 | SELECT user.id, 'Admin' 10 | FROM _user AS user WHERE email = 'admin@localhost'; 11 | -------------------------------------------------------------------------------- /examples/blog/traildepot/migrations/U1725019381__add_article.sql: -------------------------------------------------------------------------------- 1 | -- Bootstrap articles by inserting a dummy article for the admin user. 2 | INSERT INTO articles ( 3 | title, 4 | intro, 5 | tag, 6 | author, 7 | body, 8 | image 9 | ) 10 | SELECT 11 | 'TrailBase is Here 🎉', 12 | 'A rigorously simple and blazingly fast application base 😉', 13 | 'important,example', 14 | id, 15 | 'TrailBase provides core functionality such restful APIs, file upload, auth, access control and a convenient admin dashboard out of the box.', 16 | '{"id":"40e8d2a2-b025-435e-9aa0-4cb6b895ab2a","filename":"image.png","content_type":"image/png","mime_type":"image/png"}' 17 | FROM _user 18 | WHERE email = 'editor@localhost'; 19 | -------------------------------------------------------------------------------- /examples/blog/traildepot/uploads/0328bc95-9622-42e7-a609-625769a797c2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/traildepot/uploads/0328bc95-9622-42e7-a609-625769a797c2 -------------------------------------------------------------------------------- /examples/blog/traildepot/uploads/40e8d2a2-b025-435e-9aa0-4cb6b895ab2a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/traildepot/uploads/40e8d2a2-b025-435e-9aa0-4cb6b895ab2a -------------------------------------------------------------------------------- /examples/blog/web/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /examples/blog/web/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore files for PNPM, NPM and YARN 2 | pnpm-lock.yaml 3 | package-lock.json 4 | yarn.lock 5 | 6 | src/components/ui 7 | -------------------------------------------------------------------------------- /examples/blog/web/.prettierrc.mjs: -------------------------------------------------------------------------------- 1 | // .prettierrc.mjs 2 | /** @type {import("prettier").Config} */ 3 | export default { 4 | plugins: ['prettier-plugin-astro'], 5 | overrides: [ 6 | { 7 | files: '*.astro', 8 | options: { 9 | parser: 'astro', 10 | }, 11 | }, 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /examples/blog/web/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "astro/config"; 2 | 3 | import tailwind from "@astrojs/tailwind"; 4 | import icon from "astro-icon"; 5 | 6 | import solidJs from "@astrojs/solid-js"; 7 | 8 | // https://astro.build/config 9 | export default defineConfig({ 10 | integrations: [icon(), tailwind(), solidJs()], 11 | }); 12 | -------------------------------------------------------------------------------- /examples/blog/web/public/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/web/public/image.png -------------------------------------------------------------------------------- /examples/blog/web/src/assets/default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/blog/web/src/assets/default.jpg -------------------------------------------------------------------------------- /examples/blog/web/src/components/ArticleComposeButton.tsx: -------------------------------------------------------------------------------- 1 | import { Show } from "solid-js"; 2 | import { useStore } from "@nanostores/solid"; 3 | import { TbPencilPlus } from "solid-icons/tb"; 4 | 5 | import { $profile } from "@/lib/profile"; 6 | 7 | export function ArticleComposeButton() { 8 | const profile = useStore($profile); 9 | 10 | return ( 11 | }> 12 | 13 | 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/blog/web/src/components/PublishDate.tsx: -------------------------------------------------------------------------------- 1 | export function PublishDate(props: { date: number }) { 2 | return ( 3 | 4 | {new Date(props.date * 1000).toLocaleDateString()} 5 | 6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /examples/blog/web/src/components/Tag.tsx: -------------------------------------------------------------------------------- 1 | import { For } from "solid-js"; 2 | 3 | export function Tag(props: { tag: string }) { 4 | const style = 5 | "text-[16px] border-pacamara-secondary border-[1px] leading-none rounded-full flex items-center h-[34px] px-2 text-pacamara-secondary"; 6 | return ( 7 |
8 | t.trim())}> 9 | {(tag) => {tag}} 10 | 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /examples/blog/web/src/components/general/Footer.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 |
6 |
9 | 22 |
23 | -------------------------------------------------------------------------------- /examples/blog/web/src/components/general/Navigation.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const listStyle = 3 | "list-none text-[14px] font-normal flex flex-initial flex-col md:flex-row gap-5"; 4 | const itemStyle = 5 | "opacity-60 text-pacamara-primary hover:opacity-100 hover:text-pacamara-accent transition-all duration-300 dark:text-white dark:hover:text-pacamara-accent"; 6 | --- 7 | 8 | 15 | -------------------------------------------------------------------------------- /examples/blog/web/src/components/general/Tag.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { tag } = Astro.props; 3 | --- 4 | 5 | { 6 | tag && ( 7 | 8 | {tag} 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /examples/blog/web/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /examples/blog/web/src/pages/article.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Base from "@/layouts/Base.astro"; 3 | import { ArticlePage } from "@/components/ArticlePage"; 4 | --- 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/blog/web/src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Base from "@/layouts/Base.astro"; 3 | import { ArticleList } from "@/components/ArticleList"; 4 | --- 5 | 6 | 7 |
8 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /examples/blog/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict", 3 | "compilerOptions": { 4 | "strictNullChecks": true, 5 | "jsx": "preserve", 6 | "jsxImportSource": "solid-js", 7 | "baseUrl": "./", 8 | "paths": { 9 | "@/*": ["./src/*"], 10 | "@bindings/*": ["../../trailbase-core/bindings/*"], 11 | "@schema/*": ["./types/*"] 12 | } 13 | }, 14 | "exclude": [ 15 | "dist", 16 | "node_modules", 17 | "types", 18 | "public" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules/ 2 | **/dist/ 3 | 4 | Dockerfile* 5 | .docker* 6 | 7 | .git/ 8 | .git* 9 | 10 | *.image 11 | .env 12 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/Makefile: -------------------------------------------------------------------------------- 1 | build_n_data: build data_init 2 | 3 | build: dist 4 | rm -rf dist && pnpm build 5 | 6 | data_init: 7 | rm -rf traildepot/data && mkdir -p traildepot/data && cat import.sql | sqlite3 traildepot/data/main.db - 8 | 9 | run: 10 | cargo run -- run --public-dir dist 11 | 12 | .PHONY: init 13 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/README.md: -------------------------------------------------------------------------------- 1 | # Coffee Vector Search 2 | 3 | A small web application demonstrating the use of TrailBase and its vector 4 | search to build a coffee search. 5 | 6 | To import the coffee data from CSV, run: 7 | 8 | ```bash 9 | $ mkdir -p traildepot/data 10 | $ cat import.sql | sqlite3 traildepot/data/main.db - 11 | ``` 12 | 13 | To build the web app 14 | 15 | ```bash 16 | $ pnpm i 17 | $ pnpm build 18 | ``` 19 | 20 | Finally, to build the docker container: 21 | 22 | ``` 23 | $ docker build . -t coffee && docker run -p 4001:4000 coffee 24 | ``` 25 | 26 | ## Reference 27 | 28 | * Coffee data [source](https://github.com/jldbc/coffee-quality-database/blob/master/data/arabica_data_cleaned.csv) 29 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/assets/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/coffee-vector-search/assets/screenshot.png -------------------------------------------------------------------------------- /examples/coffee-vector-search/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | import tseslint from 'typescript-eslint' 6 | 7 | export default tseslint.config( 8 | { ignores: ['dist'] }, 9 | { 10 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 | files: ['**/*.{ts,tsx}'], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | globals: globals.browser, 15 | }, 16 | plugins: { 17 | 'react-hooks': reactHooks, 18 | 'react-refresh': reactRefresh, 19 | }, 20 | rules: { 21 | ...reactHooks.configs.recommended.rules, 22 | 'react-refresh/only-export-components': [ 23 | 'warn', 24 | { allowConstantExport: true }, 25 | ], 26 | }, 27 | }, 28 | ) 29 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/import.sql: -------------------------------------------------------------------------------- 1 | -- First create the strictly typed "coffee" table. 2 | CREATE TABLE coffee ( 3 | Species TEXT, 4 | Owner TEXT, 5 | 6 | Aroma REAL, 7 | Flavor REAL, 8 | Acidity REAL, 9 | Sweetness REAL, 10 | 11 | embedding BLOB 12 | ) STRICT; 13 | 14 | -- Then import the data into a "temporary" table. 15 | .mode csv 16 | .import arabica_data_cleaned.csv temporary 17 | 18 | -- Then import the un-typed temporary data into the typed "coffee" table. 19 | INSERT INTO coffee (Species, Owner, Aroma, Flavor, Acidity, Sweetness) 20 | SELECT 21 | Species, 22 | Owner, 23 | 24 | CAST(Aroma AS REAL) AS Aroma, 25 | CAST(Flavor AS REAL) AS Flavor, 26 | CAST(Acidity AS REAL) AS Acidity, 27 | CAST(Sweetness AS REAL) AS Sweetness 28 | FROM temporary; 29 | 30 | -- And clean up. 31 | DROP TABLE temporary; 32 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Coffee Search 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/screenshots/screenshot0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/coffee-vector-search/screenshots/screenshot0.png -------------------------------------------------------------------------------- /examples/coffee-vector-search/src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | transition: filter 300ms; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.react:hover { 18 | filter: drop-shadow(0 0 2em #61dafbaa); 19 | } 20 | 21 | @keyframes logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | 30 | @media (prefers-reduced-motion: no-preference) { 31 | a:nth-of-type(2) .logo { 32 | animation: logo-spin infinite 20s linear; 33 | } 34 | } 35 | 36 | .card { 37 | padding: 2em; 38 | } 39 | 40 | .read-the-docs { 41 | color: #888; 42 | } 43 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/src/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 | line-height: 1.5; 4 | font-weight: 400; 5 | color: #213547; 6 | } 7 | 8 | body { 9 | margin: 0; 10 | display: flex; 11 | min-width: 320px; 12 | min-height: 100vh; 13 | } 14 | 15 | h1 { 16 | font-size: 3.2em; 17 | line-height: 1.1; 18 | } 19 | 20 | .inputs { 21 | margin: 1em; 22 | display: grid; 23 | gap: 1rem 0px; 24 | grid-template-columns: repeat(2, minmax(0, 1fr)); 25 | } 26 | 27 | .table { 28 | display: flex; 29 | flex-direction: column; 30 | justify-content: center; 31 | } 32 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | import "./index.css"; 4 | import { App } from "./App.tsx"; 5 | 6 | createRoot(document.getElementById("root")!).render( 7 | 8 | 9 | , 10 | ); 11 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/traildepot/.gitignore: -------------------------------------------------------------------------------- 1 | backups/ 2 | data/ 3 | secrets/ 4 | uploads/ 5 | 6 | trailbase.d.ts 7 | trailbase.js 8 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/traildepot/migrations/U1732092075__crate_coffee_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS coffee ( 2 | Species TEXT NOT NULL, 3 | Owner TEXT NOT NULL, 4 | 5 | Aroma REAL NOT NULL, 6 | Flavor REAL NOT NULL, 7 | Acidity REAL NOT NULL, 8 | Sweetness REAL NOT NULL, 9 | 10 | embedding BLOB 11 | ) STRICT; 12 | 13 | UPDATE coffee SET embedding = vec_f32(FORMAT("[%f, %f, %f, %f]", Aroma, Flavor, Acidity, Sweetness)); 14 | 15 | CREATE TRIGGER _coffee__updated_trigger AFTER INSERT ON coffee FOR EACH ROW 16 | BEGIN 17 | UPDATE coffee SET embedding = vec_f32(FORMAT("[%f, %f, %f, %f]", Aroma, Flavor, Acidity, Sweetness)) WHERE _rowid_ = OLD._rowid_; 18 | END; 19 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 4 | "target": "ES2020", 5 | "useDefineForClassFields": true, 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "module": "ESNext", 8 | "skipLibCheck": true, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "Bundler", 12 | "allowImportingTsExtensions": true, 13 | "isolatedModules": true, 14 | "moduleDetection": "force", 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | 18 | /* Linting */ 19 | "strict": true, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "noUncheckedSideEffectImports": true 24 | }, 25 | "include": ["src"] 26 | } 27 | -------------------------------------------------------------------------------- /examples/coffee-vector-search/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vite.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/Makefile: -------------------------------------------------------------------------------- 1 | TRAILBIN ?= RUST_BACKTRACE=1 cargo run -- 2 | TRAILDEPOT := traildepot 3 | 4 | APPDIR := . 5 | DISTDIR := ${APPDIR}/dist 6 | ADDRESS := 127.0.0.1:4000 7 | 8 | run: ${DISTDIR}/server/entry-server.js 9 | ${TRAILBIN} --data-dir=${TRAILDEPOT} run --public-dir=${DISTDIR}/client --address=${ADDRESS} 10 | 11 | ${DISTDIR}/server/entry-server.js: $(shell find ${APPDIR}/src/ -type f) 12 | pnpm run build 13 | 14 | clean: 15 | rm -rf ${DISTDIR} ${TRAILDEPOT}/data 16 | 17 | .PHONY: run clean 18 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | TrailBase Clicker 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 |
16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/screenshots/screenshot0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailbaseio/trailbase/9f680d82ae2f8a5f9ed5714a81102671285faf20/examples/collab-clicker-ssr/screenshots/screenshot0.png -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/src/entry-client.tsx: -------------------------------------------------------------------------------- 1 | /* @refresh reload */ 2 | import './index.css' 3 | import { hydrate } from 'solid-js/web' 4 | import { App } from './App' 5 | 6 | hydrate( 7 | () => { 8 | const initialData = window.__INITIAL_DATA__; 9 | return ( 10 | 11 | ); 12 | }, 13 | document.getElementById('root') as HTMLElement, 14 | ); 15 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/src/entry-server.tsx: -------------------------------------------------------------------------------- 1 | import { renderToString, generateHydrationScript } from 'solid-js/web' 2 | import { App, type Clicked } from './App' 3 | 4 | export function render(_url: string, count: number) { 5 | const data = { count } satisfies Clicked; 6 | 7 | return { 8 | head: generateHydrationScript(), 9 | html: renderToString(() => ), 10 | data: ``, 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | h1 { 7 | @apply !text-5xl !font-bold; 8 | } 9 | h2 { 10 | @apply !text-3xl !font-bold; 11 | } 12 | h3 { 13 | @apply !text-2xl !font-bold; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | import { fontFamily } from "tailwindcss/defaultTheme"; 4 | 5 | // Colors from starlight. 6 | const accent = { 7 | 200: "#92d1fe", 8 | 600: "#0073aa", 9 | 900: "#003653", 10 | 950: "#00273d", 11 | }; 12 | 13 | const gray = { 14 | 100: "#f3f7f9", 15 | 200: "#e7eff2", 16 | 300: "#bac4c8", 17 | 400: "#7b8f96", 18 | 500: "#495c62", 19 | 700: "#2a3b41", 20 | 800: "#182a2f", 21 | 900: "#121a1c", 22 | }; 23 | 24 | export default { 25 | content: ["index.html", "./src/**/*.{html,js,jsx,md,mdx,ts,tsx}"], 26 | theme: { 27 | extend: { 28 | colors: { accent, gray }, 29 | fontFamily: { 30 | sans: ["Inter", ...fontFamily.sans], 31 | }, 32 | }, 33 | }, 34 | plugins: [], 35 | } satisfies Config; 36 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/traildepot/.gitignore: -------------------------------------------------------------------------------- 1 | backups/ 2 | data/ 3 | secrets/ 4 | uploads/ 5 | 6 | trailbase.d.ts 7 | trailbase.js 8 | 9 | # Is being built by Makefile. 10 | scripts/entry-server.js 11 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/traildepot/migrations/U1725019360__create_admin_user.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO _user 2 | (id, email, password_hash, verified, admin) 3 | VALUES 4 | (uuid_v7(), 'admin@localhost', (hash_password('secret')), TRUE, TRUE); 5 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/traildepot/migrations/U1737638313__create_table_counter.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS counter ( 2 | id INTEGER PRIMARY KEY, 3 | value INTEGER NOT NULL DEFAULT 0 4 | ) STRICT; 5 | 6 | INSERT INTO counter (id, value) VALUES (1, 5); 7 | -------------------------------------------------------------------------------- /examples/collab-clicker-ssr/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import solid from "vite-plugin-solid"; 3 | import eslint from "vite-plugin-eslint"; 4 | import tailwindcss from "tailwindcss"; 5 | 6 | // https://vite.dev/config/ 7 | export default defineConfig({ 8 | plugins: [ 9 | solid({ ssr: true }), 10 | // tailwindcss(), 11 | eslint(), 12 | ], 13 | ssr: { 14 | noExternal: true, 15 | }, 16 | css: { 17 | postcss: { 18 | plugins: [tailwindcss()], 19 | }, 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /examples/custom-binary/.gitignore: -------------------------------------------------------------------------------- 1 | traildepot/ 2 | -------------------------------------------------------------------------------- /examples/custom-binary/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "custom-binary" 3 | version = "0.1.0" 4 | edition = "2024" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "^0.8.1" 9 | env_logger = { workspace = true } 10 | tokio = { workspace = true } 11 | trailbase = { workspace = true } 12 | -------------------------------------------------------------------------------- /examples/data-cli-tutorial/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | -------------------------------------------------------------------------------- /examples/data-cli-tutorial/Makefile: -------------------------------------------------------------------------------- 1 | read: fill 2 | pnpm run read 3 | 4 | fill: 5 | pnpm run fill 6 | 7 | clean: 8 | rm -rf traildepot/data 9 | 10 | .PHONY: clean read fill 11 | -------------------------------------------------------------------------------- /examples/data-cli-tutorial/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples_tutorial_scripts", 3 | "version": "0.0.1", 4 | "description": "", 5 | "type": "module", 6 | "scripts": { 7 | "build": "tsc", 8 | "format": "prettier -w src", 9 | "read": "node --loader ts-node/esm src/index.js", 10 | "fill": "node --loader ts-node/esm src/fill.js", 11 | "check": "tsc --noEmit --skipLibCheck && eslint" 12 | }, 13 | "devDependencies": { 14 | "@eslint/js": "^9.27.0", 15 | "@types/node": "^22.15.21", 16 | "eslint": "^9.27.0", 17 | "prettier": "^3.5.3", 18 | "quicktype": "^23.2.5", 19 | "ts-node": "^10.9.2", 20 | "typescript": "^5.8.3", 21 | "typescript-eslint": "^8.32.1" 22 | }, 23 | "dependencies": { 24 | "csv-parse": "^5.6.0", 25 | "trailbase": "workspace:*" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/data-cli-tutorial/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "trailbase"; 2 | 3 | const client = new Client("http://localhost:4000"); 4 | await client.login("admin@localhost", "secret"); 5 | 6 | const movies = client.records("movies"); 7 | const m = await movies.list({ 8 | pagination: { 9 | limit: 3, 10 | }, 11 | order: ["rank"], 12 | filters: [ 13 | { 14 | column: "watch_time", 15 | op: "lessThan", 16 | value: "120", 17 | }, 18 | ], 19 | }); 20 | 21 | console.log(m.records); 22 | -------------------------------------------------------------------------------- /examples/data-cli-tutorial/traildepot/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | backups/ 3 | data/ 4 | secrets/ 5 | uploads/ 6 | 7 | !migrations/ 8 | 9 | trailbase.js 10 | trailbase.d.ts 11 | -------------------------------------------------------------------------------- /examples/data-cli-tutorial/traildepot/migrations/U1725019360__add_admin_user.sql: -------------------------------------------------------------------------------- 1 | -- Create admin user with "secret" password. 2 | INSERT INTO _user 3 | (email, password_hash, verified, admin) 4 | VALUES 5 | ('admin@localhost', (hash_password('secret')), TRUE, TRUE); 6 | -------------------------------------------------------------------------------- /examples/data-cli-tutorial/traildepot/migrations/U1728810800__create_table_movies.sql: -------------------------------------------------------------------------------- 1 | -- A table schema to hold the IMDB test dataset from: 2 | -- https://www.kaggle.com/datasets/inductiveanks/top-1000-imdb-movies-dataset/data 3 | -- 4 | -- The only TrailBase API requirements are: "STRICT" typing and a INTEGER (or 5 | -- UUIDv7) PRIMARY KEY column. 6 | CREATE TABLE IF NOT EXISTS movies ( 7 | rank INTEGER PRIMARY KEY, 8 | name TEXT NOT NULL, 9 | year ANY NOT NULL, 10 | watch_time INTEGER NOT NULL, 11 | rating REAL NOT NULL, 12 | metascore ANY, 13 | gross ANY, 14 | votes TEXT NOT NULL, 15 | description TEXT NOT NULL 16 | ) STRICT; 17 | -------------------------------------------------------------------------------- /examples/data-cli-tutorial/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "strictNullChecks": true, 5 | "forceConsistentCasingInFileNames": true, 6 | "esModuleInterop": false, 7 | "moduleResolution": "bundler", 8 | "target": "ESNext", 9 | "module": "ESNext", 10 | "noEmit": true, 11 | "paths": { 12 | "@/*": ["./src/*"], 13 | "@schema/*": ["./types/*"], 14 | "@bindings/*": ["../../trailbase-assets/js/bindings/*"] 15 | } 16 | }, 17 | "include": ["src/**/*"], 18 | "exclude": [ 19 | "dist", 20 | "node_modules" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'docs' 3 | - 'docs/examples/record_api_ts' 4 | - 'examples/blog/web' 5 | - 'examples/coffee-vector-search' 6 | - 'examples/collab-clicker-ssr' 7 | - 'examples/data-cli-tutorial' 8 | - 'trailbase-assets/js/admin' 9 | - 'trailbase-assets/js/auth' 10 | - 'trailbase-assets/js/client' 11 | - 'trailbase-js/assets/runtime' 12 | options: 13 | link-workspace-packages: true 14 | prefer-workspace-packages: true 15 | strict-peer-dependencies: true 16 | # shared-workspace-lockfile: false 17 | -------------------------------------------------------------------------------- /trailbase-assets/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trailbase-assets" 3 | version = "0.1.0" 4 | edition = "2024" 5 | license = "OSL-3.0" 6 | description = "Assets for the TrailBase framework" 7 | homepage = "https://trailbase.io" 8 | repository = "https://github.com/trailbaseio/trailbase" 9 | readme = "../README.md" 10 | exclude = [ 11 | "**/node_modules/", 12 | "**/dist/", 13 | ] 14 | 15 | [dependencies] 16 | askama = { workspace = true } 17 | axum = { workspace = true } 18 | log = "0.4.27" 19 | rust-embed = { workspace = true } 20 | tower-service = { version = "0.3.3", default-features = false } 21 | 22 | [build-dependencies] 23 | trailbase-build = { workspace = true } 24 | -------------------------------------------------------------------------------- /trailbase-assets/askama.toml: -------------------------------------------------------------------------------- 1 | [general] 2 | dirs = ["js/auth/dist"] 3 | whitespace = "preserve" 4 | -------------------------------------------------------------------------------- /trailbase-assets/js/admin/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | 4 | vite.config.mts.timestamp* 5 | -------------------------------------------------------------------------------- /trailbase-assets/js/admin/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore files for PNPM, NPM and YARN 2 | pnpm-lock.yaml 3 | package-lock.json 4 | yarn.lock 5 | 6 | src/components/ui 7 | node_modules/ 8 | proto/ 9 | -------------------------------------------------------------------------------- /trailbase-assets/js/admin/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier-plugin-tailwindcss"] 3 | } 4 | -------------------------------------------------------------------------------- /trailbase-assets/js/admin/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /trailbase-assets/js/admin/src/assets/favicon.svg: -------------------------------------------------------------------------------- 1 | ../../../../../assets/favicon.svg -------------------------------------------------------------------------------- /trailbase-assets/js/admin/src/assets/logo_104.webp: -------------------------------------------------------------------------------- 1 | ../../../../../assets/logo_104.webp -------------------------------------------------------------------------------- /trailbase-assets/js/admin/src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | import type { Component, ComponentProps } from "solid-js" 2 | import { splitProps } from "solid-js" 3 | 4 | import { cn } from "@/lib/utils" 5 | 6 | const Label: Component> = (props) => { 7 | const [local, others] = splitProps(props, ["class"]) 8 | return ( 9 |