From bdb373584009836b854861c96df617dd13655d09 Mon Sep 17 00:00:00 2001 From: Sebastian Jeltsch Date: Wed, 30 Oct 2024 23:38:29 +0100 Subject: [PATCH] Squash all commits for a fresh start. This is only to avoid accidentally leaking any secrets from early development especially in the light of short-sha attacks. --- .dockerignore | 20 + .github/workflows/test.yml | 39 + .gitignore | 13 + .gitmodules | 9 + .pre-commit-config.yaml | 103 + .rustfmt.toml | 8 + Cargo.lock | 4658 +++++ Cargo.toml | 46 + Dockerfile | 51 + LICENSE | 105 + Makefile | 20 + README.md | 40 + assets/colors.svg | 341 + assets/favicon.svg | 85 + assets/logo.svg | 191 + assets/logo_104.webp | Bin 0 -> 38344 bytes client/.gitignore | 2 + client/testfixture/Makefile | 4 + client/testfixture/config.textproto | 63 + .../U1725019360__create_admin_user.sql | 4 + .../migrations/U1725019361__add_users.sql | 16 + ...1727439999__create_simple_strict_table.sql | 69 + .../U1727956148__create_more_tables.sql | 31 + .../U1728458183__create_virtual_table.sql | 51 + client/trailbase-dart/.gitignore | 7 + client/trailbase-dart/.pubignore | 2 + client/trailbase-dart/CHANGELOG.md | 7 + client/trailbase-dart/LICENSE | 1 + client/trailbase-dart/README.md | 13 + client/trailbase-dart/analysis_options.yaml | 31 + client/trailbase-dart/lib/src/client.dart | 548 + client/trailbase-dart/lib/src/pkce.dart | 42 + client/trailbase-dart/lib/trailbase.dart | 4 + client/trailbase-dart/pubspec.yaml | 18 + .../trailbase-dart/test/trailbase_test.dart | 140 + client/trailbase-ts/.gitignore | 2 + client/trailbase-ts/eslint.config.mjs | 30 + client/trailbase-ts/package.json | 53 + client/trailbase-ts/src/index.ts | 531 + client/trailbase-ts/tests/base64.test.ts | 25 + client/trailbase-ts/tests/encoding.bench.ts | 28 + .../tests/integration/integration.test.ts | 182 + .../tests/integration_test_runner.ts | 72 + client/trailbase-ts/tsconfig.json | 14 + client/trailbase-ts/vitest.config.ts | 14 + docker-compose.yml | 14 + docs/.dockerignore | 4 + docs/.gitignore | 21 + docs/.prettierignore | 9 + docs/.prettierrc.mjs | 13 + docs/Dockerfile | 8 + docs/README.md | 55 + docs/astro.config.mjs | 68 + docs/docker-compose.yml | 16 + docs/nginx.conf | 32 + docs/package.json | 37 + docs/public/favicon.svg | 1 + docs/src/assets/flutter_logo.svg | 1 + docs/src/assets/logo_512.webp | Bin 0 -> 38344 bytes docs/src/assets/screenshot.webp | Bin 0 -> 108746 bytes docs/src/assets/ts_logo.svg | 1 + docs/src/components/BarChart.tsx | 168 + docs/src/components/LineChart.tsx | 85 + docs/src/content/config.ts | 6 + docs/src/content/docs/_roadmap.md | 21 + .../content/docs/comparison/pocketbase.mdx | 96 + docs/src/content/docs/comparison/supabase.mdx | 44 + docs/src/content/docs/contact.mdx | 11 + .../docs/documentation/APIs/query_apis.mdx | 56 + .../docs/documentation/APIs/record_apis.mdx | 299 + docs/src/content/docs/documentation/_auth.svg | 291 + docs/src/content/docs/documentation/auth.mdx | 122 + .../content/docs/documentation/extending.mdx | 121 + .../content/docs/documentation/production.mdx | 85 + .../docs/documentation/type_safety.mdx | 82 + .../docs/getting-started/first-app.mdx | 197 + .../docs/getting-started/philosophy.mdx | 87 + .../docs/getting-started/starting-up.mdx | 72 + docs/src/content/docs/index.mdx | 167 + docs/src/content/docs/license.mdx | 108 + .../docs/reference/_benchmarks/benchmarks.tsx | 378 + .../_benchmarks/pocketbase_utilization.ts | 507 + .../_benchmarks/supabase_utilization.ts | 15343 ++++++++++++++++ .../_benchmarks/trailbase_utilization.ts | 143 + docs/src/content/docs/reference/_sql.mdx | 74 + .../src/content/docs/reference/benchmarks.mdx | 207 + docs/src/content/docs/reference/faq.mdx | 107 + docs/src/content/docs/reference/roadmap.mdx | 7 + docs/src/env.d.ts | 2 + docs/src/lib/darkmode.ts | 24 + docs/src/tailwind.css | 38 + docs/tailwind.config.mjs | 33 + docs/tsconfig.json | 18 + examples/blog/Caddyfile | 5 + examples/blog/Dockerfile | 39 + examples/blog/Makefile | 45 + examples/blog/README.md | 80 + examples/blog/caddy/config/.gitignore | 1 + examples/blog/caddy/data/.gitignore | 1 + examples/blog/docker-compose.yml | 33 + examples/blog/flutter/.gitignore | 45 + examples/blog/flutter/.metadata | 45 + examples/blog/flutter/analysis_options.yaml | 21 + examples/blog/flutter/android/.gitignore | 13 + .../blog/flutter/android/app/build.gradle | 44 + .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 45 + .../example/trailbase_blog/MainActivity.kt | 5 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + examples/blog/flutter/android/build.gradle | 18 + .../blog/flutter/android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 5 + examples/blog/flutter/android/settings.gradle | 25 + examples/blog/flutter/ios/.gitignore | 34 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../blog/flutter/ios/Flutter/Debug.xcconfig | 1 + .../blog/flutter/ios/Flutter/Release.xcconfig | 1 + .../ios/Runner.xcodeproj/project.pbxproj | 616 + .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 98 + .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../blog/flutter/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 + .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1418 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + examples/blog/flutter/ios/Runner/Info.plist | 49 + .../ios/Runner/Runner-Bridging-Header.h | 1 + .../flutter/ios/RunnerTests/RunnerTests.swift | 12 + examples/blog/flutter/lib/main.dart | 237 + examples/blog/flutter/lib/src/login.dart | 174 + examples/blog/flutter/lib/types/article.dart | 91 + .../blog/flutter/lib/types/new_profile.dart | 38 + examples/blog/flutter/lib/types/profile.dart | 45 + examples/blog/flutter/linux/.gitignore | 1 + examples/blog/flutter/linux/CMakeLists.txt | 145 + .../blog/flutter/linux/flutter/CMakeLists.txt | 88 + .../flutter/generated_plugin_registrant.cc | 23 + .../flutter/generated_plugin_registrant.h | 15 + .../linux/flutter/generated_plugins.cmake | 26 + examples/blog/flutter/linux/main.cc | 6 + examples/blog/flutter/linux/my_application.cc | 124 + examples/blog/flutter/linux/my_application.h | 18 + examples/blog/flutter/macos/.gitignore | 7 + .../macos/Flutter/Flutter-Debug.xcconfig | 1 + .../macos/Flutter/Flutter-Release.xcconfig | 1 + .../Flutter/GeneratedPluginRegistrant.swift | 22 + .../macos/Runner.xcodeproj/project.pbxproj | 705 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 98 + .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../flutter/macos/Runner/AppDelegate.swift | 9 + .../AppIcon.appiconset/Contents.json | 68 + .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 102994 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 5680 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 520 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 14142 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1066 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 36406 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 2218 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 343 + .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + examples/blog/flutter/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 15 + .../flutter/macos/Runner/Release.entitlements | 8 + .../macos/RunnerTests/RunnerTests.swift | 12 + examples/blog/flutter/pubspec.lock | 529 + examples/blog/flutter/pubspec.yaml | 26 + examples/blog/flutter/web/auth.html | 26 + examples/blog/flutter/web/favicon.png | Bin 0 -> 917 bytes examples/blog/flutter/web/icons/Icon-192.png | Bin 0 -> 5292 bytes examples/blog/flutter/web/icons/Icon-512.png | Bin 0 -> 8252 bytes .../flutter/web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes .../flutter/web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes examples/blog/flutter/web/index.html | 38 + examples/blog/flutter/web/manifest.json | 35 + examples/blog/flutter/windows/.gitignore | 17 + examples/blog/flutter/windows/CMakeLists.txt | 108 + .../flutter/windows/flutter/CMakeLists.txt | 109 + .../flutter/generated_plugin_registrant.cc | 20 + .../flutter/generated_plugin_registrant.h | 15 + .../windows/flutter/generated_plugins.cmake | 26 + .../flutter/windows/runner/CMakeLists.txt | 40 + .../blog/flutter/windows/runner/Runner.rc | 121 + .../flutter/windows/runner/flutter_window.cpp | 71 + .../flutter/windows/runner/flutter_window.h | 33 + examples/blog/flutter/windows/runner/main.cpp | 43 + .../blog/flutter/windows/runner/resource.h | 16 + .../windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes .../windows/runner/runner.exe.manifest | 14 + .../blog/flutter/windows/runner/utils.cpp | 65 + examples/blog/flutter/windows/runner/utils.h | 19 + .../flutter/windows/runner/win32_window.cpp | 288 + .../flutter/windows/runner/win32_window.h | 102 + examples/blog/package.json | 11 + examples/blog/schema/article.json | 80 + examples/blog/schema/new_profile.json | 23 + examples/blog/schema/profile.json | 31 + examples/blog/traildepot/.gitignore | 7 + examples/blog/traildepot/config.textproto | 60 + .../U1725019361__create_profiles.sql | 37 + .../U1725019362__create_articles.sql | 16 + .../U1725019363__create_editor_group.sql | 10 + .../U1725019371__add_admin_user.sql | 10 + .../migrations/U1725019372__add_users.sql | 20 + .../migrations/U1725019381__add_article.sql | 18 + .../0328bc95-9622-42e7-a609-625769a797c2 | Bin 0 -> 28861 bytes .../40e8d2a2-b025-435e-9aa0-4cb6b895ab2a | Bin 0 -> 23528 bytes examples/blog/web/.gitignore | 21 + examples/blog/web/.prettierignore | 6 + examples/blog/web/.prettierrc.mjs | 13 + examples/blog/web/astro.config.mjs | 12 + examples/blog/web/package.json | 38 + examples/blog/web/public/default.svg | 84 + examples/blog/web/public/image.png | Bin 0 -> 23528 bytes examples/blog/web/public/image.svg | 600 + examples/blog/web/src/assets/default.jpg | Bin 0 -> 664742 bytes examples/blog/web/src/components/Articles.tsx | 229 + examples/blog/web/src/components/Auth.tsx | 64 + .../web/src/components/general/Footer.astro | 22 + .../components/general/HamburgerButton.astro | 32 + .../web/src/components/general/Header.astro | 37 + .../src/components/general/ModeSwitch.astro | 29 + .../src/components/general/Navigation.astro | 14 + .../blog/web/src/components/general/Tag.astro | 11 + examples/blog/web/src/css/style.css | 106 + examples/blog/web/src/env.d.ts | 2 + examples/blog/web/src/layouts/Base.astro | 58 + examples/blog/web/src/lib/client.ts | 40 + examples/blog/web/src/lib/profile.ts | 51 + examples/blog/web/src/pages/article.astro | 8 + examples/blog/web/src/pages/compose.astro | 50 + examples/blog/web/src/pages/index.astro | 10 + examples/blog/web/tailwind.config.mjs | 33 + examples/blog/web/tsconfig.json | 20 + examples/blog/web/types/article.ts | 221 + examples/blog/web/types/new_profile.ts | 189 + examples/blog/web/types/profile.ts | 193 + examples/custom-binary/Cargo.toml | 11 + examples/custom-binary/src/main.rs | 63 + examples/tutorial/Makefile | 4 + examples/tutorial/README.md | 152 + examples/tutorial/data/README.md | 35 + .../data/Top_1000_IMDb_movies_New_version.csv | 1001 + examples/tutorial/scripts/.gitignore | 2 + examples/tutorial/scripts/Makefile | 12 + examples/tutorial/scripts/eslint.config.mjs | 28 + examples/tutorial/scripts/package.json | 26 + examples/tutorial/scripts/schema/movie.json | 63 + examples/tutorial/scripts/src/fill.ts | 43 + examples/tutorial/scripts/src/index.ts | 15 + examples/tutorial/scripts/tsconfig.json | 16 + examples/tutorial/scripts/types/movie.ts | 199 + examples/tutorial/traildepot/config.textproto | 30 + .../U1725019360__add_admin_user.sql | 5 + .../U1728810800__create_table_movies.sql | 16 + pnpm-lock.yaml | 9579 ++++++++++ pnpm-workspace.yaml | 10 + proto/config.proto | 185 + proto/config_api.proto | 16 + proto/vault.proto | 7 + trailbase-cli/Cargo.toml | 27 + trailbase-cli/src/args.rs | 188 + trailbase-cli/src/bin/trail.rs | 294 + trailbase-cli/src/lib.rs | 11 + trailbase-core/Cargo.toml | 85 + trailbase-core/benches/benchmark.rs | 242 + trailbase-core/bindings/.gitignore | 1 + trailbase-core/bindings/AlterIndexRequest.ts | 4 + trailbase-core/bindings/AlterTableRequest.ts | 4 + .../bindings/AuthCodeToTokenRequest.ts | 3 + trailbase-core/bindings/ChangeEmailRequest.ts | 3 + .../bindings/ChangePasswordRequest.ts | 3 + trailbase-core/bindings/Column.ts | 5 + trailbase-core/bindings/ColumnDataType.ts | 3 + trailbase-core/bindings/ColumnOption.ts | 5 + trailbase-core/bindings/ColumnOrder.ts | 3 + .../ConfiguredOAuthProvidersResponse.ts | 3 + trailbase-core/bindings/CreateIndexRequest.ts | 4 + .../bindings/CreateIndexResponse.ts | 3 + trailbase-core/bindings/CreateTableRequest.ts | 4 + .../bindings/CreateTableResponse.ts | 3 + trailbase-core/bindings/CreateUserRequest.ts | 3 + trailbase-core/bindings/DeleteRowRequest.ts | 8 + trailbase-core/bindings/DeleteRowsRequest.ts | 12 + trailbase-core/bindings/DropIndexRequest.ts | 3 + trailbase-core/bindings/DropTableRequest.ts | 3 + trailbase-core/bindings/ForeignKey.ts | 4 + .../bindings/GeneratedExpressionMode.ts | 3 + trailbase-core/bindings/JsonSchema.ts | 3 + .../bindings/ListJsonSchemasResponse.ts | 4 + trailbase-core/bindings/ListLogsResponse.ts | 5 + trailbase-core/bindings/ListRowsResponse.ts | 4 + .../bindings/ListSchemasResponse.ts | 7 + trailbase-core/bindings/ListUsersResponse.ts | 4 + trailbase-core/bindings/LogJson.ts | 3 + trailbase-core/bindings/LoginRequest.ts | 3 + trailbase-core/bindings/LoginResponse.ts | 3 + .../bindings/LoginStatusResponse.ts | 3 + trailbase-core/bindings/LogoutRequest.ts | 3 + trailbase-core/bindings/Mode.ts | 3 + trailbase-core/bindings/OAuthProviderEntry.ts | 3 + .../bindings/OAuthProviderResponse.ts | 4 + trailbase-core/bindings/ParseRequest.ts | 4 + trailbase-core/bindings/ParseResponse.ts | 3 + trailbase-core/bindings/QueryRequest.ts | 3 + trailbase-core/bindings/QueryResponse.ts | 4 + trailbase-core/bindings/ReadFilesRequest.ts | 8 + trailbase-core/bindings/ReferentialAction.ts | 3 + trailbase-core/bindings/RefreshRequest.ts | 3 + trailbase-core/bindings/RefreshResponse.ts | 3 + trailbase-core/bindings/Stats.ts | 3 + trailbase-core/bindings/Table.ts | 6 + trailbase-core/bindings/TableIndex.ts | 4 + trailbase-core/bindings/TableTrigger.ts | 3 + trailbase-core/bindings/UniqueConstraint.ts | 8 + .../bindings/UpdateJsonSchemaRequest.ts | 3 + trailbase-core/bindings/UpdateRowRequest.ts | 10 + trailbase-core/bindings/UpdateUserRequest.ts | 3 + trailbase-core/bindings/UserJson.ts | 3 + trailbase-core/bindings/View.ts | 12 + trailbase-core/build.rs | 113 + .../migrations/logs/V1__initial.sql | 28 + .../migrations/main/V1__initial.sql | 84 + trailbase-core/src/admin/config/get_config.rs | 35 + trailbase-core/src/admin/config/mod.rs | 5 + .../src/admin/config/update_config.rs | 33 + trailbase-core/src/admin/error.rs | 73 + trailbase-core/src/admin/jwt.rs | 10 + trailbase-core/src/admin/list_logs.rs | 396 + trailbase-core/src/admin/mod.rs | 66 + trailbase-core/src/admin/oauth_providers.rs | 22 + trailbase-core/src/admin/parse.rs | 57 + trailbase-core/src/admin/query.rs | 82 + trailbase-core/src/admin/rows/delete_rows.rs | 239 + trailbase-core/src/admin/rows/insert_row.rs | 38 + trailbase-core/src/admin/rows/list_rows.rs | 189 + trailbase-core/src/admin/rows/mod.rs | 11 + trailbase-core/src/admin/rows/read_files.rs | 79 + trailbase-core/src/admin/rows/update_row.rs | 54 + trailbase-core/src/admin/schema/mod.rs | 97 + trailbase-core/src/admin/table/alter_index.rs | 58 + trailbase-core/src/admin/table/alter_table.rs | 223 + .../src/admin/table/create_index.rs | 58 + .../src/admin/table/create_table.rs | 66 + trailbase-core/src/admin/table/drop_index.rs | 43 + trailbase-core/src/admin/table/drop_table.rs | 54 + .../src/admin/table/get_table_schema.rs | 31 + trailbase-core/src/admin/table/list_tables.rs | 119 + trailbase-core/src/admin/table/mod.rs | 25 + trailbase-core/src/admin/user/create_user.rs | 111 + trailbase-core/src/admin/user/list_users.rs | 170 + trailbase-core/src/admin/user/mod.rs | 68 + trailbase-core/src/admin/user/update_user.rs | 69 + trailbase-core/src/app_state.rs | 427 + trailbase-core/src/assets.rs | 152 + trailbase-core/src/auth/api/avatar.rs | 292 + trailbase-core/src/auth/api/change_email.rs | 205 + .../src/auth/api/change_password.rs | 108 + trailbase-core/src/auth/api/delete.rs | 38 + trailbase-core/src/auth/api/login.rs | 296 + trailbase-core/src/auth/api/logout.rs | 81 + trailbase-core/src/auth/api/mod.rs | 13 + trailbase-core/src/auth/api/refresh.rs | 57 + trailbase-core/src/auth/api/register.rs | 117 + trailbase-core/src/auth/api/reset_password.rs | 193 + trailbase-core/src/auth/api/token.rs | 108 + trailbase-core/src/auth/api/verify_email.rs | 139 + trailbase-core/src/auth/auth_test.rs | 434 + trailbase-core/src/auth/error.rs | 127 + trailbase-core/src/auth/jwt.rs | 203 + trailbase-core/src/auth/mod.rs | 150 + trailbase-core/src/auth/oauth/callback.rs | 306 + .../src/auth/oauth/list_providers.rs | 24 + trailbase-core/src/auth/oauth/login.rs | 81 + trailbase-core/src/auth/oauth/mod.rs | 33 + trailbase-core/src/auth/oauth/oauth_test.rs | 195 + trailbase-core/src/auth/oauth/provider.rs | 100 + .../src/auth/oauth/providers/discord.rs | 130 + .../src/auth/oauth/providers/gitlab.rs | 117 + .../src/auth/oauth/providers/google.rs | 116 + .../src/auth/oauth/providers/mod.rs | 102 + .../src/auth/oauth/providers/test.rs | 95 + trailbase-core/src/auth/oauth/state.rs | 45 + trailbase-core/src/auth/password.rs | 51 + trailbase-core/src/auth/tokens.rs | 232 + trailbase-core/src/auth/ui/mod.rs | 261 + trailbase-core/src/auth/user.rs | 170 + trailbase-core/src/auth/util.rs | 223 + trailbase-core/src/config.rs | 727 + trailbase-core/src/constants.rs | 39 + trailbase-core/src/data_dir.rs | 97 + trailbase-core/src/email.rs | 401 + trailbase-core/src/extract/either.rs | 219 + trailbase-core/src/extract/mod.rs | 4 + trailbase-core/src/extract/multipart.rs | 165 + trailbase-core/src/lib.rs | 82 + trailbase-core/src/listing.rs | 376 + trailbase-core/src/logging.rs | 397 + trailbase-core/src/migrations.rs | 140 + trailbase-core/src/query/error.rs | 76 + trailbase-core/src/query/mod.rs | 192 + trailbase-core/src/query/query_api.rs | 156 + trailbase-core/src/records/create_record.rs | 286 + trailbase-core/src/records/delete_record.rs | 194 + trailbase-core/src/records/error.rs | 82 + trailbase-core/src/records/files.rs | 107 + trailbase-core/src/records/json_schema.rs | 40 + trailbase-core/src/records/json_to_sql.rs | 1083 ++ trailbase-core/src/records/list_records.rs | 275 + trailbase-core/src/records/mod.rs | 123 + trailbase-core/src/records/read_record.rs | 584 + trailbase-core/src/records/record_api.rs | 508 + trailbase-core/src/records/sql_to_json.rs | 224 + trailbase-core/src/records/test_utils.rs | 130 + trailbase-core/src/records/update_record.rs | 201 + trailbase-core/src/records/validate.rs | 96 + trailbase-core/src/scheduler.rs | 139 + trailbase-core/src/schema.rs | 1217 ++ trailbase-core/src/server/init.rs | 169 + trailbase-core/src/server/mod.rs | 399 + trailbase-core/src/table_metadata.rs | 1085 ++ trailbase-core/src/test.rs | 8 + trailbase-core/src/transaction.rs | 138 + trailbase-core/src/util.rs | 57 + trailbase-core/src/value_notifier.rs | 119 + trailbase-core/tests/integration_test.rs | 268 + trailbase-extension/Cargo.toml | 32 + trailbase-extension/src/jsonschema.rs | 356 + trailbase-extension/src/lib.rs | 187 + trailbase-extension/src/password.rs | 35 + trailbase-extension/src/uuid.rs | 154 + trailbase-extension/src/validators.rs | 208 + trailbase-sqlite/Cargo.toml | 20 + trailbase-sqlite/examples/uuid.rs | 27 + trailbase-sqlite/src/lib.rs | 135 + trailbase-sqlite/src/schema.rs | 278 + ui/admin/.gitignore | 4 + ui/admin/.prettierignore | 6 + ui/admin/.prettierrc.mjs | 13 + ui/admin/README.md | 17 + ui/admin/eslint.config.mjs | 30 + ui/admin/index.html | 22 + ui/admin/package.json | 67 + ui/admin/postcss.config.mjs | 8 + ui/admin/proto/config.ts | 1919 ++ ui/admin/proto/config_api.ts | 202 + ui/admin/proto/google/protobuf/descriptor.ts | 4752 +++++ ui/admin/proto/vault.ts | 203 + ui/admin/src/App.tsx | 62 + ui/admin/src/assets/favicon.svg | 1 + .../components/DestructiveActionButton.tsx | 56 + ui/admin/src/components/ErrorBoundary.tsx | 44 + ui/admin/src/components/FilterBar.tsx | 44 + ui/admin/src/components/FormFields.tsx | 454 + ui/admin/src/components/IndexPage.tsx | 113 + ui/admin/src/components/NavBar.tsx | 52 + ui/admin/src/components/SafeSheet.tsx | 103 + ui/admin/src/components/SplitView.tsx | 103 + ui/admin/src/components/Table.tsx | 435 + ui/admin/src/components/auth/AccountsPage.tsx | 17 + ui/admin/src/components/auth/AddUser.tsx | 109 + ui/admin/src/components/auth/AuthButton.tsx | 74 + ui/admin/src/components/auth/LoginPage.tsx | 76 + ui/admin/src/components/auth/UserTable.tsx | 363 + ui/admin/src/components/editor/EditorPage.tsx | 443 + ui/admin/src/components/logs/LogsPage.tsx | 337 + .../src/components/settings/AuthSettings.tsx | 475 + .../src/components/settings/EmailSettings.tsx | 255 + .../components/settings/SchemaSettings.tsx | 152 + .../src/components/settings/SettingsPage.tsx | 463 + .../components/tables/CreateAlterIndex.tsx | 253 + .../components/tables/CreateAlterTable.tsx | 876 + .../src/components/tables/InsertAlterRow.tsx | 221 + .../components/tables/RecordApiSettings.tsx | 545 + ui/admin/src/components/tables/TablesPage.tsx | 1326 ++ ui/admin/src/components/ui/accordion.tsx | 82 + ui/admin/src/components/ui/badge.tsx | 48 + ui/admin/src/components/ui/button.tsx | 52 + ui/admin/src/components/ui/card.tsx | 43 + ui/admin/src/components/ui/checkbox.tsx | 38 + ui/admin/src/components/ui/dialog.tsx | 141 + ui/admin/src/components/ui/hover-card.tsx | 37 + ui/admin/src/components/ui/label.tsx | 19 + ui/admin/src/components/ui/resizable.tsx | 60 + ui/admin/src/components/ui/select.tsx | 109 + ui/admin/src/components/ui/separator.tsx | 29 + ui/admin/src/components/ui/sheet.tsx | 168 + ui/admin/src/components/ui/switch.tsx | 77 + ui/admin/src/components/ui/table.tsx | 70 + ui/admin/src/components/ui/tabs.tsx | 87 + ui/admin/src/components/ui/text-field.tsx | 143 + ui/admin/src/components/ui/toast.tsx | 163 + ui/admin/src/components/ui/toggle.tsx | 49 + ui/admin/src/components/ui/tooltip.tsx | 34 + ui/admin/src/index.css | 141 + ui/admin/src/index.tsx | 19 + ui/admin/src/lib/bindings.ts | 55 + ui/admin/src/lib/config.ts | 64 + ui/admin/src/lib/fetch.ts | 40 + ui/admin/src/lib/name.ts | 33 + ui/admin/src/lib/parse.ts | 23 + ui/admin/src/lib/schema.ts | 260 + ui/admin/src/lib/table.ts | 87 + ui/admin/src/lib/user.ts | 35 + ui/admin/src/lib/utils.ts | 37 + ui/admin/tailwind.config.ts | 5 + ui/admin/tests/util.test.ts | 17 + ui/admin/tsconfig.json | 24 + ui/admin/ui.config.json | 13 + ui/admin/vite.config.mts | 18 + ui/auth/.gitignore | 24 + ui/auth/.prettierignore | 8 + ui/auth/.prettierrc.mjs | 13 + ui/auth/astro.config.mjs | 18 + ui/auth/package.json | 40 + ui/auth/src/components/AlertBox.astro | 58 + ui/auth/src/components/Card.astro | 7 + ui/auth/src/components/ErrorBoundary.tsx | 35 + ui/auth/src/components/Form.astro | 27 + ui/auth/src/components/ListOauthProviders.tsx | 53 + ui/auth/src/components/Profile.tsx | 286 + ui/auth/src/components/ui/button.tsx | 52 + ui/auth/src/components/ui/card.tsx | 43 + ui/auth/src/components/ui/dialog.tsx | 141 + ui/auth/src/components/ui/label.tsx | 19 + ui/auth/src/components/ui/text-field.tsx | 143 + ui/auth/src/components/ui/toast.tsx | 163 + ui/auth/src/env.d.ts | 2 + ui/auth/src/layouts/BaseLayout.astro | 87 + ui/auth/src/lib/constants.ts | 76 + ui/auth/src/lib/utils.ts | 7 + ui/auth/src/pages/change_email.astro | 53 + ui/auth/src/pages/change_password.astro | 60 + ui/auth/src/pages/login.astro | 85 + ui/auth/src/pages/profile.astro | 12 + ui/auth/src/pages/register.astro | 60 + .../src/pages/reset_password/request.astro | 42 + ui/auth/src/pages/reset_password/update.astro | 51 + ui/auth/tailwind.config.ts | 5 + ui/auth/tsconfig.json | 19 + ui/auth/ui.config.json | 11 + ui/auth/ui.preset.mjs | 104 + ui/common/css/global.css | 141 + ui/common/css/kobalte.css | 24 + ui/common/tailwind.config.mjs | 153 + ui/common/tsconfig.base.json | 11 + vendor/refinery | 1 + vendor/refinery-libsql/Cargo.toml | 16 + vendor/refinery-libsql/src/lib.rs | 87 + vendor/refinery-libsql/tests/libsql.rs | 625 + .../tests/migrations/V1-2/V1__initial.rs | 15 + .../V1-2/V2__add_cars_and_motos_table.sql | 8 + .../V3/V3__add_brand_to_cars_table.sql | 2 + .../migrations/V4__add_year_to_motos_table.rs | 13 + .../tests/migrations_broken/V1__initial.sql | 5 + .../migrations_broken/V2__add_cars_table.sql | 4 + .../V3__add_brand_to_cars_table.sql | 2 + .../migrations_missing/V2__add_cars_table.sql | 4 + .../U0__merge_out_of_order.sql | 5 + vendor/sqlean/Cargo.toml | 11 + vendor/sqlean/bindings.h | 3 + vendor/sqlean/build.rs | 78 + vendor/sqlean/bundled/sqlean | 1 + vendor/sqlean/src/lib.rs | 5 + vendor/sqlite-loadable | 1 + 603 files changed, 88250 insertions(+) create mode 100644 .dockerignore create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 .pre-commit-config.yaml create mode 100644 .rustfmt.toml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 assets/colors.svg create mode 100644 assets/favicon.svg create mode 100644 assets/logo.svg create mode 100644 assets/logo_104.webp create mode 100644 client/.gitignore create mode 100644 client/testfixture/Makefile create mode 100644 client/testfixture/config.textproto create mode 100644 client/testfixture/migrations/U1725019360__create_admin_user.sql create mode 100644 client/testfixture/migrations/U1725019361__add_users.sql create mode 100644 client/testfixture/migrations/U1727439999__create_simple_strict_table.sql create mode 100644 client/testfixture/migrations/U1727956148__create_more_tables.sql create mode 100644 client/testfixture/migrations/U1728458183__create_virtual_table.sql create mode 100644 client/trailbase-dart/.gitignore create mode 100644 client/trailbase-dart/.pubignore create mode 100644 client/trailbase-dart/CHANGELOG.md create mode 120000 client/trailbase-dart/LICENSE create mode 100644 client/trailbase-dart/README.md create mode 100644 client/trailbase-dart/analysis_options.yaml create mode 100644 client/trailbase-dart/lib/src/client.dart create mode 100644 client/trailbase-dart/lib/src/pkce.dart create mode 100644 client/trailbase-dart/lib/trailbase.dart create mode 100644 client/trailbase-dart/pubspec.yaml create mode 100644 client/trailbase-dart/test/trailbase_test.dart create mode 100644 client/trailbase-ts/.gitignore create mode 100644 client/trailbase-ts/eslint.config.mjs create mode 100644 client/trailbase-ts/package.json create mode 100644 client/trailbase-ts/src/index.ts create mode 100644 client/trailbase-ts/tests/base64.test.ts create mode 100644 client/trailbase-ts/tests/encoding.bench.ts create mode 100644 client/trailbase-ts/tests/integration/integration.test.ts create mode 100644 client/trailbase-ts/tests/integration_test_runner.ts create mode 100644 client/trailbase-ts/tsconfig.json create mode 100644 client/trailbase-ts/vitest.config.ts create mode 100644 docker-compose.yml create mode 100644 docs/.dockerignore create mode 100644 docs/.gitignore create mode 100644 docs/.prettierignore create mode 100644 docs/.prettierrc.mjs create mode 100644 docs/Dockerfile create mode 100644 docs/README.md create mode 100644 docs/astro.config.mjs create mode 100644 docs/docker-compose.yml create mode 100644 docs/nginx.conf create mode 100644 docs/package.json create mode 120000 docs/public/favicon.svg create mode 100644 docs/src/assets/flutter_logo.svg create mode 100644 docs/src/assets/logo_512.webp create mode 100644 docs/src/assets/screenshot.webp create mode 100644 docs/src/assets/ts_logo.svg create mode 100644 docs/src/components/BarChart.tsx create mode 100644 docs/src/components/LineChart.tsx create mode 100644 docs/src/content/config.ts create mode 100644 docs/src/content/docs/_roadmap.md create mode 100644 docs/src/content/docs/comparison/pocketbase.mdx create mode 100644 docs/src/content/docs/comparison/supabase.mdx create mode 100644 docs/src/content/docs/contact.mdx create mode 100644 docs/src/content/docs/documentation/APIs/query_apis.mdx create mode 100644 docs/src/content/docs/documentation/APIs/record_apis.mdx create mode 100644 docs/src/content/docs/documentation/_auth.svg create mode 100644 docs/src/content/docs/documentation/auth.mdx create mode 100644 docs/src/content/docs/documentation/extending.mdx create mode 100644 docs/src/content/docs/documentation/production.mdx create mode 100644 docs/src/content/docs/documentation/type_safety.mdx create mode 100644 docs/src/content/docs/getting-started/first-app.mdx create mode 100644 docs/src/content/docs/getting-started/philosophy.mdx create mode 100644 docs/src/content/docs/getting-started/starting-up.mdx create mode 100644 docs/src/content/docs/index.mdx create mode 100644 docs/src/content/docs/license.mdx create mode 100644 docs/src/content/docs/reference/_benchmarks/benchmarks.tsx create mode 100644 docs/src/content/docs/reference/_benchmarks/pocketbase_utilization.ts create mode 100644 docs/src/content/docs/reference/_benchmarks/supabase_utilization.ts create mode 100644 docs/src/content/docs/reference/_benchmarks/trailbase_utilization.ts create mode 100644 docs/src/content/docs/reference/_sql.mdx create mode 100644 docs/src/content/docs/reference/benchmarks.mdx create mode 100644 docs/src/content/docs/reference/faq.mdx create mode 100644 docs/src/content/docs/reference/roadmap.mdx create mode 100644 docs/src/env.d.ts create mode 100644 docs/src/lib/darkmode.ts create mode 100644 docs/src/tailwind.css create mode 100644 docs/tailwind.config.mjs create mode 100644 docs/tsconfig.json create mode 100644 examples/blog/Caddyfile create mode 100644 examples/blog/Dockerfile create mode 100644 examples/blog/Makefile create mode 100644 examples/blog/README.md create mode 100644 examples/blog/caddy/config/.gitignore create mode 100644 examples/blog/caddy/data/.gitignore create mode 100644 examples/blog/docker-compose.yml create mode 100644 examples/blog/flutter/.gitignore create mode 100644 examples/blog/flutter/.metadata create mode 100644 examples/blog/flutter/analysis_options.yaml create mode 100644 examples/blog/flutter/android/.gitignore create mode 100644 examples/blog/flutter/android/app/build.gradle create mode 100644 examples/blog/flutter/android/app/src/debug/AndroidManifest.xml create mode 100644 examples/blog/flutter/android/app/src/main/AndroidManifest.xml create mode 100644 examples/blog/flutter/android/app/src/main/kotlin/com/example/trailbase_blog/MainActivity.kt create mode 100644 examples/blog/flutter/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 examples/blog/flutter/android/app/src/main/res/drawable/launch_background.xml create mode 100644 examples/blog/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 examples/blog/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 examples/blog/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 examples/blog/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 examples/blog/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 examples/blog/flutter/android/app/src/main/res/values-night/styles.xml create mode 100644 examples/blog/flutter/android/app/src/main/res/values/styles.xml create mode 100644 examples/blog/flutter/android/app/src/profile/AndroidManifest.xml create mode 100644 examples/blog/flutter/android/build.gradle create mode 100644 examples/blog/flutter/android/gradle.properties create mode 100644 examples/blog/flutter/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 examples/blog/flutter/android/settings.gradle create mode 100644 examples/blog/flutter/ios/.gitignore create mode 100644 examples/blog/flutter/ios/Flutter/AppFrameworkInfo.plist create mode 100644 examples/blog/flutter/ios/Flutter/Debug.xcconfig create mode 100644 examples/blog/flutter/ios/Flutter/Release.xcconfig create mode 100644 examples/blog/flutter/ios/Runner.xcodeproj/project.pbxproj create mode 100644 examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 examples/blog/flutter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 examples/blog/flutter/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 examples/blog/flutter/ios/Runner/AppDelegate.swift create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 examples/blog/flutter/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 examples/blog/flutter/ios/Runner/Base.lproj/Main.storyboard create mode 100644 examples/blog/flutter/ios/Runner/Info.plist create mode 100644 examples/blog/flutter/ios/Runner/Runner-Bridging-Header.h create mode 100644 examples/blog/flutter/ios/RunnerTests/RunnerTests.swift create mode 100644 examples/blog/flutter/lib/main.dart create mode 100644 examples/blog/flutter/lib/src/login.dart create mode 100644 examples/blog/flutter/lib/types/article.dart create mode 100644 examples/blog/flutter/lib/types/new_profile.dart create mode 100644 examples/blog/flutter/lib/types/profile.dart create mode 100644 examples/blog/flutter/linux/.gitignore create mode 100644 examples/blog/flutter/linux/CMakeLists.txt create mode 100644 examples/blog/flutter/linux/flutter/CMakeLists.txt create mode 100644 examples/blog/flutter/linux/flutter/generated_plugin_registrant.cc create mode 100644 examples/blog/flutter/linux/flutter/generated_plugin_registrant.h create mode 100644 examples/blog/flutter/linux/flutter/generated_plugins.cmake create mode 100644 examples/blog/flutter/linux/main.cc create mode 100644 examples/blog/flutter/linux/my_application.cc create mode 100644 examples/blog/flutter/linux/my_application.h create mode 100644 examples/blog/flutter/macos/.gitignore create mode 100644 examples/blog/flutter/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 examples/blog/flutter/macos/Flutter/Flutter-Release.xcconfig create mode 100644 examples/blog/flutter/macos/Flutter/GeneratedPluginRegistrant.swift create mode 100644 examples/blog/flutter/macos/Runner.xcodeproj/project.pbxproj create mode 100644 examples/blog/flutter/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/blog/flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 examples/blog/flutter/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 examples/blog/flutter/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/blog/flutter/macos/Runner/AppDelegate.swift create mode 100644 examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 examples/blog/flutter/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 examples/blog/flutter/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 examples/blog/flutter/macos/Runner/Configs/Debug.xcconfig create mode 100644 examples/blog/flutter/macos/Runner/Configs/Release.xcconfig create mode 100644 examples/blog/flutter/macos/Runner/Configs/Warnings.xcconfig create mode 100644 examples/blog/flutter/macos/Runner/DebugProfile.entitlements create mode 100644 examples/blog/flutter/macos/Runner/Info.plist create mode 100644 examples/blog/flutter/macos/Runner/MainFlutterWindow.swift create mode 100644 examples/blog/flutter/macos/Runner/Release.entitlements create mode 100644 examples/blog/flutter/macos/RunnerTests/RunnerTests.swift create mode 100644 examples/blog/flutter/pubspec.lock create mode 100644 examples/blog/flutter/pubspec.yaml create mode 100644 examples/blog/flutter/web/auth.html create mode 100644 examples/blog/flutter/web/favicon.png create mode 100644 examples/blog/flutter/web/icons/Icon-192.png create mode 100644 examples/blog/flutter/web/icons/Icon-512.png create mode 100644 examples/blog/flutter/web/icons/Icon-maskable-192.png create mode 100644 examples/blog/flutter/web/icons/Icon-maskable-512.png create mode 100644 examples/blog/flutter/web/index.html create mode 100644 examples/blog/flutter/web/manifest.json create mode 100644 examples/blog/flutter/windows/.gitignore create mode 100644 examples/blog/flutter/windows/CMakeLists.txt create mode 100644 examples/blog/flutter/windows/flutter/CMakeLists.txt create mode 100644 examples/blog/flutter/windows/flutter/generated_plugin_registrant.cc create mode 100644 examples/blog/flutter/windows/flutter/generated_plugin_registrant.h create mode 100644 examples/blog/flutter/windows/flutter/generated_plugins.cmake create mode 100644 examples/blog/flutter/windows/runner/CMakeLists.txt create mode 100644 examples/blog/flutter/windows/runner/Runner.rc create mode 100644 examples/blog/flutter/windows/runner/flutter_window.cpp create mode 100644 examples/blog/flutter/windows/runner/flutter_window.h create mode 100644 examples/blog/flutter/windows/runner/main.cpp create mode 100644 examples/blog/flutter/windows/runner/resource.h create mode 100644 examples/blog/flutter/windows/runner/resources/app_icon.ico create mode 100644 examples/blog/flutter/windows/runner/runner.exe.manifest create mode 100644 examples/blog/flutter/windows/runner/utils.cpp create mode 100644 examples/blog/flutter/windows/runner/utils.h create mode 100644 examples/blog/flutter/windows/runner/win32_window.cpp create mode 100644 examples/blog/flutter/windows/runner/win32_window.h create mode 100644 examples/blog/package.json create mode 100644 examples/blog/schema/article.json create mode 100644 examples/blog/schema/new_profile.json create mode 100644 examples/blog/schema/profile.json create mode 100644 examples/blog/traildepot/.gitignore create mode 100644 examples/blog/traildepot/config.textproto create mode 100644 examples/blog/traildepot/migrations/U1725019361__create_profiles.sql create mode 100644 examples/blog/traildepot/migrations/U1725019362__create_articles.sql create mode 100644 examples/blog/traildepot/migrations/U1725019363__create_editor_group.sql create mode 100644 examples/blog/traildepot/migrations/U1725019371__add_admin_user.sql create mode 100644 examples/blog/traildepot/migrations/U1725019372__add_users.sql create mode 100644 examples/blog/traildepot/migrations/U1725019381__add_article.sql create mode 100644 examples/blog/traildepot/uploads/0328bc95-9622-42e7-a609-625769a797c2 create mode 100644 examples/blog/traildepot/uploads/40e8d2a2-b025-435e-9aa0-4cb6b895ab2a create mode 100644 examples/blog/web/.gitignore create mode 100644 examples/blog/web/.prettierignore create mode 100644 examples/blog/web/.prettierrc.mjs create mode 100644 examples/blog/web/astro.config.mjs create mode 100644 examples/blog/web/package.json create mode 100644 examples/blog/web/public/default.svg create mode 100644 examples/blog/web/public/image.png create mode 100644 examples/blog/web/public/image.svg create mode 100644 examples/blog/web/src/assets/default.jpg create mode 100644 examples/blog/web/src/components/Articles.tsx create mode 100644 examples/blog/web/src/components/Auth.tsx create mode 100644 examples/blog/web/src/components/general/Footer.astro create mode 100644 examples/blog/web/src/components/general/HamburgerButton.astro create mode 100644 examples/blog/web/src/components/general/Header.astro create mode 100644 examples/blog/web/src/components/general/ModeSwitch.astro create mode 100644 examples/blog/web/src/components/general/Navigation.astro create mode 100644 examples/blog/web/src/components/general/Tag.astro create mode 100644 examples/blog/web/src/css/style.css create mode 100644 examples/blog/web/src/env.d.ts create mode 100644 examples/blog/web/src/layouts/Base.astro create mode 100644 examples/blog/web/src/lib/client.ts create mode 100644 examples/blog/web/src/lib/profile.ts create mode 100644 examples/blog/web/src/pages/article.astro create mode 100644 examples/blog/web/src/pages/compose.astro create mode 100644 examples/blog/web/src/pages/index.astro create mode 100644 examples/blog/web/tailwind.config.mjs create mode 100644 examples/blog/web/tsconfig.json create mode 100644 examples/blog/web/types/article.ts create mode 100644 examples/blog/web/types/new_profile.ts create mode 100644 examples/blog/web/types/profile.ts create mode 100644 examples/custom-binary/Cargo.toml create mode 100644 examples/custom-binary/src/main.rs create mode 100644 examples/tutorial/Makefile create mode 100644 examples/tutorial/README.md create mode 100644 examples/tutorial/data/README.md create mode 100644 examples/tutorial/data/Top_1000_IMDb_movies_New_version.csv create mode 100644 examples/tutorial/scripts/.gitignore create mode 100644 examples/tutorial/scripts/Makefile create mode 100644 examples/tutorial/scripts/eslint.config.mjs create mode 100644 examples/tutorial/scripts/package.json create mode 100644 examples/tutorial/scripts/schema/movie.json create mode 100644 examples/tutorial/scripts/src/fill.ts create mode 100644 examples/tutorial/scripts/src/index.ts create mode 100644 examples/tutorial/scripts/tsconfig.json create mode 100644 examples/tutorial/scripts/types/movie.ts create mode 100644 examples/tutorial/traildepot/config.textproto create mode 100644 examples/tutorial/traildepot/migrations/U1725019360__add_admin_user.sql create mode 100644 examples/tutorial/traildepot/migrations/U1728810800__create_table_movies.sql create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 proto/config.proto create mode 100644 proto/config_api.proto create mode 100644 proto/vault.proto create mode 100644 trailbase-cli/Cargo.toml create mode 100644 trailbase-cli/src/args.rs create mode 100644 trailbase-cli/src/bin/trail.rs create mode 100644 trailbase-cli/src/lib.rs create mode 100644 trailbase-core/Cargo.toml create mode 100644 trailbase-core/benches/benchmark.rs create mode 100644 trailbase-core/bindings/.gitignore create mode 100644 trailbase-core/bindings/AlterIndexRequest.ts create mode 100644 trailbase-core/bindings/AlterTableRequest.ts create mode 100644 trailbase-core/bindings/AuthCodeToTokenRequest.ts create mode 100644 trailbase-core/bindings/ChangeEmailRequest.ts create mode 100644 trailbase-core/bindings/ChangePasswordRequest.ts create mode 100644 trailbase-core/bindings/Column.ts create mode 100644 trailbase-core/bindings/ColumnDataType.ts create mode 100644 trailbase-core/bindings/ColumnOption.ts create mode 100644 trailbase-core/bindings/ColumnOrder.ts create mode 100644 trailbase-core/bindings/ConfiguredOAuthProvidersResponse.ts create mode 100644 trailbase-core/bindings/CreateIndexRequest.ts create mode 100644 trailbase-core/bindings/CreateIndexResponse.ts create mode 100644 trailbase-core/bindings/CreateTableRequest.ts create mode 100644 trailbase-core/bindings/CreateTableResponse.ts create mode 100644 trailbase-core/bindings/CreateUserRequest.ts create mode 100644 trailbase-core/bindings/DeleteRowRequest.ts create mode 100644 trailbase-core/bindings/DeleteRowsRequest.ts create mode 100644 trailbase-core/bindings/DropIndexRequest.ts create mode 100644 trailbase-core/bindings/DropTableRequest.ts create mode 100644 trailbase-core/bindings/ForeignKey.ts create mode 100644 trailbase-core/bindings/GeneratedExpressionMode.ts create mode 100644 trailbase-core/bindings/JsonSchema.ts create mode 100644 trailbase-core/bindings/ListJsonSchemasResponse.ts create mode 100644 trailbase-core/bindings/ListLogsResponse.ts create mode 100644 trailbase-core/bindings/ListRowsResponse.ts create mode 100644 trailbase-core/bindings/ListSchemasResponse.ts create mode 100644 trailbase-core/bindings/ListUsersResponse.ts create mode 100644 trailbase-core/bindings/LogJson.ts create mode 100644 trailbase-core/bindings/LoginRequest.ts create mode 100644 trailbase-core/bindings/LoginResponse.ts create mode 100644 trailbase-core/bindings/LoginStatusResponse.ts create mode 100644 trailbase-core/bindings/LogoutRequest.ts create mode 100644 trailbase-core/bindings/Mode.ts create mode 100644 trailbase-core/bindings/OAuthProviderEntry.ts create mode 100644 trailbase-core/bindings/OAuthProviderResponse.ts create mode 100644 trailbase-core/bindings/ParseRequest.ts create mode 100644 trailbase-core/bindings/ParseResponse.ts create mode 100644 trailbase-core/bindings/QueryRequest.ts create mode 100644 trailbase-core/bindings/QueryResponse.ts create mode 100644 trailbase-core/bindings/ReadFilesRequest.ts create mode 100644 trailbase-core/bindings/ReferentialAction.ts create mode 100644 trailbase-core/bindings/RefreshRequest.ts create mode 100644 trailbase-core/bindings/RefreshResponse.ts create mode 100644 trailbase-core/bindings/Stats.ts create mode 100644 trailbase-core/bindings/Table.ts create mode 100644 trailbase-core/bindings/TableIndex.ts create mode 100644 trailbase-core/bindings/TableTrigger.ts create mode 100644 trailbase-core/bindings/UniqueConstraint.ts create mode 100644 trailbase-core/bindings/UpdateJsonSchemaRequest.ts create mode 100644 trailbase-core/bindings/UpdateRowRequest.ts create mode 100644 trailbase-core/bindings/UpdateUserRequest.ts create mode 100644 trailbase-core/bindings/UserJson.ts create mode 100644 trailbase-core/bindings/View.ts create mode 100644 trailbase-core/build.rs create mode 100644 trailbase-core/migrations/logs/V1__initial.sql create mode 100644 trailbase-core/migrations/main/V1__initial.sql create mode 100644 trailbase-core/src/admin/config/get_config.rs create mode 100644 trailbase-core/src/admin/config/mod.rs create mode 100644 trailbase-core/src/admin/config/update_config.rs create mode 100644 trailbase-core/src/admin/error.rs create mode 100644 trailbase-core/src/admin/jwt.rs create mode 100644 trailbase-core/src/admin/list_logs.rs create mode 100644 trailbase-core/src/admin/mod.rs create mode 100644 trailbase-core/src/admin/oauth_providers.rs create mode 100644 trailbase-core/src/admin/parse.rs create mode 100644 trailbase-core/src/admin/query.rs create mode 100644 trailbase-core/src/admin/rows/delete_rows.rs create mode 100644 trailbase-core/src/admin/rows/insert_row.rs create mode 100644 trailbase-core/src/admin/rows/list_rows.rs create mode 100644 trailbase-core/src/admin/rows/mod.rs create mode 100644 trailbase-core/src/admin/rows/read_files.rs create mode 100644 trailbase-core/src/admin/rows/update_row.rs create mode 100644 trailbase-core/src/admin/schema/mod.rs create mode 100644 trailbase-core/src/admin/table/alter_index.rs create mode 100644 trailbase-core/src/admin/table/alter_table.rs create mode 100644 trailbase-core/src/admin/table/create_index.rs create mode 100644 trailbase-core/src/admin/table/create_table.rs create mode 100644 trailbase-core/src/admin/table/drop_index.rs create mode 100644 trailbase-core/src/admin/table/drop_table.rs create mode 100644 trailbase-core/src/admin/table/get_table_schema.rs create mode 100644 trailbase-core/src/admin/table/list_tables.rs create mode 100644 trailbase-core/src/admin/table/mod.rs create mode 100644 trailbase-core/src/admin/user/create_user.rs create mode 100644 trailbase-core/src/admin/user/list_users.rs create mode 100644 trailbase-core/src/admin/user/mod.rs create mode 100644 trailbase-core/src/admin/user/update_user.rs create mode 100644 trailbase-core/src/app_state.rs create mode 100644 trailbase-core/src/assets.rs create mode 100644 trailbase-core/src/auth/api/avatar.rs create mode 100644 trailbase-core/src/auth/api/change_email.rs create mode 100644 trailbase-core/src/auth/api/change_password.rs create mode 100644 trailbase-core/src/auth/api/delete.rs create mode 100644 trailbase-core/src/auth/api/login.rs create mode 100644 trailbase-core/src/auth/api/logout.rs create mode 100644 trailbase-core/src/auth/api/mod.rs create mode 100644 trailbase-core/src/auth/api/refresh.rs create mode 100644 trailbase-core/src/auth/api/register.rs create mode 100644 trailbase-core/src/auth/api/reset_password.rs create mode 100644 trailbase-core/src/auth/api/token.rs create mode 100644 trailbase-core/src/auth/api/verify_email.rs create mode 100644 trailbase-core/src/auth/auth_test.rs create mode 100644 trailbase-core/src/auth/error.rs create mode 100644 trailbase-core/src/auth/jwt.rs create mode 100644 trailbase-core/src/auth/mod.rs create mode 100644 trailbase-core/src/auth/oauth/callback.rs create mode 100644 trailbase-core/src/auth/oauth/list_providers.rs create mode 100644 trailbase-core/src/auth/oauth/login.rs create mode 100644 trailbase-core/src/auth/oauth/mod.rs create mode 100644 trailbase-core/src/auth/oauth/oauth_test.rs create mode 100644 trailbase-core/src/auth/oauth/provider.rs create mode 100644 trailbase-core/src/auth/oauth/providers/discord.rs create mode 100644 trailbase-core/src/auth/oauth/providers/gitlab.rs create mode 100644 trailbase-core/src/auth/oauth/providers/google.rs create mode 100644 trailbase-core/src/auth/oauth/providers/mod.rs create mode 100644 trailbase-core/src/auth/oauth/providers/test.rs create mode 100644 trailbase-core/src/auth/oauth/state.rs create mode 100644 trailbase-core/src/auth/password.rs create mode 100644 trailbase-core/src/auth/tokens.rs create mode 100644 trailbase-core/src/auth/ui/mod.rs create mode 100644 trailbase-core/src/auth/user.rs create mode 100644 trailbase-core/src/auth/util.rs create mode 100644 trailbase-core/src/config.rs create mode 100644 trailbase-core/src/constants.rs create mode 100644 trailbase-core/src/data_dir.rs create mode 100644 trailbase-core/src/email.rs create mode 100644 trailbase-core/src/extract/either.rs create mode 100644 trailbase-core/src/extract/mod.rs create mode 100644 trailbase-core/src/extract/multipart.rs create mode 100644 trailbase-core/src/lib.rs create mode 100644 trailbase-core/src/listing.rs create mode 100644 trailbase-core/src/logging.rs create mode 100644 trailbase-core/src/migrations.rs create mode 100644 trailbase-core/src/query/error.rs create mode 100644 trailbase-core/src/query/mod.rs create mode 100644 trailbase-core/src/query/query_api.rs create mode 100644 trailbase-core/src/records/create_record.rs create mode 100644 trailbase-core/src/records/delete_record.rs create mode 100644 trailbase-core/src/records/error.rs create mode 100644 trailbase-core/src/records/files.rs create mode 100644 trailbase-core/src/records/json_schema.rs create mode 100644 trailbase-core/src/records/json_to_sql.rs create mode 100644 trailbase-core/src/records/list_records.rs create mode 100644 trailbase-core/src/records/mod.rs create mode 100644 trailbase-core/src/records/read_record.rs create mode 100644 trailbase-core/src/records/record_api.rs create mode 100644 trailbase-core/src/records/sql_to_json.rs create mode 100644 trailbase-core/src/records/test_utils.rs create mode 100644 trailbase-core/src/records/update_record.rs create mode 100644 trailbase-core/src/records/validate.rs create mode 100644 trailbase-core/src/scheduler.rs create mode 100644 trailbase-core/src/schema.rs create mode 100644 trailbase-core/src/server/init.rs create mode 100644 trailbase-core/src/server/mod.rs create mode 100644 trailbase-core/src/table_metadata.rs create mode 100644 trailbase-core/src/test.rs create mode 100644 trailbase-core/src/transaction.rs create mode 100644 trailbase-core/src/util.rs create mode 100644 trailbase-core/src/value_notifier.rs create mode 100644 trailbase-core/tests/integration_test.rs create mode 100644 trailbase-extension/Cargo.toml create mode 100644 trailbase-extension/src/jsonschema.rs create mode 100644 trailbase-extension/src/lib.rs create mode 100644 trailbase-extension/src/password.rs create mode 100644 trailbase-extension/src/uuid.rs create mode 100644 trailbase-extension/src/validators.rs create mode 100644 trailbase-sqlite/Cargo.toml create mode 100644 trailbase-sqlite/examples/uuid.rs create mode 100644 trailbase-sqlite/src/lib.rs create mode 100644 trailbase-sqlite/src/schema.rs create mode 100644 ui/admin/.gitignore create mode 100644 ui/admin/.prettierignore create mode 100644 ui/admin/.prettierrc.mjs create mode 100644 ui/admin/README.md create mode 100644 ui/admin/eslint.config.mjs create mode 100644 ui/admin/index.html create mode 100644 ui/admin/package.json create mode 100644 ui/admin/postcss.config.mjs create mode 100644 ui/admin/proto/config.ts create mode 100644 ui/admin/proto/config_api.ts create mode 100644 ui/admin/proto/google/protobuf/descriptor.ts create mode 100644 ui/admin/proto/vault.ts create mode 100644 ui/admin/src/App.tsx create mode 120000 ui/admin/src/assets/favicon.svg create mode 100644 ui/admin/src/components/DestructiveActionButton.tsx create mode 100644 ui/admin/src/components/ErrorBoundary.tsx create mode 100644 ui/admin/src/components/FilterBar.tsx create mode 100644 ui/admin/src/components/FormFields.tsx create mode 100644 ui/admin/src/components/IndexPage.tsx create mode 100644 ui/admin/src/components/NavBar.tsx create mode 100644 ui/admin/src/components/SafeSheet.tsx create mode 100644 ui/admin/src/components/SplitView.tsx create mode 100644 ui/admin/src/components/Table.tsx create mode 100644 ui/admin/src/components/auth/AccountsPage.tsx create mode 100644 ui/admin/src/components/auth/AddUser.tsx create mode 100644 ui/admin/src/components/auth/AuthButton.tsx create mode 100644 ui/admin/src/components/auth/LoginPage.tsx create mode 100644 ui/admin/src/components/auth/UserTable.tsx create mode 100644 ui/admin/src/components/editor/EditorPage.tsx create mode 100644 ui/admin/src/components/logs/LogsPage.tsx create mode 100644 ui/admin/src/components/settings/AuthSettings.tsx create mode 100644 ui/admin/src/components/settings/EmailSettings.tsx create mode 100644 ui/admin/src/components/settings/SchemaSettings.tsx create mode 100644 ui/admin/src/components/settings/SettingsPage.tsx create mode 100644 ui/admin/src/components/tables/CreateAlterIndex.tsx create mode 100644 ui/admin/src/components/tables/CreateAlterTable.tsx create mode 100644 ui/admin/src/components/tables/InsertAlterRow.tsx create mode 100644 ui/admin/src/components/tables/RecordApiSettings.tsx create mode 100644 ui/admin/src/components/tables/TablesPage.tsx create mode 100644 ui/admin/src/components/ui/accordion.tsx create mode 100644 ui/admin/src/components/ui/badge.tsx create mode 100644 ui/admin/src/components/ui/button.tsx create mode 100644 ui/admin/src/components/ui/card.tsx create mode 100644 ui/admin/src/components/ui/checkbox.tsx create mode 100644 ui/admin/src/components/ui/dialog.tsx create mode 100644 ui/admin/src/components/ui/hover-card.tsx create mode 100644 ui/admin/src/components/ui/label.tsx create mode 100644 ui/admin/src/components/ui/resizable.tsx create mode 100644 ui/admin/src/components/ui/select.tsx create mode 100644 ui/admin/src/components/ui/separator.tsx create mode 100644 ui/admin/src/components/ui/sheet.tsx create mode 100644 ui/admin/src/components/ui/switch.tsx create mode 100644 ui/admin/src/components/ui/table.tsx create mode 100644 ui/admin/src/components/ui/tabs.tsx create mode 100644 ui/admin/src/components/ui/text-field.tsx create mode 100644 ui/admin/src/components/ui/toast.tsx create mode 100644 ui/admin/src/components/ui/toggle.tsx create mode 100644 ui/admin/src/components/ui/tooltip.tsx create mode 100644 ui/admin/src/index.css create mode 100644 ui/admin/src/index.tsx create mode 100644 ui/admin/src/lib/bindings.ts create mode 100644 ui/admin/src/lib/config.ts create mode 100644 ui/admin/src/lib/fetch.ts create mode 100644 ui/admin/src/lib/name.ts create mode 100644 ui/admin/src/lib/parse.ts create mode 100644 ui/admin/src/lib/schema.ts create mode 100644 ui/admin/src/lib/table.ts create mode 100644 ui/admin/src/lib/user.ts create mode 100644 ui/admin/src/lib/utils.ts create mode 100644 ui/admin/tailwind.config.ts create mode 100644 ui/admin/tests/util.test.ts create mode 100644 ui/admin/tsconfig.json create mode 100644 ui/admin/ui.config.json create mode 100644 ui/admin/vite.config.mts create mode 100644 ui/auth/.gitignore create mode 100644 ui/auth/.prettierignore create mode 100644 ui/auth/.prettierrc.mjs create mode 100644 ui/auth/astro.config.mjs create mode 100644 ui/auth/package.json create mode 100644 ui/auth/src/components/AlertBox.astro create mode 100644 ui/auth/src/components/Card.astro create mode 100644 ui/auth/src/components/ErrorBoundary.tsx create mode 100644 ui/auth/src/components/Form.astro create mode 100644 ui/auth/src/components/ListOauthProviders.tsx create mode 100644 ui/auth/src/components/Profile.tsx create mode 100644 ui/auth/src/components/ui/button.tsx create mode 100644 ui/auth/src/components/ui/card.tsx create mode 100644 ui/auth/src/components/ui/dialog.tsx create mode 100644 ui/auth/src/components/ui/label.tsx create mode 100644 ui/auth/src/components/ui/text-field.tsx create mode 100644 ui/auth/src/components/ui/toast.tsx create mode 100644 ui/auth/src/env.d.ts create mode 100644 ui/auth/src/layouts/BaseLayout.astro create mode 100644 ui/auth/src/lib/constants.ts create mode 100644 ui/auth/src/lib/utils.ts create mode 100644 ui/auth/src/pages/change_email.astro create mode 100644 ui/auth/src/pages/change_password.astro create mode 100644 ui/auth/src/pages/login.astro create mode 100644 ui/auth/src/pages/profile.astro create mode 100644 ui/auth/src/pages/register.astro create mode 100644 ui/auth/src/pages/reset_password/request.astro create mode 100644 ui/auth/src/pages/reset_password/update.astro create mode 100644 ui/auth/tailwind.config.ts create mode 100644 ui/auth/tsconfig.json create mode 100644 ui/auth/ui.config.json create mode 100644 ui/auth/ui.preset.mjs create mode 100644 ui/common/css/global.css create mode 100644 ui/common/css/kobalte.css create mode 100644 ui/common/tailwind.config.mjs create mode 100644 ui/common/tsconfig.base.json create mode 160000 vendor/refinery create mode 100644 vendor/refinery-libsql/Cargo.toml create mode 100644 vendor/refinery-libsql/src/lib.rs create mode 100644 vendor/refinery-libsql/tests/libsql.rs create mode 100644 vendor/refinery-libsql/tests/migrations/V1-2/V1__initial.rs create mode 100644 vendor/refinery-libsql/tests/migrations/V1-2/V2__add_cars_and_motos_table.sql create mode 100644 vendor/refinery-libsql/tests/migrations/V3/V3__add_brand_to_cars_table.sql create mode 100644 vendor/refinery-libsql/tests/migrations/V4__add_year_to_motos_table.rs create mode 100644 vendor/refinery-libsql/tests/migrations_broken/V1__initial.sql create mode 100644 vendor/refinery-libsql/tests/migrations_broken/V2__add_cars_table.sql create mode 100644 vendor/refinery-libsql/tests/migrations_broken/V3__add_brand_to_cars_table.sql create mode 100644 vendor/refinery-libsql/tests/migrations_missing/V2__add_cars_table.sql create mode 100644 vendor/refinery-libsql/tests/migrations_unversioned/U0__merge_out_of_order.sql create mode 100644 vendor/sqlean/Cargo.toml create mode 100644 vendor/sqlean/bindings.h create mode 100644 vendor/sqlean/build.rs create mode 160000 vendor/sqlean/bundled/sqlean create mode 100644 vendor/sqlean/src/lib.rs create mode 160000 vendor/sqlite-loadable diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d265f54 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,20 @@ +.hooks/ + +target/ +../../target/ +**/target/ +**/node_modules/ +**/dist/ + +traildepot/ +docs/ + +Dockerfile* +.docker* + +.git/ +.git* + +*.image +.rustfmt.toml +.env diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..11d1ee2 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,39 @@ +name: test + +on: + pull_request: + push: + branches: [main] + +jobs: + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: 'true' + - name: Install Dependencies + run: | + sudo apt-get update && \ + sudo apt-get install -y --no-install-recommends curl libssl-dev pkg-config libclang-dev protobuf-compiler libprotobuf-dev libsqlite3-dev + - uses: pnpm/action-setup@v4 + with: + version: 9 + - name: PNPM install + run: | + pnpm i + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + channel: stable + flutter-version: 3.24.3 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + default: true + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.1 + # - name: Rust tests + # run: | + # cargo test -p trailbase-core -p trailbase-extension -p trailbase-sqlite -p trailbase-cli diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8163535 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Build artifacts +target/ +node_modules/ + +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ + +# Dev artifacts +public/ +traildepot/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3a84216 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "vendor/refinery"] + path = vendor/refinery + url = git@github.com:trailbaseio/refinery.git +[submodule "vendor/sqlite_loadable"] + path = vendor/sqlite-loadable + url = git@github.com:trailbaseio/sqlite-loadable-rs.git +[submodule "vendor/sqlean/bundled/sqlean"] + path = vendor/sqlean/bundled/sqlean + url = https://github.com/trailbaseio/sqlean diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..09fed59 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,103 @@ +exclude: '(trailbase-core/bindings|bindings)/.*' + +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-byte-order-marker + - id: check-case-conflict + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml + - id: end-of-file-fixer + - id: mixed-line-ending + - id: trailing-whitespace + +# Self-validation for pre-commit manifest. +- repo: https://github.com/pre-commit/pre-commit + rev: v3.8.0 + hooks: + - id: validate_manifest + +- repo: local + hooks: + ### Rust ### + - id: cargofmt + name: Cargo Format + entry: cargo fmt -- --check + pass_filenames: false + # NOTE: language refers to the language in which the hook is implemented + # in, rather than the inputs. In this case we rely on cargo being + # installed on the system + language: system + # NOTE: types/files/exclude narrow the inputs the hook should run on. + types: [rust] + exclude: '^vendor/' + + - id: cargoclippy + name: Cargo Clippy + # Be verbose to at least still see warnings scroll by. + verbose: true + entry: cargo clippy --workspace --no-deps + language: system + types: [rust] + exclude: '^vendor/' + pass_filenames: false + + - id: cargotest + name: Cargo Test + entry: cargo test --workspace -- --show-output + language: system + types: [rust] + exclude: '^(vendor|bindings)/' + pass_filenames: false + + ### Auth, Admin, Docs UI ### + - id: prettier + name: Prettier + entry: pnpm -r format --check + language: system + types: [file] + files: .*\.(js|mjs|cjs|ts|jsx|tsx|astro|md|mdx)$ + pass_filenames: false + + - id: typescript_check + name: Typescript Check + entry: pnpm -r check + language: system + types: [file] + files: .*\.(js|mjs|cjs|ts|jsx|tsx|astro|mdx)$ + pass_filenames: false + + - id: javascript_test + name: JavaScript Test + entry: pnpm -r test + language: system + types: [file] + files: .*\.(js|mjs|cjs|ts|jsx|tsx|astro)$ + pass_filenames: false + + ### Dart client and example + - id: dart_format + name: Dart format + entry: dart format -o none --set-exit-if-changed client/trailbase-dart examples/blog/flutter + language: system + types: [file] + files: .*\.dart$ + pass_filenames: false + + - id: dart_analyze + name: Dart analyze + entry: sh -c 'dart pub -C client/trailbase-dart get && dart pub -C examples/blog/flutter get && dart analyze -- client/trailbase-dart examples/blog/flutter' + language: system + types: [file] + files: .*\.dart$ + pass_filenames: false + + - id: dart_test + name: Dart test + entry: sh -c 'cd client/trailbase-dart && dart pub get && dart test' + language: system + types: [file] + files: .*\.dart$ + pass_filenames: false diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..96caafd --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,8 @@ +# Docs: https://rust-lang.github.io/rustfmt/ +edition = "2021" +brace_style = "SameLineWhere" +empty_item_single_line = true +max_width = 100 +comment_width = 100 +wrap_comments = true +tab_spaces = 2 diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..da44a32 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4658 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "serde", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstream" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "argon2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures", + "password-hash", +] + +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.3.1", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel 2.3.1", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener 5.3.1", + "futures-lite", + "rustix", + "tracing", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-std" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io", + "async-lock", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "auto-future" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c1e7e457ea78e524f48639f551fd79703ac3f2237f5ecccdf4708f8a75ad373" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "axum" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http 1.1.0", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "multer", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-client-ip" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eefda7e2b27e1bda4d6fa8a06b50803b8793769045918bc37ad062d48a6efac" +dependencies = [ + "axum", + "forwarded-header-value", + "serde", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.1.0", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.1", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-extra" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73c3220b188aea709cf1b6c5f9b01c3bd936bb08bd2b5184a12b35ac8131b1f9" +dependencies = [ + "axum", + "axum-core", + "bytes", + "futures-util", + "http 1.1.0", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "prost 0.12.6", + "serde", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-test" +version = "16.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ba5211f2e0b77d1cbe1e1c7c826edc20fb1f69720a7fdb1d2a25289c98978e" +dependencies = [ + "anyhow", + "assert-json-diff", + "auto-future", + "axum", + "bytes", + "bytesize", + "cookie", + "http 1.1.0", + "http-body-util", + "hyper", + "hyper-util", + "mime", + "pretty_assertions", + "reserve-port", + "rust-multipart-rfc7578_2", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "tokio", + "tower", + "url", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "barrel" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9e605929a6964efbec5ac0884bd0fe93f12a3b1eb271f52c251316640c68d9" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bindgen" +version = "0.66.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel 2.3.1", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "borrow-or-share" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytecount" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +dependencies = [ + "serde", +] + +[[package]] +name = "bytesize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +dependencies = [ + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "chumsky" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" +dependencies = [ + "hashbrown 0.14.5", + "stacker", +] + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "futures", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "tokio", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "custom-binary" +version = "0.1.0" +dependencies = [ + "axum", + "env_logger", + "tokio", + "tracing-subscriber", + "trailbase-core", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core", + "serde", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "email-encoding" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60d1d33cdaede7e24091f039632eb5d3c7469fe5b066a985281a34fc70fa317f" +dependencies = [ + "base64 0.22.1", + "memchr", +] + +[[package]] +name = "email_address" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" +dependencies = [ + "serde", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fancy-regex" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fluent-uri" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1918b65d96df47d3591bed19c5cca17e3fa5d0707318e4b5ef2eae01764df7e5" +dependencies = [ + "borrow-or-share", + "ref-cast", + "serde", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "forwarded-header-value" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9" +dependencies = [ + "nonempty", + "thiserror", +] + +[[package]] +name = "fraction" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f158e3ff0a1b334408dc9fb811cd99b446986f4d8b741bb08f9df1604085ae7" +dependencies = [ + "lazy_static", + "num", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd69211b9b519e98303c015e21a007e293db403b6c85b9b124e133d25e242cdd" +dependencies = [ + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", + "serde", +] + +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "infer" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847" +dependencies = [ + "cfb", +] + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonschema" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "893d6229c7315763ca0df9b29ab7661ee419f286577a02847c5521b462e071af" +dependencies = [ + "ahash", + "base64 0.22.1", + "bytecount", + "email_address", + "fancy-regex", + "fraction", + "idna 1.0.2", + "itoa", + "num-cmp", + "once_cell", + "percent-encoding", + "referencing", + "regex-syntax", + "serde", + "serde_json", + "uuid-simd", +] + +[[package]] +name = "jsonwebtoken" +version = "9.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" +dependencies = [ + "base64 0.21.7", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lettre" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0161e452348e399deb685ba05e55ee116cae9410f4f51fe42d597361444521d9" +dependencies = [ + "async-std", + "async-trait", + "base64 0.22.1", + "chumsky", + "email-encoding", + "email_address", + "fastrand", + "futures-io", + "futures-util", + "httpdate", + "idna 1.0.2", + "mime", + "nom", + "percent-encoding", + "quoted_printable", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "socket2", + "tokio", + "tokio-rustls", + "url", + "webpki-roots", +] + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "libsql" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe18646e4ef8db446bc3e3f5fb96131483203bc5f4998ff149f79a067530c01c" +dependencies = [ + "async-trait", + "bitflags", + "bytes", + "futures", + "libsql-sys", + "serde", + "thiserror", + "tracing", +] + +[[package]] +name = "libsql-ffi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5919d202c2d296b4c44b6877d1b67fe6ad8f18520ce74bd70a29c383e44ccbee" +dependencies = [ + "bindgen 0.66.1", + "cc", +] + +[[package]] +name = "libsql-ffi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2a50a585a1184a43621a9133b7702ba5cb7a87ca5e704056b19d8005de6faf" +dependencies = [ + "bindgen 0.66.1", + "cc", +] + +[[package]] +name = "libsql-rusqlite" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b811f72e13b9864601197d234621ffe89a490b2cb034cf28753b111334cf1db3" +dependencies = [ + "bitflags", + "fallible-iterator 0.2.0", + "fallible-streaming-iterator", + "hashlink", + "libsql-ffi 0.4.1", + "smallvec", +] + +[[package]] +name = "libsql-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c05b61c226781d6f5e26e3e7364617f19c0c1d5332035802e9229d6024cec05" +dependencies = [ + "bytes", + "libsql-ffi 0.5.0", + "once_cell", + "tracing", + "zerocopy", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +dependencies = [ + "value-bag", +] + +[[package]] +name = "logos" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6b6e02facda28ca5fb8dbe4b152496ba3b1bd5a4b40bb2b1b2d8ad74e0f39b" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b32eb6b5f26efacd015b000bfc562186472cd9b34bdba3f6b264e2a052676d10" +dependencies = [ + "beef", + "fnv", + "lazy_static", + "proc-macro2", + "quote", + "regex-syntax", + "syn", +] + +[[package]] +name = "logos-derive" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5d0c5463c911ef55624739fc353238b4e310f0144be1f875dc42fec6bfd5ec" +dependencies = [ + "logos-codegen", +] + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mimalloc" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minijinja" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9ca8daf4b0b4029777f1bc6e1aedd1aec7b74c276a43bc6f620a8e1a1c0a90e" +dependencies = [ + "serde", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "multer" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http 1.1.0", + "httparse", + "memchr", + "mime", + "spin", + "version_check", +] + +[[package]] +name = "multimap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nonempty" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-cmp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "oauth2" +version = "5.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d385da3c602d29036d2f70beed71c36604df7570be17fed4c5b839616785bf" +dependencies = [ + "base64 0.22.1", + "chrono", + "getrandom", + "http 1.1.0", + "rand", + "reqwest", + "serde", + "serde_json", + "serde_path_to_error", + "sha2", + "thiserror", + "url", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "object_store" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eb4c22c6154a1e759d7099f9ffad7cc5ef8245f9efbab4a41b92623079c82f3" +dependencies = [ + "async-trait", + "bytes", + "chrono", + "futures", + "humantime", + "itertools 0.13.0", + "parking_lot", + "percent-encoding", + "snafu", + "tokio", + "tracing", + "url", + "walkdir", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "oorandom" +version = "11.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" + +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64 0.22.1", + "serde", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher 0.3.11", + "uncased", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "polling" +version = "3.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive 0.12.6", +] + +[[package]] +name = "prost" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +dependencies = [ + "bytes", + "prost-derive 0.13.3", +] + +[[package]] +name = "prost-build" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" +dependencies = [ + "bytes", + "heck", + "itertools 0.13.0", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost 0.13.3", + "prost-types 0.13.3", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-derive" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +dependencies = [ + "anyhow", + "itertools 0.13.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-reflect" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5eec97d5d34bdd17ad2db2219aabf46b054c6c41bd5529767c9ce55be5898f" +dependencies = [ + "logos", + "once_cell", + "prost 0.12.6", + "prost-reflect-derive 0.13.0", + "prost-types 0.12.6", +] + +[[package]] +name = "prost-reflect" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b7535b02f0e5efe3e1dbfcb428be152226ed0c66cad9541f2274c8ba8d4cd40" +dependencies = [ + "once_cell", + "prost 0.13.3", + "prost-reflect-derive 0.14.0", + "prost-types 0.13.3", +] + +[[package]] +name = "prost-reflect-build" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e2537231d94dd2778920c2ada37dd9eb1ac0325bb3ee3ee651bd44c1134123" +dependencies = [ + "prost-build", + "prost-reflect 0.14.2", +] + +[[package]] +name = "prost-reflect-derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c3f519df051f8a700c5aa42b53f9c42d54959506b7ed58ac7a6af7991fdc22" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-reflect-derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fce6b22f15cc8d8d400a2b98ad29202b33bd56c7d9ddd815bc803a807ecb65" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost 0.12.6", +] + +[[package]] +name = "prost-types" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +dependencies = [ + "prost 0.13.3", +] + +[[package]] +name = "psm" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" +dependencies = [ + "cc", +] + +[[package]] +name = "quinn" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.0.0", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash 2.0.0", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e346e016eacfff12233c243718197ca12f148c84e1e84268a896699b41c71780" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "quoted_printable" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "referencing" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb853437e467c693ac1dc8c1520105a31b8c2588544ff2f3cfa5a7c706c6c069" +dependencies = [ + "ahash", + "fluent-uri", + "once_cell", + "percent-encoding", + "serde_json", +] + +[[package]] +name = "refinery" +version = "0.8.14" +dependencies = [ + "refinery-core", + "refinery-macros", +] + +[[package]] +name = "refinery-core" +version = "0.8.14" +dependencies = [ + "async-trait", + "cfg-if", + "log", + "regex", + "siphasher 1.0.1", + "thiserror", + "time", + "url", + "walkdir", +] + +[[package]] +name = "refinery-libsql" +version = "0.0.1" +dependencies = [ + "async-trait", + "barrel", + "libsql", + "refinery", + "refinery-core", + "tempfile", + "time", + "tokio", +] + +[[package]] +name = "refinery-macros" +version = "0.8.14" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "refinery-core", + "regex", + "syn", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.12.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "windows-registry", +] + +[[package]] +name = "reserve-port" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9838134a2bfaa8e1f40738fcc972ac799de6e0e06b5157acb95fc2b05a0ea283" +dependencies = [ + "lazy_static", + "thiserror", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rust-embed" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" +dependencies = [ + "mime_guess", + "sha2", + "walkdir", +] + +[[package]] +name = "rust-multipart-rfc7578_2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b748410c0afdef2ebbe3685a6a862e2ee937127cdaae623336a459451c8d57" +dependencies = [ + "bytes", + "futures-core", + "futures-util", + "http 0.2.12", + "mime", + "mime_guess", + "rand", + "thiserror", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "snafu" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019" +dependencies = [ + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlean" +version = "0.0.1" +dependencies = [ + "bindgen 0.70.1", + "cc", + "libsql-ffi 0.5.0", +] + +[[package]] +name = "sqlformat" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" +dependencies = [ + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlite-loadable" +version = "0.0.6-alpha.6" +dependencies = [ + "bitflags", + "libsql-ffi 0.5.0", + "serde", + "serde_json", + "sqlite-loadable-macros", +] + +[[package]] +name = "sqlite-loadable-macros" +version = "0.0.3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sqlite3-parser" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5307dad6cb84730ce8bdefde56ff4cf95fe516972d52e2bbdc8a8cd8f2520b" +dependencies = [ + "bitflags", + "cc", + "fallible-iterator 0.3.0", + "indexmap", + "log", + "memchr", + "phf", + "phf_codegen", + "phf_shared", + "uncased", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.59.0", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "temp-dir" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-cookies" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fd0118512cf0b3768f7fcccf0bef1ae41d68f2b45edc1e77432b36c97c56c6d" +dependencies = [ + "async-trait", + "axum-core", + "cookie", + "futures-util", + "http 1.1.0", + "parking_lot", + "pin-project-lite", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http 1.1.0", + "http-body", + "http-body-util", + "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trailbase-cli" +version = "0.1.0" +dependencies = [ + "axum", + "chrono", + "clap", + "env_logger", + "libsql", + "log", + "mimalloc", + "serde", + "serde_json", + "tokio", + "tracing-subscriber", + "trailbase-core", + "utoipa", + "utoipa-swagger-ui", + "uuid", +] + +[[package]] +name = "trailbase-core" +version = "0.1.0" +dependencies = [ + "anyhow", + "arc-swap", + "argon2", + "async-trait", + "axum", + "axum-client-ip", + "axum-extra", + "axum-test", + "base64 0.22.1", + "chrono", + "cookie", + "criterion", + "ed25519-dalek", + "env_logger", + "fallible-iterator 0.3.0", + "form_urlencoded", + "futures", + "indexmap", + "indoc", + "itertools 0.13.0", + "jsonschema", + "jsonwebtoken", + "lazy_static", + "lettre", + "libsql", + "libsql-rusqlite", + "log", + "minijinja", + "oauth2", + "object_store", + "parking_lot", + "prost 0.12.6", + "prost-build", + "prost-reflect 0.13.1", + "prost-reflect-build", + "quoted_printable", + "rand", + "refinery", + "refinery-libsql", + "regex", + "reqwest", + "rust-embed", + "schemars", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sha2", + "sqlformat", + "sqlite3-parser", + "temp-dir", + "thiserror", + "tokio", + "tower", + "tower-cookies", + "tower-http", + "tower-service", + "tracing", + "tracing-subscriber", + "trailbase-extension", + "trailbase-sqlite", + "ts-rs", + "url", + "utoipa", + "uuid", + "validator", +] + +[[package]] +name = "trailbase-extension" +version = "0.1.0" +dependencies = [ + "argon2", + "base64 0.22.1", + "jsonschema", + "libsql", + "lru", + "parking_lot", + "rand", + "regex", + "serde_json", + "sqlean", + "sqlite-loadable", + "tokio", + "uuid", + "validator", +] + +[[package]] +name = "trailbase-sqlite" +version = "0.1.0" +dependencies = [ + "infer", + "jsonschema", + "lazy_static", + "libsql", + "log", + "schemars", + "serde", + "serde_json", + "thiserror", + "tokio", + "trailbase-extension", + "uuid", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "ts-rs" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a2f31991cee3dce1ca4f929a8a04fdd11fd8801aac0f2030b0fa8a0a3fef6b9" +dependencies = [ + "lazy_static", + "serde_json", + "thiserror", + "ts-rs-macros", + "uuid", +] + +[[package]] +name = "ts-rs-macros" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea0b99e8ec44abd6f94a18f28f7934437809dd062820797c52401298116f70e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "termcolor", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uncased" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicase" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna 0.5.0", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "utoipa" +version = "5.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d9ba0ade4e2f024cd1842dfbaf9dbc540639fc082299acf7649d71bd14eaca3" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "5.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf390d6503c9c9eac988447c38ba934a707b0b768b14511a493b4fc0e8ecb00" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "8.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5c80b4dd79ea382e8374d67dcce22b5c6663fa13a82ad3886441d1bbede5e35" +dependencies = [ + "axum", + "mime_guess", + "regex", + "rust-embed", + "serde", + "serde_json", + "url", + "utoipa", + "zip", +] + +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", + "serde", +] + +[[package]] +name = "uuid-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" +dependencies = [ + "outref", + "uuid", + "vsimd", +] + +[[package]] +name = "validator" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db79c75af171630a3148bd3e6d7c4f42b6a9a014c2945bc5ed0020cbb8d9478e" +dependencies = [ + "idna 0.5.0", + "once_cell", + "regex", + "serde", + "serde_derive", + "serde_json", + "url", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-bag" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "web-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zip" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "displaydoc", + "flate2", + "indexmap", + "memchr", + "thiserror", + "zopfli", +] + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..0c8e15c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,46 @@ +[workspace] +resolver = "2" +members = [ + "examples/custom-binary", + "trailbase-cli", + "trailbase-core", + "trailbase-extension", + "trailbase-sqlite", + "vendor/refinery-libsql", + "vendor/sqlean", +] +default-members = [ + "trailbase-cli", + "trailbase-core", + "trailbase-extension", + "trailbase-sqlite", +] +exclude = [ + "vendor/refinery", + "vendor/sqlite-loadable", +] + +# https://doc.rust-lang.org/cargo/reference/profiles.html +[profile.release] +panic = "unwind" +opt-level = 3 +# PGO doesn't work with LTO: https://github.com/llvm/llvm-project/issues/57501 +# lto = "off" +lto = true +codegen-units = 1 + +[workspace.dependencies] +libsql = { package = "libsql", version = "^0.6.0", default-features = false, features = ["core", "serde"] } +refinery = { package = "refinery", path = "vendor/refinery/refinery", default-features = false } +refinery-core = { package = "refinery-core", path = "vendor/refinery/refinery_core" } +refinery-libsql = { package = "refinery-libsql", path = "vendor/refinery-libsql" } +rusqlite = { package = "libsql-rusqlite", version = "^0.32", default-features = false, features = [ + "libsql-experimental", + "column_decltype", + "load_extension", + "modern_sqlite", + "functions", + "limits", + "backup", +] } +sqlite-loadable = { package = "sqlite-loadable", path = "./vendor/sqlite-loadable", features=["static"] } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..675b947 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,51 @@ +FROM lukemathwalker/cargo-chef:latest-rust-1.81-slim AS chef + +# Install additional build dependencies. +# +# NOTE: we should consider building sqlean against +# libsql/libsql-sqlite3/src/sqlite3ext.h rather than upstrean libsqlite3-dev +# for increased consistency. +RUN apt-get update && apt-get install -y --no-install-recommends curl libssl-dev pkg-config libclang-dev protobuf-compiler libprotobuf-dev libsqlite3-dev + +ENV PATH=/usr/local/node/bin:$PATH +ARG NODE_VERSION=22.9.0 + +RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \ + /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \ + rm -rf /tmp/node-build-master + +RUN npm install -g pnpm +RUN pnpm --version + +FROM chef AS planner +WORKDIR /app +COPY . . +RUN cargo chef prepare --recipe-path recipe.json + + +FROM planner AS builder +# Re-build dependencies in case they have changed. +COPY --from=planner /app/recipe.json recipe.json +RUN cargo chef cook --release --recipe-path recipe.json + +COPY . . + +RUN RUSTFLAGS="-C target-feature=+crt-static" cargo build --target x86_64-unknown-linux-gnu --release --bin trail + +FROM alpine:3.20 AS runtime +RUN apk add --no-cache tini curl + +COPY --from=builder /app/target/x86_64-unknown-linux-gnu/release/trail /app/ + +# When `docker run` is executed, launch the binary as unprivileged user. +RUN adduser -D trailbase +USER trailbase + +WORKDIR /app + +EXPOSE 4000 +ENTRYPOINT ["tini", "--"] + +CMD ["/app/trail", "--data-dir", "/app/traildepot", "run", "--address", "0.0.0.0:4000"] + +HEALTHCHECK CMD curl --fail http://localhost:4000/api/healthcheck || exit 1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7ddce61 --- /dev/null +++ b/LICENSE @@ -0,0 +1,105 @@ +# Functional Source License, Version 1.1, Apache 2.0 Future License + +## Abbreviation + +FSL-1.1-Apache-2.0 + +## Notice + +Copyright 2024 Sebastian Jeltsch + +## Terms and Conditions + +### Licensor ("We") + +The party offering the Software under these Terms and Conditions. + +### The Software + +The "Software" is each version of the software that we make available under +these Terms and Conditions, as indicated by our inclusion of these Terms and +Conditions with the Software. + +### License Grant + +Subject to your compliance with this License Grant and the Patents, +Redistribution and Trademark clauses below, we hereby grant you the right to +use, copy, modify, create derivative works, publicly perform, publicly display +and redistribute the Software for any Permitted Purpose identified below. + +### Permitted Purpose + +A Permitted Purpose is any purpose other than a Competing Use. A Competing Use +means making the Software available to others in a commercial product or +service that: + +1. substitutes for the Software; + +2. substitutes for any other product or service we offer using the Software + that exists as of the date we make the Software available; or + +3. offers the same or substantially similar functionality as the Software. + +Permitted Purposes specifically include using the Software: + +1. for your internal use and access; + +2. for non-commercial education; + +3. for non-commercial research; and + +4. in connection with professional services that you provide to a licensee + using the Software in accordance with these Terms and Conditions. + +### Patents + +To the extent your use for a Permitted Purpose would necessarily infringe our +patents, the license grant above includes a license under our patents. If you +make a claim against any party that the Software infringes or contributes to +the infringement of any patent, then your patent license to the Software ends +immediately. + +### Redistribution + +The Terms and Conditions apply to all copies, modifications and derivatives of +the Software. + +If you redistribute any copies, modifications or derivatives of the Software, +you must include a copy of or a link to these Terms and Conditions and not +remove any copyright notices provided in or with the Software. + +### Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR +PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT. + +IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE +SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, +EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE. + +### Trademarks + +Except for displaying the License Details and identifying us as the origin of +the Software, you have no right under these Terms and Conditions to use our +trademarks, trade names, service marks or product names. + +## Grant of Future License + +We hereby irrevocably grant you an additional license to use the Software under +the Apache License, Version 2.0 that is effective on the second anniversary of +the date we make the Software available. On or after that date, you may use the +Software under the Apache License, Version 2.0, in which case the following +will apply: + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..da94511 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +default: format check + +target/x86_64-unknown-linux-gnu/release/trail: + RUSTFLAGS="-C target-feature=+crt-static" cargo build --target x86_64-unknown-linux-gnu --release --bin trail + +format: + pnpm -r format; \ + cargo +nightly fmt; \ + dart format client/trailbase-dart/ examples/blog/flutter/; \ + txtpbfmt `find . -regex ".*.textproto"` + +check: + pnpm -r check; \ + cargo clippy --workspace --no-deps; \ + dart analyze client/trailbase-dart examples/blog/flutter + +docker: + docker build . -t trailbase/trailbase + +.PHONY: default format check diff --git a/README.md b/README.md new file mode 100644 index 0000000..d214ea7 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# TrailBase + +A blazingly fast, single-file, and open-source server for your application with +type-safe restful APIs, auth, admin dashboard, etc. + +For more context, documentation, and an online live demo, check out our website +[trailbase.io](https://trailbase.io). + +## FAQ + +Check out our [website](https://trailbase.io/reference/faq/). + +## Project Structure + +This repository contains all components that make up TrailBase, as well as +tests, documentation and examples. +Only our [benchmarks](https://github.com/trailbaseio/trailbase-benchmark) are +kept separately due to their external dependencies. + +## Building + +If you have all the necessary build dependencies (rust, nodejs, pnpm, ...) +installed, you can simply build TrailBase by running: + +```bash +$ git submodule update --init --recursive +$ cargo build +``` + +Alternatively, you can build with docker: + +```bash +$ git submodule update --init --recursive +$ docker build . -t trailbase +``` + +## Contributing + +Contributions are very welcome, let's just talk upfront to see how a proposal +fits into the overall roadmap and avoid any surprises. diff --git a/assets/colors.svg b/assets/colors.svg new file mode 100644 index 0000000..091a750 --- /dev/null +++ b/assets/colors.svg @@ -0,0 +1,341 @@ + + + + + + + + + Accent + gray + + + 200 + 600 + 900 + 950 + + + + + 400 + + + + 100 + + + + + + 200 + 300 + 400 + 500 + 700 + + + + 800 + 900 + + + diff --git a/assets/favicon.svg b/assets/favicon.svg new file mode 100644 index 0000000..d66cff3 --- /dev/null +++ b/assets/favicon.svg @@ -0,0 +1,85 @@ + + + + diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 0000000..afa8056 --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,191 @@ + + + + diff --git a/assets/logo_104.webp b/assets/logo_104.webp new file mode 100644 index 0000000000000000000000000000000000000000..ea2dbb9f2d90ba105200e7b4b57847ba5eacf7dd GIT binary patch literal 38344 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 z�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�g&@j1?L}c84S#uYvB=%vhcimag$dOQI_g7 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 literal 0 HcmV?d00001 diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 0000000..3de1249 --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,2 @@ +**/data/ +**/secrets/ diff --git a/client/testfixture/Makefile b/client/testfixture/Makefile new file mode 100644 index 0000000..114bbd5 --- /dev/null +++ b/client/testfixture/Makefile @@ -0,0 +1,4 @@ +clean: + rm -rf data/ uploads/ + +.PHONY: clean diff --git a/client/testfixture/config.textproto b/client/testfixture/config.textproto new file mode 100644 index 0000000..17a3eb7 --- /dev/null +++ b/client/testfixture/config.textproto @@ -0,0 +1,63 @@ +# Auto-generated config.Config textproto +email {} +server { + application_name: "TrailBase" + site_url: "http://localhost:4000" + logs_retention_sec: 604800 +} +auth {} +record_apis: [ + { + name: "_user_avatar" + table_name: "_user_avatar" + conflict_resolution: REPLACE + autofill_missing_user_id_columns: true + acl_world: [READ] + acl_authenticated: [CREATE, READ, UPDATE, DELETE] + create_access_rule: "_REQ_.user IS NULL OR _REQ_.user = _USER_.id" + update_access_rule: "_ROW_.user = _USER_.id" + delete_access_rule: "_ROW_.user = _USER_.id" + }, + { + name: "simple_strict_table" + table_name: "simple_strict_table" + acl_authenticated: [CREATE, READ, UPDATE, DELETE] + }, + { + name: "simple_complete_view" + table_name: "simple_complete_view" + acl_authenticated: [CREATE, READ, UPDATE, DELETE] + }, + { + name: "simple_subset_view" + table_name: "simple_subset_view" + acl_authenticated: [CREATE, READ, UPDATE, DELETE] + } +] +query_apis: [ + { + name: "simple_query_api" + virtual_table_name: "simple_query_api" + params: [ + { + name: "number" + type: INTEGER + } + ] + acl: WORLD + } +] +schemas: [ + { + name: "simple_schema" + schema: + "{" + " \"type\": \"object\"," + " \"properties\": {" + " \"name\": { \"type\": \"string\" }," + " \"obj\": { \"type\": \"object\" }" + " }," + " \"required\": [\"name\"]" + "}" + } +] diff --git a/client/testfixture/migrations/U1725019360__create_admin_user.sql b/client/testfixture/migrations/U1725019360__create_admin_user.sql new file mode 100644 index 0000000..8d97b06 --- /dev/null +++ b/client/testfixture/migrations/U1725019360__create_admin_user.sql @@ -0,0 +1,4 @@ +INSERT INTO _user + (id, email, password_hash, verified, admin) +VALUES + (uuid_v7(), 'admin@localhost', (hash_password('secret')), TRUE, TRUE); diff --git a/client/testfixture/migrations/U1725019361__add_users.sql b/client/testfixture/migrations/U1725019361__add_users.sql new file mode 100644 index 0000000..462e098 --- /dev/null +++ b/client/testfixture/migrations/U1725019361__add_users.sql @@ -0,0 +1,16 @@ +-- Add a a few non-admin users. +INSERT INTO _user (id, email, password_hash, verified) +VALUES + (uuid_v7(), '0@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '1@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '2@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '3@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '4@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '5@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '6@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '7@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '8@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '9@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '10@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '11@localhost', (hash_password('secret')), TRUE), + (uuid_v7(), '12@localhost', (hash_password('secret')), TRUE); diff --git a/client/testfixture/migrations/U1727439999__create_simple_strict_table.sql b/client/testfixture/migrations/U1727439999__create_simple_strict_table.sql new file mode 100644 index 0000000..a5304d2 --- /dev/null +++ b/client/testfixture/migrations/U1727439999__create_simple_strict_table.sql @@ -0,0 +1,69 @@ +-- Create a canonical table satisfying API requirements. +CREATE TABLE simple_strict_table ( + id BLOB PRIMARY KEY CHECK (is_uuid_v7(id)) DEFAULT (uuid_v7()) NOT NULL, + + text_null TEXT, + text_default TEXT DEFAULT '', + text_not_null TEXT NOT NULL DEFAULT '', + + int_null INTEGER, + int_default INTEGER DEFAULT 5, + int_not_null INTEGER NOT NULL DEFAULT 7, + + real_null REAL, + real_default REAL DEFAULT 5.1, + real_not_null REAL NOT NULL DEFAULT 7.1, + + blob_null BLOB, + blob_default BLOB DEFAULT X'AABBCCDD', + blob_not_null BLOB NOT NULL DEFAULT X'AABBCCDD' +) STRICT; + + +-- Create a variety of views. +CREATE VIEW simple_complete_view AS SELECT * FROM simple_strict_table; +CREATE VIEW simple_subset_view AS SELECT id, text_null AS t_null, text_default AS t_default, text_not_null AS t_not_null FROM simple_strict_table; +CREATE VIEW simple_subset_wo_id_view AS SELECT text_null, text_default, text_not_null FROM simple_strict_table; +CREATE VIEW simple_filter_view AS SELECT * FROM simple_strict_table WHERE (int_not_null % 2) = 0; + + +INSERT INTO simple_strict_table + (text_default, text_not_null, int_default, int_not_null, real_default, real_not_null, blob_default, blob_not_null) +VALUES + ('1', '1', 1, 1, 1.1, 1.2, X'01', X'01'), + ('2', '2', 2, 2, 2.1, 2.2, X'02', X'02'), + ('3', '3', 3, 3, 3.1, 3.2, X'03', X'03'), + ('4', '4', 4, 4, 4.1, 4.2, X'04', X'04'), + ('5', '5', 5, 5, 5.1, 5.2, X'05', X'05'), + ('6', '6', 6, 6, 6.1, 6.2, X'06', X'06'), + ('7', '7', 7, 7, 7.1, 7.2, X'07', X'07'), + ('8', '8', 8, 8, 8.1, 8.2, X'08', X'08'), + ('9', '9', 9, 9, 9.1, 9.2, X'09', X'09'), + ('10', '10', 10, 10, 10.1, 10.2, X'0A', X'0A'), + ('11', '11', 11, 11, 11.1, 11.2, X'0B', X'0B'), + ('12', '12', 12, 12, 12.1, 12.2, X'0C', X'0C'), + ('13', '13', 13, 13, 13.1, 13.2, X'0D', X'0D'), + ('14', '14', 14, 14, 14.1, 14.2, X'0E', X'0E'), + ('15', '15', 15, 15, 15.1, 15.2, X'0F', X'0F'), + ('16', '16', 16, 16, 16.1, 16.2, X'10', X'10'), + ('17', '17', 17, 17, 17.1, 17.2, X'11', X'11'), + ('18', '18', 18, 18, 18.1, 18.2, X'12', X'12'), + ('19', '19', 19, 19, 19.1, 19.2, X'13', X'13'), + ('20', '20', 20, 20, 20.1, 20.2, X'14', X'14'), + ('21', '21', 21, 21, 21.1, 21.2, X'15', X'15'); + +CREATE TABLE simple_strict_table_int ( + id INTEGER PRIMARY KEY, + + text_null TEXT, + blob_null BLOB, + int_null INTEGER, + real_null REAL, + any_col ANY +) STRICT; + +INSERT INTO simple_strict_table_int (id, text_null, blob_null, int_null, real_null, any_col) +VALUES + (NULL, '1', X'01', 1, 1.1, 'one'), + (NULL, '2', X'02', 2, 2.2, 2), + (NULL, '3', X'03', 3, 3.3, 3.3); diff --git a/client/testfixture/migrations/U1727956148__create_more_tables.sql b/client/testfixture/migrations/U1727956148__create_more_tables.sql new file mode 100644 index 0000000..a699066 --- /dev/null +++ b/client/testfixture/migrations/U1727956148__create_more_tables.sql @@ -0,0 +1,31 @@ +-- Create a table that doesn't satisfy record API requirements and uses +-- "affinity names" rather than strict storage types. +CREATE TABLE non_strict_table ( + id INTEGER PRIMARY KEY NOT NULL, + + tinyint_col TINYINT, + bigint_col BIGINT, + + varchar_col VARCHAR(64), + double_col DOUBLE, + float_col FLOAT, + + boolean_col BOOLEAN, + date_col DATE, + datetime_col DATETIME +); + +INSERT INTO non_strict_table + (id, tinyint_col, bigint_col, varchar_col, double_col, float_col, boolean_col, date_col, datetime_col) +VALUES + (0, 5, 64, 'varchar', 5.2, 2.4, FALSE, UNIXEPOCH(), UNIXEPOCH()), + (1, 5, 64, 'varchar', 5.2, 2.4, FALSE, UNIXEPOCH(), UNIXEPOCH()), + (2, 5, 64, 'varchar', 5.2, 2.4, FALSE, UNIXEPOCH(), UNIXEPOCH()), + (NULL, 5, 64, 'varchar', 5.2, 2.4, FALSE, UNIXEPOCH(), UNIXEPOCH()); + +CREATE TABLE non_strict_autoincrement_table ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + int4_col INT4 +); + +INSERT INTO non_strict_autoincrement_table (int4_col) VALUES (12); diff --git a/client/testfixture/migrations/U1728458183__create_virtual_table.sql b/client/testfixture/migrations/U1728458183__create_virtual_table.sql new file mode 100644 index 0000000..2cda4ca --- /dev/null +++ b/client/testfixture/migrations/U1728458183__create_virtual_table.sql @@ -0,0 +1,51 @@ +-- Create a virtual R-star table backed by physical, shadow tables. +-- +-- NOTE: The column types are here only for readability. rtree doesn't care. +CREATE VIRTUAL TABLE virtual_spatial_index USING rtree( + id INTEGER, + + -- Minimum and maximum X coordinate (rtree uses f32) + minX, + maxX, + + -- Minimum and maximum Y coordinate (rtree uses f32) + minY, + maxY, + + -- From the docs: + -- + -- "For auxiliary columns, only the name of the column matters. The type + -- affinity is ignored. Constraints such as NOT NULL, UNIQUE, REFERENCES, or + -- CHECK are also ignored. However, future versions of SQLite might start + -- paying attention to the type affinity and constraints, so users of + -- auxiliary columns are advised to leave both blank, to avoid future + -- compatibility problems." + +uuid BLOB +); + +-- 14 zipcodes near Charlotte, NC. Inspired by https://sqlite.org/rtree.html. +INSERT INTO virtual_spatial_index VALUES + (28215, -80.781227, -80.604706, 35.208813, 35.297367, uuid_v7()), + (28216, -80.957283, -80.840599, 35.235920, 35.367825, uuid_v7()), + (28217, -80.960869, -80.869431, 35.133682, 35.208233, uuid_v7()), + (28226, -80.878983, -80.778275, 35.060287, 35.154446, uuid_v7()), + (28227, -80.745544, -80.555382, 35.130215, 35.236916, uuid_v7()), + (28244, -80.844208, -80.841988, 35.223728, 35.225471, uuid_v7()), + (28262, -80.809074, -80.682938, 35.276207, 35.377747, uuid_v7()), + (28269, -80.851471, -80.735718, 35.272560, 35.407925, uuid_v7()), + (28270, -80.794983, -80.728966, 35.059872, 35.161823, uuid_v7()), + (28273, -80.994766, -80.875259, 35.074734, 35.172836, uuid_v7()), + (28277, -80.876793, -80.767586, 35.001709, 35.101063, uuid_v7()), + (28278, -81.058029, -80.956375, 35.044701, 35.223812, uuid_v7()), + (28280, -80.844208, -80.841972, 35.225468, 35.227203, uuid_v7()), + (28282, -80.846382, -80.844193, 35.223972, 35.225655, uuid_v7()); + +-- NOTE: define rejects mutating statements. +-- CREATE VIRTUAL TABLE virtual_spatial_index_writer USING define( +-- (INSERT INTO virtual_spatial_index VALUES ($1, $2, $3, $4, $5, uuid_v7()) RETURNING *)); + +-- Create a virtual table based on a stored procedure. +-- +-- This virtual table is also exposed as a Query API in the config. To see in +-- action browse to: http://localhost:4000/api/query/v1/simple_query_api?number=4. +CREATE VIRTUAL TABLE simple_query_api USING define((SELECT UNIXEPOCH() AS epoch, $1 AS random_number)); diff --git a/client/trailbase-dart/.gitignore b/client/trailbase-dart/.gitignore new file mode 100644 index 0000000..3cceda5 --- /dev/null +++ b/client/trailbase-dart/.gitignore @@ -0,0 +1,7 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ + +# Avoid committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock diff --git a/client/trailbase-dart/.pubignore b/client/trailbase-dart/.pubignore new file mode 100644 index 0000000..6e3b0e5 --- /dev/null +++ b/client/trailbase-dart/.pubignore @@ -0,0 +1,2 @@ +test +analysis_options.yaml diff --git a/client/trailbase-dart/CHANGELOG.md b/client/trailbase-dart/CHANGELOG.md new file mode 100644 index 0000000..763ea3e --- /dev/null +++ b/client/trailbase-dart/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +## 0.1.0 + +### Features + +- Initial client release including support for authentication and record APIs. diff --git a/client/trailbase-dart/LICENSE b/client/trailbase-dart/LICENSE new file mode 120000 index 0000000..30cff74 --- /dev/null +++ b/client/trailbase-dart/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/client/trailbase-dart/README.md b/client/trailbase-dart/README.md new file mode 100644 index 0000000..b0baeab --- /dev/null +++ b/client/trailbase-dart/README.md @@ -0,0 +1,13 @@ +# TrailBase client library for Dart and Flutter + +TrailBase is a blazingly fast, single-file, and open-source server for your +application with type-safe restful APIs, auth, admin dashboard, etc. + +For more context, documentation, and an online live demo, check out our website +[trailbase.io](https://trailbase.io). + +This is the first-party client for hooking up your Flutter or Dart applications +with your TrailBase server. +While working on documentation, an example setup can be found under +[`/examples/blog/flutter`](https://github.com/trailbaseio/trailbase/tree/main/examples/blog/flutter) +in the repository. diff --git a/client/trailbase-dart/analysis_options.yaml b/client/trailbase-dart/analysis_options.yaml new file mode 100644 index 0000000..fed045e --- /dev/null +++ b/client/trailbase-dart/analysis_options.yaml @@ -0,0 +1,31 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:lints/recommended.yaml + +linter: + rules: + prefer_single_quotes: true + unnecessary_brace_in_string_interps: false + unawaited_futures: true + sort_child_properties_last: false + +# analyzer: +# exclude: +# - path/to/excluded/files/** + +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/client/trailbase-dart/lib/src/client.dart b/client/trailbase-dart/lib/src/client.dart new file mode 100644 index 0000000..8c69d8a --- /dev/null +++ b/client/trailbase-dart/lib/src/client.dart @@ -0,0 +1,548 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:jwt_decoder/jwt_decoder.dart'; +import 'package:logging/logging.dart'; +import 'package:dio/dio.dart' as dio; + +class User { + final String id; + final String email; + + const User({ + required this.id, + required this.email, + }); + + User.fromJson(Map json) + : id = json['id'], + email = json['email']; + + @override + String toString() => 'User(id=${id}, email=${email})'; +} + +class Tokens { + final String auth; + final String? refresh; + final String? csrf; + + const Tokens(this.auth, this.refresh, this.csrf); + + Tokens.fromJson(Map json) + : auth = json['auth_token'], + refresh = json['refresh_token'], + csrf = json['csrf_token']; + + Map toJson() => { + 'auth_token': auth, + 'refresh_token': refresh, + 'csrf_token': csrf, + }; + + @override + String toString() => 'Tokens(${auth}, ${refresh}, ${csrf})'; +} + +class JwtToken { + final String sub; + final int iat; + final int exp; + final String email; + final String csrfToken; + + const JwtToken({ + required this.sub, + required this.iat, + required this.exp, + required this.email, + required this.csrfToken, + }); + + JwtToken.fromJson(Map json) + : sub = json['sub'], + iat = json['iat'], + exp = json['exp'], + email = json['email'], + csrfToken = json['csrf_token']; +} + +class _TokenState { + final (Tokens, JwtToken)? state; + final Map headers; + + const _TokenState(this.state, this.headers); + + static _TokenState build(Tokens? tokens) { + return _TokenState( + tokens != null + ? (tokens, JwtToken.fromJson(JwtDecoder.decode(tokens.auth))) + : null, + buildHeaders(tokens), + ); + } +} + +class Pagination { + final String? cursor; + final int? limit; + + const Pagination({ + required this.cursor, + required this.limit, + }); +} + +class RecordId { + @override + String toString(); + + factory RecordId.integer(int id) => _IntegerRecordId(id); + factory RecordId.uuid(String id) => _UuidRecordId(id); +} + +class _ResponseRecordId implements RecordId { + final String id; + + const _ResponseRecordId(this.id); + + _ResponseRecordId.fromJson(Map json) : id = json['id']; + + int integer() => int.parse(id); + Uint8List uuid() => base64Decode(id); + + @override + String toString() => id; + + @override + bool operator ==(Object other) { + if (other is _ResponseRecordId) return id == other.id; + + if (other is int) return int.tryParse(id) == other; + if (other is _IntegerRecordId) return int.tryParse(id) == other.id; + if (other is String) return id == other; + if (other is _UuidRecordId) return id == other.id; + + return false; + } + + @override + int get hashCode => id.hashCode; +} + +class _IntegerRecordId implements RecordId { + final int id; + + const _IntegerRecordId(this.id); + + @override + String toString() => id.toString(); + + @override + bool operator ==(Object other) { + if (other is _IntegerRecordId) return id == other.id; + if (other is int) return id == other; + if (other is _ResponseRecordId) return id == int.tryParse(other.id); + return false; + } + + @override + int get hashCode => id.hashCode; +} + +extension RecordIdExtInt on int { + RecordId id() => _IntegerRecordId(this); +} + +class _UuidRecordId implements RecordId { + final String id; + + const _UuidRecordId(this.id); + + @override + String toString() => id; + + @override + bool operator ==(Object other) { + if (other is _UuidRecordId) return id == other.id; + if (other is String) return id == other; + if (other is _ResponseRecordId) return id == other.id; + return false; + } + + @override + int get hashCode => id.hashCode; +} + +extension RecordIdExtString on String { + RecordId id() => _UuidRecordId(this); +} + +class RecordApi { + static const String _recordApi = 'api/records/v1'; + + final String _name; + final Client _client; + + const RecordApi(this._client, this._name); + + Future>> list({ + Pagination? pagination, + List? order, + List? filters, + }) async { + final params = {}; + if (pagination != null) { + final cursor = pagination.cursor; + if (cursor != null) params['cursor'] = cursor; + + final limit = pagination.limit; + if (limit != null) params['limit'] = limit.toString(); + } + + if (order != null) params['order'] = order.join(','); + + if (filters != null) { + for (final filter in filters) { + final (nameOp, value) = splitOnce(filter, '='); + if (value == null) { + throw Exception( + 'Filter "${filter}" does not match: "name[op]=value"'); + } + params[nameOp] = value; + } + } + + final response = await _client.fetch( + '${RecordApi._recordApi}/${_name}', + queryParams: params, + ); + + return (response.data as List).cast>(); + } + + Future> read(RecordId id) async { + final response = await _client.fetch( + '${RecordApi._recordApi}/${_name}/${id}', + ); + return response.data; + } + + Future create(Map record) async { + final response = await _client.fetch( + '${RecordApi._recordApi}/${_name}', + method: 'POST', + data: record, + ); + + if ((response.statusCode ?? 400) > 200) { + throw Exception('${response.data} ${response.statusMessage}'); + } + return _ResponseRecordId.fromJson(response.data); + } + + Future update( + RecordId id, + Map record, + ) async { + await _client.fetch( + '${RecordApi._recordApi}/${_name}/${id}', + method: 'PATCH', + data: record, + ); + } + + Future delete(RecordId id) async { + await _client.fetch( + '${RecordApi._recordApi}/${_name}/${id}', + method: 'DELETE', + ); + } + + Uri imageUri(RecordId id, String colName, {int? index}) { + if (index != null) { + return Uri.parse( + '${_client.site()}/${RecordApi._recordApi}/${_name}/${id}/file/${colName}/${index}'); + } + return Uri.parse( + '${_client.site()}/${RecordApi._recordApi}/${_name}/${id}/file/${colName}'); + } +} + +class _ThinClient { + static final _dio = dio.Dio(); + + final String site; + + const _ThinClient(this.site); + + Future fetch( + String path, + _TokenState tokenState, { + Object? data, + String? method, + Map? queryParams, + }) async { + if (path.startsWith('/')) { + throw Exception('Path starts with "/". Relative path expected.'); + } + + final response = await _dio.request( + '${site}/${path}', + data: data, + queryParameters: queryParams, + options: dio.Options( + method: method, + headers: tokenState.headers, + validateStatus: (int? status) => true, + ), + ); + + return response; + } +} + +class Client { + static const String _authApi = 'api/auth/v1'; + + final _ThinClient _client; + final String _site; + _TokenState _tokenState; + final void Function(Client, Tokens?)? _authChange; + + Client._( + String site, { + Tokens? tokens, + void Function(Client, Tokens?)? onAuthChange, + }) : _client = _ThinClient(site), + _site = site, + _tokenState = _TokenState.build(tokens), + _authChange = onAuthChange; + + Client( + String site, { + void Function(Client, Tokens?)? onAuthChange, + }) : this._(site, onAuthChange: onAuthChange); + + static Future withTokens(String site, Tokens tokens, + {void Function(Client, Tokens?)? onAuthChange}) async { + final client = Client(site, onAuthChange: onAuthChange); + + try { + final statusResponse = await client._client + .fetch('${_authApi}/status', _TokenState.build(tokens)); + final Map response = statusResponse.data; + + final newTokens = Tokens( + response['auth_token'], + tokens.refresh, + response['csrf_token'], + ); + client._tokenState = _TokenState.build(newTokens); + client._authChange?.call(client, newTokens); + } catch (err) { + // Do nothing + } + + return client; + } + + /// Access to the raw tokens, can be used to persist login state. + Tokens? tokens() => _tokenState.state?.$1; + User? user() { + final authToken = tokens()?.auth; + if (authToken != null) { + return User.fromJson(JwtDecoder.decode(authToken)['user']); + } + return null; + } + + String site() => _site; + + RecordApi records(String name) => RecordApi(this, name); + + _TokenState _updateTokens(Tokens? tokens) { + final state = _TokenState.build(tokens); + + _tokenState = state; + _authChange?.call(this, state.state?.$1); + + final claims = state.state?.$2; + if (claims != null) { + final now = DateTime.now().millisecondsSinceEpoch / 1000; + if (claims.exp < now) { + _logger.warning('Token expired'); + } + } + + return state; + } + + Future login(String email, String password) async { + final response = await fetch( + '${_authApi}/login', + method: 'POST', + data: { + 'email': email, + 'password': password, + }, + ); + + final Map json = response.data; + final tokens = Tokens( + json['auth_token']!, + json['refresh_token'], + json['csrf_token'], + ); + + _updateTokens(tokens); + return tokens; + } + + Future loginWithAuthCode( + String authCode, { + String? pkceCodeVerifier, + }) async { + final response = await fetch( + '${Client._authApi}/token', + method: 'POST', + data: { + 'authorization_code': authCode, + 'pkce_code_verifier': pkceCodeVerifier, + }, + ); + + final Map tokenResponse = await response.data; + final tokens = Tokens( + tokenResponse['auth_token']!, + tokenResponse['refresh_token']!, + tokenResponse['csrf_token'], + ); + + _updateTokens(tokens); + return tokens; + } + + Future logout() async { + final refreshToken = _tokenState.state?.$1.refresh; + try { + if (refreshToken != null) { + await fetch('${_authApi}/logout', method: 'POST', data: { + 'refresh_token': refreshToken, + }); + } else { + await fetch('${_authApi}/logout'); + } + } catch (err) { + _logger.warning(err); + } + _updateTokens(null); + return true; + } + + Future deleteUser() async { + await fetch('${Client._authApi}/delete'); + _updateTokens(null); + } + + Future changeEmail(String email) async { + await fetch( + '${Client._authApi}/change_email', + method: 'POST', + data: { + 'new_email': email, + }, + ); + } + + Future refreshAuthToken() async { + final refreshToken = _shouldRefresh(_tokenState); + if (refreshToken != null) { + _tokenState = await _refreshTokensImpl(refreshToken); + } + } + + Future<_TokenState> _refreshTokensImpl(String refreshToken) async { + final response = await _client.fetch( + '${_authApi}/refresh', + _tokenState, + method: 'POST', + data: { + 'refresh_token': refreshToken, + }, + ); + + final Map tokenResponse = await response.data; + return _TokenState.build(Tokens( + tokenResponse['auth_token']!, + refreshToken, + tokenResponse['csrf_token'], + )); + } + + static String? _shouldRefresh(_TokenState tokenState) { + final state = tokenState.state; + final now = DateTime.now().millisecondsSinceEpoch / 1000; + if (state != null && state.$2.exp - 60 < now) { + return state.$1.refresh; + } + return null; + } + + Future fetch( + String path, { + bool? throwOnError, + Object? data, + String? method, + Map? queryParams, + }) async { + var tokenState = _tokenState; + final refreshToken = _shouldRefresh(tokenState); + if (refreshToken != null) { + tokenState = _tokenState = await _refreshTokensImpl(refreshToken); + } + + final response = await _client.fetch(path, tokenState, + data: data, method: method, queryParams: queryParams); + + if (response.statusCode != 200 && (throwOnError ?? true)) { + final errMsg = await response.data; + throw Exception( + '[${response.statusCode}] ${response.statusMessage}}: ${errMsg}'); + } + + return response; + } +} + +Map buildHeaders(Tokens? tokens) { + final Map base = { + 'Content-Type': 'application/json', + }; + + if (tokens != null) { + base['Authorization'] = 'Bearer ${tokens.auth}'; + + final refresh = tokens.refresh; + if (refresh != null) { + base['Refresh-Token'] = refresh; + } + + final csrf = tokens.csrf; + if (csrf != null) { + base['CSRF-Token'] = csrf; + } + } + + return base; +} + +(String, String?) splitOnce(String s, Pattern pattern) { + final int idx = s.indexOf(pattern); + if (idx < 0) { + return (s, null); + } + return (s.substring(0, idx), s.substring(idx + 1)); +} + +final _logger = Logger('trailbase'); diff --git a/client/trailbase-dart/lib/src/pkce.dart b/client/trailbase-dart/lib/src/pkce.dart new file mode 100644 index 0000000..2f98fce --- /dev/null +++ b/client/trailbase-dart/lib/src/pkce.dart @@ -0,0 +1,42 @@ +import 'dart:convert'; +import 'dart:math'; + +import 'package:crypto/crypto.dart'; + +/// A pair of (pkceCodeVerifier, pkceCodeChallenge). +typedef PkcePair = ({ + /// The random code verifier. + String verifier, + + /// The code challenge, computed as base64UrlNoPad(sha256(verifier)). + String challenge +}); + +extension Pkce on PkcePair { + /// Generates a [PkcePair]. + /// + /// [length] is the length used to generate the [verifier]. It must be + /// between 32 and 96, inclusive, which corresponds to a [verifier] of + /// length between 43 and 128, inclusive. The spec recommends a length of 32. + static PkcePair generate({int length = 32}) { + if (length < 32 || length > 96) { + throw ArgumentError.value( + length, + 'length', + 'The length must be between 32 and 96, inclusive.', + ); + } + + final random = Random.secure(); + final verifier = + base64UrlEncode(List.generate(length, (_) => random.nextInt(256))) + .split('=') + .first; + final challenge = + base64UrlEncode(sha256.convert(ascii.encode(verifier)).bytes) + .split('=') + .first; + + return (verifier: verifier, challenge: challenge); + } +} diff --git a/client/trailbase-dart/lib/trailbase.dart b/client/trailbase-dart/lib/trailbase.dart new file mode 100644 index 0000000..06a947f --- /dev/null +++ b/client/trailbase-dart/lib/trailbase.dart @@ -0,0 +1,4 @@ +library; + +export 'src/client.dart'; +export 'src/pkce.dart'; diff --git a/client/trailbase-dart/pubspec.yaml b/client/trailbase-dart/pubspec.yaml new file mode 100644 index 0000000..9d7a338 --- /dev/null +++ b/client/trailbase-dart/pubspec.yaml @@ -0,0 +1,18 @@ +name: trailbase +description: Thing client library for TrailBase. +homepage: https://trailbase.io +repository: https://github.com/trailbaseio/trailbase +version: 0.1.0 + +environment: + sdk: ^3.5.3 + +dependencies: + crypto: ^3.0.5 + dio: ^5.7.0 + jwt_decoder: ^2.0.1 + logging: ^1.2.0 + +dev_dependencies: + lints: ^5.0.0 + test: ^1.24.0 diff --git a/client/trailbase-dart/test/trailbase_test.dart b/client/trailbase-dart/test/trailbase_test.dart new file mode 100644 index 0000000..0462e45 --- /dev/null +++ b/client/trailbase-dart/test/trailbase_test.dart @@ -0,0 +1,140 @@ +import 'dart:io'; + +import 'package:trailbase/trailbase.dart'; +import 'package:test/test.dart'; +import 'package:dio/dio.dart'; + +const port = 4006; + +class SimpleStrict { + final String id; + + final String? textNull; + final String? textDefault; + final String textNotNull; + + SimpleStrict.fromJson(Map json) + : id = json['id'], + textNull = json['text_null'], + textDefault = json['text_default'], + textNotNull = json['text_not_null']; +} + +Future connect() async { + final client = Client('http://127.0.0.1:${port}'); + await client.login('admin@localhost', 'secret'); + return client; +} + +Future initTrailBase() async { + final result = await Process.run('cargo', ['build']); + if (result.exitCode > 0) { + throw Exception( + 'Cargo build failed.\n\nstdout: ${result.stdout}}\n\nstderr: ${result.stderr}}\n'); + } + final process = await Process.start('cargo', [ + 'run', + '--', + '--data-dir', + '../testfixture', + 'run', + '--dev', + '-a', + '127.0.0.1:${port}', + ]); + + final dio = Dio(); + for (int i = 0; i < 50; ++i) { + try { + final response = await dio.fetch( + RequestOptions(path: 'http://127.0.0.1:${port}/api/healthcheck')); + if (response.statusCode == 200) { + return process; + } + } catch (err) { + print('Trying to connect to TrailBase'); + } + + await Future.delayed(Duration(milliseconds: 500)); + } + + process.kill(ProcessSignal.sigkill); + final exitCode = await process.exitCode; + + await process.stdout.forEach(print); + await process.stderr.forEach(print); + throw Exception('Cargo run failed: ${exitCode}.'); +} + +Future main() async { + if (!Directory.current.path.endsWith('trailbase-dart')) { + throw Exception('Unexpected working directory'); + } + + await initTrailBase(); + + group('client tests', () { + test('auth', () async { + final client = await connect(); + + final oldTokens = client.tokens(); + expect(oldTokens, isNotNull); + + // We need to wait a little to push the expiry time in seconds to avoid just getting the same token minted again. + await Future.delayed(Duration(milliseconds: 1500)); + + await client.refreshAuthToken(); + final newTokens = client.tokens(); + expect(newTokens, isNot(equals(oldTokens!.auth))); + }); + + test('records', () async { + final client = await connect(); + final api = client.records('simple_strict_table'); + + final int now = DateTime.now().millisecondsSinceEpoch ~/ 1000; + final messages = [ + 'dart client test 0: ${now}', + 'dart client test 1: ${now}', + ]; + final ids = []; + for (final msg in messages) { + ids.add(await api.create({'text_not_null': msg})); + } + + { + final records = await api.list( + filters: ['text_not_null=${messages[0]}'], + ); + expect(records.length, 1); + expect(records[0]['text_not_null'], messages[0]); + } + + { + final recordsAsc = await api.list( + order: ['+text_not_null'], + filters: ['text_not_null[like]=%${now}'], + ); + expect(recordsAsc.map((el) => el['text_not_null']), + orderedEquals(messages)); + + final recordsDesc = await api.list( + order: ['-text_not_null'], + filters: ['text_not_null[like]=%${now}'], + ); + expect(recordsDesc.map((el) => el['text_not_null']).toList().reversed, + orderedEquals(messages)); + } + + final record = SimpleStrict.fromJson(await api.read(ids[0])); + + expect(ids[0] == record.id, isTrue); + // Note: the .id() is needed otherwise we call String's operator==. It's not ideal + // but we didn't come up with a better option. + expect(record.id.id() == ids[0], isTrue); + expect(RecordId.uuid(record.id) == ids[0], isTrue); + + expect(record.textNotNull, messages[0]); + }); + }); +} diff --git a/client/trailbase-ts/.gitignore b/client/trailbase-ts/.gitignore new file mode 100644 index 0000000..b947077 --- /dev/null +++ b/client/trailbase-ts/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ diff --git a/client/trailbase-ts/eslint.config.mjs b/client/trailbase-ts/eslint.config.mjs new file mode 100644 index 0000000..c1105f9 --- /dev/null +++ b/client/trailbase-ts/eslint.config.mjs @@ -0,0 +1,30 @@ +import globals from "globals"; +import pluginJs from "@eslint/js"; +import tseslint from "typescript-eslint"; + +export default [ + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + ignores: ["dist/", "node_modules/"], + }, + { + files: ["**/*.{js,mjs,cjs,mts,ts,tsx,jsx}"], + rules: { + // https://typescript-eslint.io/rules/no-explicit-any/ + "@typescript-eslint/no-explicit-any": "warn", + // http://eslint.org/docs/rules/no-unused-vars + "@typescript-eslint/no-unused-vars": [ + "error", + { + vars: "all", + args: "after-used", + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + }, + ], + "no-empty": ["error", { allowEmptyCatch: true }], + }, + languageOptions: { globals: globals.browser }, + }, +]; diff --git a/client/trailbase-ts/package.json b/client/trailbase-ts/package.json new file mode 100644 index 0000000..3f5051c --- /dev/null +++ b/client/trailbase-ts/package.json @@ -0,0 +1,53 @@ +{ + "name": "trailbase", + "version": "0.1.0", + "description": "Official TrailBase client", + "type": "module", + "main": "./src/index.ts", + "publishConfig": { + "access": "public", + "main": "./dist/client/trailbase-ts/src/index.js", + "types": "./dist/client/trailbase-ts/src/index.d.ts", + "exports": { + ".": { + "types": "./dist/client/trailbase-ts/src/index.d.ts", + "default": "./dist/client/trailbase-ts/src/index.js" + } + } + }, + "files": [ + "dist", + "package.json" + ], + "repository": { + "type": "git", + "url": "https://github.com/trailbaseio/trailbae.git", + "directory": "client/trailbase-ts" + }, + "homepage": "https://trailbase.io", + "scripts": { + "start": "tsc && node dist/client/trailbase-ts/src/index.js", + "build": "tsc", + "test": "vitest run && vite-node tests/integration_test_runner.ts", + "format": "prettier -w src tests", + "check": "tsc --noEmit --skipLibCheck && eslint" + }, + "devDependencies": { + "@eslint/js": "^9.13.0", + "eslint": "^9.13.0", + "execa": "^9.5.1", + "globals": "^15.11.0", + "http-status": "^2.0.0", + "jsdom": "^25.0.1", + "prettier": "^3.3.3", + "tinybench": "^3.0.0", + "typescript": "^5.6.3", + "typescript-eslint": "^8.12.1", + "vite-node": "^2.1.4", + "vitest": "^2.1.4" + }, + "dependencies": { + "jwt-decode": "^4.0.0", + "uuid": "^11.0.2" + } +} diff --git a/client/trailbase-ts/src/index.ts b/client/trailbase-ts/src/index.ts new file mode 100644 index 0000000..02ca8dc --- /dev/null +++ b/client/trailbase-ts/src/index.ts @@ -0,0 +1,531 @@ +import { jwtDecode } from "jwt-decode"; + +import type { ChangeEmailRequest } from "@bindings/ChangeEmailRequest"; +import type { LoginRequest } from "@bindings/LoginRequest"; +import type { LoginResponse } from "@bindings/LoginResponse"; +import type { LoginStatusResponse } from "@bindings/LoginStatusResponse"; +import type { LogoutRequest } from "@bindings/LogoutRequest"; +import type { RefreshRequest } from "@bindings/RefreshRequest"; +import type { RefreshResponse } from "@bindings/RefreshResponse"; + +export type User = { + id: string; + email: string; +}; + +export type Pagination = { + cursor?: string; + limit?: number; +}; + +export type Tokens = { + auth_token: string; + refresh_token: string | null; + csrf_token: string | null; +}; + +type TokenClaims = { + sub: string; + iat: number; + exp: number; + email: string; + csrf_token: string; +}; + +type TokenState = { + state?: { + tokens: Tokens; + claims: TokenClaims; + }; + headers: HeadersInit; +}; + +function buildTokenState(tokens?: Tokens): TokenState { + return { + state: tokens && { + tokens, + claims: jwtDecode(tokens.auth_token), + }, + headers: headers(tokens), + }; +} + +type FetchOptions = RequestInit & { + throwOnError?: boolean; +}; + +export class FetchError extends Error { + public status: number; + + constructor(status: number, msg: string) { + super(msg); + this.status = status; + } + + static async from(response: Response): Promise { + let body: string | undefined; + try { + body = await response.text(); + } catch {} + + console.warn(response); + + return new FetchError( + response.status, + body ? `${response.statusText}: ${body}` : response.statusText, + ); + } + + public isClient(): boolean { + return this.status >= 400 && this.status < 500; + } + + public isServer(): boolean { + return this.status >= 500; + } + + public toString(): string { + return `[${this.status}] ${this.message}`; + } +} + +export interface FileUpload { + content_type?: null | string; + filename?: null | string; + mime_type?: null | string; + objectstore_path: string; +} + +/// Provides CRUD access to records through TrailBase's record API. +/// +/// TODO: add file upload/download. +export class RecordApi { + private static readonly _recordApi = "api/records/v1"; + private readonly _createApi: string; + + constructor( + private readonly client: Client, + private readonly name: string, + ) { + this._createApi = `${RecordApi._recordApi}/${this.name}`; + } + + public async list>(opts?: { + pagination?: Pagination; + order?: string[]; + filters?: string[]; + }): Promise { + const params: [string, string][] = []; + const pagination = opts?.pagination; + if (pagination) { + const cursor = pagination.cursor; + if (cursor) params.push(["cursor", cursor]); + + const limit = pagination.limit; + if (limit) params.push(["limit", limit.toString()]); + } + const order = opts?.order; + if (order) params.push(["order", order.join(",")]); + + const filters = opts?.filters; + if (filters) { + for (const filter of filters) { + const [nameOp, value] = filter.split("=", 2); + if (value === undefined) { + throw Error(`Filter '${filter}' does not match: 'name[op]=value'`); + } + params.push([nameOp, value]); + } + } + + const queryParams = encodeURI( + params.map(([key, value]) => `${key}=${value}`).join("&"), + ); + const response = await this.client.fetch( + `${RecordApi._recordApi}/${this.name}?${queryParams}`, + ); + return (await response.json()) as T[]; + } + + public async read>( + id: string | number, + ): Promise { + const response = await this.client.fetch( + `${RecordApi._recordApi}/${this.name}/${id}`, + ); + return (await response.json()) as T; + } + + public async create>( + record: T, + ): Promise { + return this.client.fetch(this._createApi, { + method: "POST", + body: JSON.stringify(record), + }); + } + + public async createId>( + record: T, + ): Promise { + const response = await this.create(record); + return (await response.json()).id; + } + + public async update>( + id: string | number, + record: Partial, + ): Promise { + await this.client.fetch(`${RecordApi._recordApi}/${this.name}/${id}`, { + method: "PATCH", + body: JSON.stringify(record), + }); + } + + public async delete(id: string | number): Promise { + await this.client.fetch(`${RecordApi._recordApi}/${this.name}/${id}`, { + method: "DELETE", + }); + } + + public imageUri(id: string | number, colName: string): string { + return `${this.client.site}/${RecordApi._recordApi}/${this.name}/${id}/file/${colName}`; + } + + public imagesUri( + id: string | number, + colName: string, + index: number, + ): string { + return `${this.client.site}/${RecordApi._recordApi}/${this.name}/${id}/files/${colName}/${index}`; + } +} + +class ThinClient { + constructor(public readonly site: string) {} + + public async fetch( + path: string, + tokenState: TokenState, + init?: RequestInit, + ): Promise { + if (path.startsWith("/")) { + throw Error("Path starts with '/'. Relative path expected."); + } + + const response = await fetch(`${this.site}/${path}`, { + ...init, + credentials: isDev ? "include" : "same-origin", + headers: tokenState.headers, + }); + + return response; + } +} + +type ClientOptions = { + tokens?: Tokens; + onAuthChange?: (client: Client, user?: User) => void; +}; + +/// Client for interacting with TrailBase auth and record APIs. +/// +/// TODO: Add +/// * issue_password_reset_email +/// * issue_change_email +/// * status +export class Client { + private static readonly _authApi = "api/auth/v1"; + private static readonly _authUi = "_/auth"; + + private readonly _client: ThinClient; + private readonly _authChange: + | undefined + | ((client: Client, user?: User) => void); + private _tokenState: TokenState; + + constructor(site: string, opts?: ClientOptions) { + this._client = new ThinClient(site); + this._authChange = opts?.onAuthChange; + + this._tokenState = this.updateTokens(opts?.tokens); + } + + public static init(site: string, opts?: ClientOptions): Client { + return new Client(site, opts); + } + + public static async tryFromCookies( + site: string, + opts?: ClientOptions, + ): Promise { + const client = new Client(site, opts); + + // Prefer explicit tokens. When given, do not update/refresh infinite recursion + // with `($token) => Client` factories. + if (!client.tokens()) { + try { + const response = await client.fetch(`${Client._authApi}/status`); + const status: LoginStatusResponse = await response.json(); + + const authToken = status?.auth_token; + if (authToken) { + client.updateTokens({ + auth_token: authToken, + refresh_token: status.refresh_token, + csrf_token: status.csrf_token, + }); + } + } catch (err) { + console.debug("No valid cookies found: ", err); + } + } + + return client; + } + + private updateTokens(tokens?: Tokens): TokenState { + const state = buildTokenState(tokens); + + this._tokenState = state; + this._authChange?.(this, this.user()); + + const claims = state.state?.claims; + if (claims) { + const now = Date.now() / 1000; + if (claims.exp < now) { + console.warn("Token expired"); + } + } + + return state; + } + + public get site() { + return this._client.site; + } + + /// Low-level access to tokens (auth, refresh, csrf) useful for persisting them. + public tokens = (): Tokens | undefined => this._tokenState?.state?.tokens; + + /// Provides current user. + public user(): User | undefined { + const claims = this._tokenState.state?.claims; + if (claims) { + return { + id: claims.sub, + email: claims.email, + }; + } + } + public records = (name: string): RecordApi => new RecordApi(this, name); + + public async avatarUrl(): Promise { + const user = this.user(); + if (user) { + const response = await this.fetch(`${Client._authApi}/avatar/${user.id}`); + const json = (await response.json()) as { avatar_url: string }; + return json.avatar_url; + } + return undefined; + } + + public async login(email: string, password: string): Promise { + const response = await this.fetch(`${Client._authApi}/login`, { + method: "POST", + body: JSON.stringify({ + email: email, + password: password, + } as LoginRequest), + }); + + this.updateTokens((await response.json()) as LoginResponse); + } + + public loginUri(redirect?: string): string { + return `${this._client.site}/${Client._authUi}/login?${redirect ? `redirect_to=${redirect}` : ""}`; + } + + public async logout(): Promise { + try { + const refresh_token = this._tokenState.state?.tokens.refresh_token; + if (refresh_token) { + await this.fetch(`${Client._authApi}/logout`, { + method: "POST", + body: JSON.stringify({ + refresh_token, + } as LogoutRequest), + }); + } else { + await this.fetch(`${Client._authApi}/logout`); + } + } catch (err) { + console.warn(err); + } + this.updateTokens(undefined); + return true; + } + + public logoutUri(redirect?: string): string { + return `${this._client.site}/${Client._authApi}/logout?${redirect ? `redirect_to=${redirect}` : ""}`; + } + + public async deleteUser(): Promise { + await this.fetch(`${Client._authApi}/delete`); + this.updateTokens(undefined); + } + + public async changeEmail(email: string): Promise { + await this.fetch(`${Client._authApi}/change_email`, { + method: "POST", + body: JSON.stringify({ + new_email: email, + } as ChangeEmailRequest), + }); + } + + public async refreshAuthToken(): Promise { + const refreshToken = Client.shouldRefresh(this._tokenState); + if (refreshToken) { + this._tokenState = await this.refreshTokensImpl(refreshToken); + } + } + + /// Returns the refresh token if should refresh. + private static shouldRefresh(tokenState: TokenState): string | undefined { + const state = tokenState.state; + if (state && state.claims.exp - 60 < Date.now() / 1000) { + return state.tokens?.refresh_token ?? undefined; + } + } + + private async refreshTokensImpl(refreshToken: string): Promise { + const response = await this._client.fetch( + `${Client._authApi}/refresh`, + this._tokenState, + { + method: "POST", + body: JSON.stringify({ + refresh_token: refreshToken, + } as RefreshRequest), + }, + ); + + if (!response.ok) { + if (response.status === 401) { + this.logout(); + } + throw await FetchError.from(response); + } + + return buildTokenState({ + ...((await response.json()) as RefreshResponse), + refresh_token: refreshToken, + }); + } + + /// Fetches data from TrailBase endpoints, e.g.: + // const response = await client.fetch("api/auth/v1/status"); + // + // Unlike native fetch, will throw in case !response.ok. + public async fetch(path: string, init?: FetchOptions): Promise { + let tokenState = this._tokenState; + const refreshToken = Client.shouldRefresh(tokenState); + if (refreshToken) { + this._tokenState = tokenState = + await this.refreshTokensImpl(refreshToken); + } + + try { + const response = await this._client.fetch(path, tokenState, init); + if (!response.ok && (init?.throwOnError ?? true)) { + throw await FetchError.from(response); + } + return response; + } catch (err) { + if (err instanceof TypeError) { + throw Error(`Connection refused ${err}. TrailBase down or CORS?`); + } + throw err; + } + } +} + +function _isDev(): boolean { + type ImportMeta = { + env: object | undefined; + }; + const env = (import.meta as unknown as ImportMeta).env; + const key = "DEV" as keyof typeof env; + const isDev = env?.[key] ?? false; + + return isDev; +} +const isDev = _isDev(); + +export function headers(tokens?: Tokens): HeadersInit { + const base = { + "Content-Type": "application/json", + }; + + if (tokens) { + const { auth_token, refresh_token, csrf_token } = tokens; + return { + ...base, + ...(auth_token && { + Authorization: `Bearer ${auth_token}`, + }), + ...(refresh_token && { + "Refresh-Token": refresh_token, + }), + ...(csrf_token && { + "CSRF-Token": csrf_token, + }), + }; + } + + return base; +} + +export function textEncode(s: string): Uint8Array { + return new TextEncoder().encode(s); +} + +export function textDecode(ar: Uint8Array): string { + return new TextDecoder().decode(ar); +} + +/// Decode a base64 string to bytes. +export function base64Decode(base64: string): string { + return atob(base64); +} + +/// Decode a "url-safe" base64 string to bytes. +export function urlSafeBase64Decode(base64: string): string { + return base64Decode(base64.replace(/_/g, "/").replace(/-/g, "+")); +} + +/// Encode an arbitrary string input as base64 string. +export function base64Encode(s: string): string { + return btoa(s); +} + +/// Encode an arbitrary string input as a "url-safe" base64 string. +export function urlSafeBase64Encode(s: string): string { + return base64Encode(s).replace(/\//g, "_").replace(/\+/g, "-"); +} + +export function asyncBase64Encode(blob: Blob): Promise { + return new Promise((resolve, _) => { + const reader = new FileReader(); + reader.onloadend = () => resolve(reader.result as string); + reader.readAsDataURL(blob); + }); +} + +export const exportedForTesting = isDev + ? { + base64Decode, + base64Encode, + } + : undefined; diff --git a/client/trailbase-ts/tests/base64.test.ts b/client/trailbase-ts/tests/base64.test.ts new file mode 100644 index 0000000..517c946 --- /dev/null +++ b/client/trailbase-ts/tests/base64.test.ts @@ -0,0 +1,25 @@ +import { expect, test } from "vitest"; +import { + exportedForTesting, + urlSafeBase64Encode, + urlSafeBase64Decode, + textEncode, + textDecode, + asyncBase64Encode, +} from "../src/index"; + +const { base64Encode, base64Decode } = exportedForTesting!; + +test("encoding", async () => { + const input = ".,~`!@#$%^&*()_Hi!:)/|\\"; + + expect(textDecode(textEncode(input))).toBe(input); + expect(base64Decode(base64Encode(input))).toBe(input); + expect(urlSafeBase64Decode(urlSafeBase64Encode(input))).toBe(input); + + const blob = new Blob([textEncode(input)]); + const base64 = await asyncBase64Encode(blob); + const components = base64.split(","); + + expect(base64Decode(components[1])).toBe(input); +}); diff --git a/client/trailbase-ts/tests/encoding.bench.ts b/client/trailbase-ts/tests/encoding.bench.ts new file mode 100644 index 0000000..f7b9d4e --- /dev/null +++ b/client/trailbase-ts/tests/encoding.bench.ts @@ -0,0 +1,28 @@ +import { test } from "vitest"; +import { Bench } from "tinybench"; +import { + urlSafeBase64Encode, + urlSafeBase64Decode, + base64Encode, + base64Decode, +} from "../src/index"; + +test("encoding benchmark", async () => { + const bench = new Bench({ time: 500 }); + + const input = "!@#$%^&*(!@#$%^&*@".repeat(1000); + const standardInput = base64Encode(input); + const urlSafeInput = urlSafeBase64Encode(input); + + bench + .add("Url-Safe decode", () => { + urlSafeBase64Decode(urlSafeInput); + }) + .add("Standard decode", () => { + base64Decode(standardInput); + }); + + await bench.run(); + + console.table(bench.table()); +}); diff --git a/client/trailbase-ts/tests/integration/integration.test.ts b/client/trailbase-ts/tests/integration/integration.test.ts new file mode 100644 index 0000000..2f2d128 --- /dev/null +++ b/client/trailbase-ts/tests/integration/integration.test.ts @@ -0,0 +1,182 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions */ + +import { expect, test } from "vitest"; +import { Client, headers, urlSafeBase64Encode } from "../../src/index"; +import { status } from "http-status"; +import { v7 as uuidv7, parse as uuidParse } from "uuid"; + +test("headers", () => { + const h0 = headers(); + expect(Object.keys(h0).length).toBe(1); + const h1 = headers({ + auth_token: "foo", + refresh_token: "bar", + csrf_token: null, + }); + expect(Object.keys(h1).length).toBe(3); +}); + +type SimpleStrict = { + id: string; + + text_null?: string; + text_default?: string; + text_not_null: string; + + // Add or generate missing fields. +}; + +type NewSimpleStrict = Partial; + +type SimpleCompleteView = SimpleStrict; + +type SimpleSubsetView = { + id: string; + + t_null?: string; + t_default?: string; + t_not_null: string; +}; + +const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); +const port: number = 4005; + +async function connect(): Promise { + const client = Client.init(`http://127.0.0.1:${port}`); + await client.login("admin@localhost", "secret"); + return client; +} + +// WARN: this test is not hermetic. I requires an appropriate TrailBase instance to be running. +test("auth integration tests", async () => { + const client = await connect(); + + const oldTokens = client.tokens(); + expect(oldTokens).not.undefined; + + // We need to wait a little to push the expiry time in seconds to avoid just getting the same token minted again. + await sleep(1500); + + await client.refreshAuthToken(); + const newTokens = client.tokens(); + expect(newTokens).not.undefined.and.not.equals(oldTokens!.auth_token); + + expect(await client.logout()).toBe(true); + expect(client.user()).toBe(undefined); +}); + +test("Record integration tests", async () => { + const client = await connect(); + const api = client.records("simple_strict_table"); + + const now = new Date().getTime(); + const messages = [`ts client test 0: ${now}`, `ts client test 1: ${now}`]; + + const ids: string[] = []; + for (const msg of messages) { + ids.push( + (await api.createId({ text_not_null: msg })) as string, + ); + } + + { + const records = await api.list({ + filters: [`text_not_null=${messages[0]}`], + }); + expect(records.length).toBe(1); + expect(records[0].text_not_null).toBe(messages[0]); + } + + { + const records = await api.list({ + filters: [`text_not_null[like]=%${now}`], + order: ["+text_not_null"], + }); + expect(records.map((el) => el.text_not_null)).toStrictEqual(messages); + } + + { + const records = await api.list({ + filters: [`text_not_null[like]=%${now}`], + order: ["-text_not_null"], + }); + expect(records.map((el) => el.text_not_null).reverse()).toStrictEqual( + messages, + ); + } + + const record: SimpleStrict = await api.read(ids[0]); + expect(record.id).toStrictEqual(ids[0]); + expect(record.text_not_null).toStrictEqual(messages[0]); + + // Test 1:1 view-bases record API. + const view_record: SimpleCompleteView = await client + .records("simple_complete_view") + .read(ids[0]); + expect(view_record.id).toStrictEqual(ids[0]); + expect(view_record.text_not_null).toStrictEqual(messages[0]); + + // Test view-based record API with column renames. + const subset_view_record: SimpleSubsetView = await client + .records("simple_subset_view") + .read(ids[0]); + expect(subset_view_record.id).toStrictEqual(ids[0]); + expect(subset_view_record.t_not_null).toStrictEqual(messages[0]); + + const updated_value: Partial = { + text_not_null: "updated not null", + text_default: "updated default", + text_null: "updated null", + }; + await api.update(ids[1], updated_value); + const updated_record: SimpleStrict = await api.read(ids[1]); + expect(updated_record).toEqual( + expect.objectContaining({ + id: ids[1], + ...updated_value, + }), + ); + + await api.delete(ids[1]); + + expect(await client.logout()).toBe(true); + expect(client.user()).toBe(undefined); + + expect(async () => await api.read(ids[0])).rejects.toThrowError( + expect.objectContaining({ + status: status.FORBIDDEN, + }), + ); +}); + +test("record error tests", async () => { + const client = await connect(); + + const nonExistantId = urlSafeBase64Encode( + String.fromCharCode.apply(null, uuidParse(uuidv7())), + ); + const nonExistantApi = client.records("non-existant"); + expect( + async () => await nonExistantApi.read(nonExistantId), + ).rejects.toThrowError( + expect.objectContaining({ + status: status.METHOD_NOT_ALLOWED, + }), + ); + + const api = client.records("simple_strict_table"); + expect( + async () => await api.read("invalid id"), + ).rejects.toThrowError( + expect.objectContaining({ + status: status.BAD_REQUEST, + }), + ); + expect( + async () => await api.read(nonExistantId), + ).rejects.toThrowError( + expect.objectContaining({ + status: status.NOT_FOUND, + }), + ); +}); diff --git a/client/trailbase-ts/tests/integration_test_runner.ts b/client/trailbase-ts/tests/integration_test_runner.ts new file mode 100644 index 0000000..f5045b6 --- /dev/null +++ b/client/trailbase-ts/tests/integration_test_runner.ts @@ -0,0 +1,72 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { createVitest } from "vitest/node"; +import { cwd } from "node:process"; +import { execa, type Subprocess } from "execa"; + +const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); +const port: number = 4005; + +async function initTrailBase(): Promise<{ subprocess: Subprocess }> { + const pwd = cwd(); + if (!pwd.endsWith("trailbase-ts")) { + throw Error(`Unxpected CWD: ${pwd}`); + } + + const build = await execa`cargo build`; + if (build.failed) { + console.error("STDOUT:", build.stdout); + console.error("STDERR:", build.stderr); + throw Error("cargo build failed"); + } + + const subprocess = execa`cargo run -- --data-dir ../testfixture run --dev -a 127.0.0.1:${port}`; + + for (let i = 0; i < 50; ++i) { + if ((subprocess.exitCode ?? 0) > 0) { + break; + } + + try { + const response = await fetch(`http://127.0.0.1:${port}/api/healthcheck`); + if (response.ok) { + return { subprocess }; + } + + console.log(await response.text()); + } catch (err) { + console.info("Waiting for TrailBase to become healthy"); + } + + await sleep(500); + } + + subprocess.kill(); + + const result = await subprocess; + console.error("EXIT:", result.exitCode); + console.error("STDOUT:", result.stdout); + console.error("STDERR:", result.stderr); + + throw Error("Failed to start TrailBase"); +} + +const { subprocess } = await initTrailBase(); + +const ctx = await createVitest("test", { + watch: false, + environment: "jsdom", + include: ["tests/integration/*"], +}); +await ctx.start(); +await ctx.close(); + +if (subprocess.exitCode === null) { + // Still running + subprocess.kill(); +} else { + // Otherwise TrailBase terminated. Log output to provide a clue as to why. + const { stderr, stdout } = subprocess; + console.error(stdout); + console.error(stderr); +} diff --git a/client/trailbase-ts/tsconfig.json b/client/trailbase-ts/tsconfig.json new file mode 100644 index 0000000..ba76a1e --- /dev/null +++ b/client/trailbase-ts/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../ui/common/tsconfig.base.json", + "compilerOptions": { + "declaration": true, + "outDir": "./dist", + "paths": { + "@/*": ["./src/*"], + "@bindings/*": ["../../trailbase-core/bindings/*"] + } + }, + "include": [ + "./src/**/*" + ] +} diff --git a/client/trailbase-ts/vitest.config.ts b/client/trailbase-ts/vitest.config.ts new file mode 100644 index 0000000..06f1cb3 --- /dev/null +++ b/client/trailbase-ts/vitest.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + globals: true, + environment: "jsdom", + // We do not include transitively, since we rely on our own runner for + // executing tests/integration/** instead. + include: [ + 'tests/*.test.ts', + 'tests/*.bench.ts', + ], + }, +}) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..bce7e1f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +services: + + trail: + build: . + ports: + - "4000:4000" + restart: unless-stopped + volumes: + - ./traildepot:/app/traildepot + environment: + # Setup Rust's env-logger. + RUST_LOG: "info,refinery_core=warn" + RUST_BACKTRACE: "1" + command: "/app/trail --data-dir /app/traildepot run --address 0.0.0.0:4000" diff --git a/docs/.dockerignore b/docs/.dockerignore new file mode 100644 index 0000000..6c79c0e --- /dev/null +++ b/docs/.dockerignore @@ -0,0 +1,4 @@ +node_modules/ + +.git* +*.log diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..6240da8 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,21 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/docs/.prettierignore b/docs/.prettierignore new file mode 100644 index 0000000..c4bfc42 --- /dev/null +++ b/docs/.prettierignore @@ -0,0 +1,9 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock + +src/components/ui + +# Prettier breaks {/* */} comments in MDX files :/ +**/*.mdx diff --git a/docs/.prettierrc.mjs b/docs/.prettierrc.mjs new file mode 100644 index 0000000..85ccfb5 --- /dev/null +++ b/docs/.prettierrc.mjs @@ -0,0 +1,13 @@ +// .prettierrc.mjs +/** @type {import("prettier").Config} */ +export default { + plugins: ['prettier-plugin-astro'], + overrides: [ + { + files: '*.astro', + options: { + parser: 'astro', + }, + }, + ], +}; diff --git a/docs/Dockerfile b/docs/Dockerfile new file mode 100644 index 0000000..a5990a3 --- /dev/null +++ b/docs/Dockerfile @@ -0,0 +1,8 @@ +FROM nginx:mainline-alpine AS runner + +COPY ./nginx.conf /etc/nginx/conf.d/default.conf +COPY ./dist /usr/share/nginx/html + +EXPOSE 80 + +HEALTHCHECK CMD curl --fail http://localhost:80 || exit 1 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..e09bf55 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,55 @@ +# Starlight Starter Kit: Basics + +[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build) + +``` +npm create astro@latest -- --template starlight +``` + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/starlight/tree/main/examples/basics) +[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/withastro/starlight&create_from_path=examples/basics) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwithastro%2Fstarlight%2Ftree%2Fmain%2Fexamples%2Fbasics&project-name=my-starlight-docs&repository-name=my-starlight-docs) + +> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! + +## 🚀 Project Structure + +Inside of your Astro + Starlight project, you'll see the following folders and files: + +``` +. +├── public/ +├── src/ +│ ├── assets/ +│ ├── content/ +│ │ ├── docs/ +│ │ └── config.ts +│ └── env.d.ts +├── astro.config.mjs +├── package.json +└── tsconfig.json +``` + +Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name. + +Images can be added to `src/assets/` and embedded in Markdown with a relative link. + +Static assets, like favicons, can be placed in the `public/` directory. + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | +| `npm run astro -- --help` | Get help using the Astro CLI | + +## 👀 Want to learn more? + +Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat). diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs new file mode 100644 index 0000000..add3cfc --- /dev/null +++ b/docs/astro.config.mjs @@ -0,0 +1,68 @@ +import { defineConfig } from "astro/config"; + +import icon from "astro-icon"; +import robotsTxt from "astro-robots-txt"; +import sitemap from "@astrojs/sitemap"; +import solid from "@astrojs/solid-js"; +import starlight from "@astrojs/starlight"; +import tailwind from "@astrojs/tailwind"; + +// https://astro.build/config +export default defineConfig({ + site: "https://trailbase.io", + integrations: [ + icon(), + solid(), + starlight({ + title: "TrailBase", + customCss: ["./src/tailwind.css"], + social: { + github: "https://github.com/trailbaseio/trailbase", + discord: "https://discord.gg/X8cWs7YC22", + }, + sidebar: [ + { + label: "Getting Started", + items: [ + { + label: "Starting Up", + slug: "getting-started/starting-up", + }, + { + label: "First App", + slug: "getting-started/first-app", + }, + { + label: "Philosophy", + slug: "getting-started/philosophy", + }, + ], + }, + { + label: "Documentation", + autogenerate: { + directory: "documentation", + }, + }, + { + label: "Comparisons", + autogenerate: { + directory: "comparison", + }, + }, + { + label: "Reference", + autogenerate: { + directory: "reference", + }, + }, + ], + }), + sitemap(), + robotsTxt(), + tailwind({ + // Disable the default base styles: + applyBaseStyles: false, + }), + ], +}); diff --git a/docs/docker-compose.yml b/docs/docker-compose.yml new file mode 100644 index 0000000..819dd52 --- /dev/null +++ b/docs/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3.9" + +services: + trailbase-docs: + container_name: trailbase-docs + build: . + ports: + - "127.0.0.1:3036:80/tcp" + restart: unless-stopped + + # By default containers get 1024 cpu shares. Setting it to 512 means half + # the resources compared to a default container. And 2048 double, + # respectively. + cpu_shares: 1024 + mem_limit: 128m + oom_score_adj: -200 diff --git a/docs/nginx.conf b/docs/nginx.conf new file mode 100644 index 0000000..bc4af87 --- /dev/null +++ b/docs/nginx.conf @@ -0,0 +1,32 @@ +server { + # TLS termination is done by the reverse proxy. + listen 80; + listen [::]:80; + server_name trailbase_documentation; + + #access_log /var/log/nginx/host.access.log main; + + # File root matching build target location in Dockerfile. + root /usr/share/nginx/html; + + # 404 and 500s should load our custom error pages. + error_page 404 /404.html; + # error_page 500 502 503 504 /50x/index.html; + + location / { + # Set long client-side cache TTLs for astro assets. Astro assets carry a + # content hash in their filename, thus can be cached safely for ever. + location /_astro/ { + add_header Cache-Control "public, max-age=31536000, immutable"; + } + location /particles/ { + add_header Cache-Control "public, max-age=2592000, immutable"; + } + + # Try resolve $uri in the following order: + # * try $uri first + # * then $uri/index.html + # * finally fall back to 404 error_page below. + try_files $uri $uri/index.html =404; + } +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..bddf0b9 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,37 @@ +{ + "name": "", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro check && astro build", + "preview": "astro preview", + "astro": "astro", + "check": "astro check", + "format": "prettier -w tailwind.config.mjs astro.config.mjs src " + }, + "dependencies": { + "@astrojs/check": "^0.9.4", + "@astrojs/starlight": "^0.28.4", + "@astrojs/starlight-tailwind": "^2.0.3", + "@astrojs/tailwind": "^5.1.2", + "@iconify-json/tabler": "^1.2.6", + "astro": "^4.16.7", + "astro-icon": "^1.1.1", + "chart.js": "^4.4.6", + "chartjs-chart-error-bars": "^4.4.3", + "chartjs-plugin-deferred": "^2.0.0", + "sharp": "^0.33.5", + "solid-js": "^1.9.3", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3" + }, + "devDependencies": { + "@astrojs/sitemap": "^3.2.1", + "@astrojs/solid-js": "^4.4.2", + "astro-robots-txt": "^1.0.0", + "prettier": "^3.3.3", + "prettier-plugin-astro": "^0.14.1" + } +} diff --git a/docs/public/favicon.svg b/docs/public/favicon.svg new file mode 120000 index 0000000..e6e7e56 --- /dev/null +++ b/docs/public/favicon.svg @@ -0,0 +1 @@ +../../assets/favicon.svg \ No newline at end of file diff --git a/docs/src/assets/flutter_logo.svg b/docs/src/assets/flutter_logo.svg new file mode 100644 index 0000000..8f2cf83 --- /dev/null +++ b/docs/src/assets/flutter_logo.svg @@ -0,0 +1 @@ + diff --git a/docs/src/assets/logo_512.webp b/docs/src/assets/logo_512.webp new file mode 100644 index 0000000000000000000000000000000000000000..ea2dbb9f2d90ba105200e7b4b57847ba5eacf7dd GIT binary patch literal 38344 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 z�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�g&@j1?L}c84S#uYvB=%vhcimag$dOQI_g7 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 literal 0 HcmV?d00001 diff --git a/docs/src/assets/screenshot.webp b/docs/src/assets/screenshot.webp new file mode 100644 index 0000000000000000000000000000000000000000..be9399263bf0190d8d7535aec65c095d6e34c88c GIT binary patch literal 108746 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

`yO5%yc$FtDhxz*w4W5!>g8;!I%a+%8^AX;I3 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 diff --git a/docs/src/components/BarChart.tsx b/docs/src/components/BarChart.tsx new file mode 100644 index 0000000..b9e8c50 --- /dev/null +++ b/docs/src/components/BarChart.tsx @@ -0,0 +1,168 @@ +import { onCleanup, createEffect } from "solid-js"; +import { + Chart, + type ChartData, + type Tick, + type ScaleOptions, +} from "chart.js/auto"; +import { + BarWithErrorBarsController, + BarWithErrorBar, +} from "chartjs-chart-error-bars"; +import ChartDeferred from "chartjs-plugin-deferred"; + +import { createDarkMode } from "@/lib/darkmode"; + +Chart.register(BarWithErrorBarsController, BarWithErrorBar, ChartDeferred); + +interface BarChartProps { + data: ChartData<"bar">; + scales?: { [key: string]: ScaleOptions<"linear"> }; +} + +export function BarChart(props: BarChartProps) { + const darkMode = createDarkMode(); + + let ref: HTMLCanvasElement | undefined; + let chart: Chart | undefined; + + createEffect(() => { + chart?.destroy(); + + chart = new Chart<"bar">(ref!, { + type: "bar", + data: props.data, + options: { + scales: adjustScaleColor(darkMode(), { + y: {}, + x: {}, + ...props.scales, + }), + maintainAspectRatio: false, + plugins: { + // Defers rendering and animation until on screen. + deferred: { + yOffset: "30%", // defer until 50% of the canvas height are inside the viewport + delay: 200, // delay of 500 ms after the canvas is considered inside the viewport + }, + colors: { + enabled: true, + forceOverride: false, + }, + legend: { + position: "bottom", + labels: { + color: darkMode() ? "white" : undefined, + }, + }, + }, + }, + }); + }); + + onCleanup(() => chart?.destroy()); + + return ( +
+ +
+ ); +} + +function adjustScaleColor( + dark: boolean, + scales: { [key: string]: ScaleOptions<"linear"> }, +) { + for (const axis of Object.keys(scales)) { + const scale = scales[axis]; + + scale.ticks = { + ...scales[axis].ticks, + color: dark ? "white" : undefined, + }; + + scale.title = { + ...scale.title, + color: dark ? "white" : undefined, + }; + } + + return scales; +} + +interface BarChartWithErrorsProps { + data: ChartData<"barWithErrorBars">; + yTickFormatter?: ( + value: number | string, + index: number, + ticks: Tick[], + ) => string; +} + +export function BarChartWithErrors(props: BarChartWithErrorsProps) { + const darkMode = createDarkMode(); + + let ref: HTMLCanvasElement | undefined; + let chart: Chart | undefined; + + createEffect(() => { + chart?.destroy(); + + const scaleIds = props.data.datasets.map((e) => e.yAxisID ?? "y"); + const yScaleStyle = { + ticks: { + color: darkMode() ? "white" : undefined, + display: true, + callback: props.yTickFormatter, + }, + grid: { + display: true, + lineWidth: 0, + tickWidth: 0.5, + tickLength: 2, + tickColor: darkMode() ? "white" : "black", + }, + }; + + chart = new Chart<"barWithErrorBars">(ref!, { + type: BarWithErrorBarsController.id, + data: props.data, + options: { + scales: { + x: { + ticks: { + color: darkMode() ? "white" : undefined, + }, + }, + ...Object.fromEntries(scaleIds.map((id) => [id, yScaleStyle])), + }, + maintainAspectRatio: false, + plugins: { + // Defers rendering and animation until on screen. + deferred: { + yOffset: "30%", // defer until 50% of the canvas height are inside the viewport + delay: 200, // delay of 500 ms after the canvas is considered inside the viewport + }, + colors: { + enabled: true, + forceOverride: false, + }, + legend: { + position: "bottom", + labels: { + color: darkMode() ? "white" : undefined, + }, + }, + }, + }, + }); + }); + + onCleanup(() => chart?.destroy()); + + return ( +
+ +
+ ); +} diff --git a/docs/src/components/LineChart.tsx b/docs/src/components/LineChart.tsx new file mode 100644 index 0000000..6254db8 --- /dev/null +++ b/docs/src/components/LineChart.tsx @@ -0,0 +1,85 @@ +import { onCleanup, createEffect } from "solid-js"; +import { Chart, type ChartData, type ScaleOptions } from "chart.js/auto"; +import ChartDeferred from "chartjs-plugin-deferred"; + +import { createDarkMode } from "@/lib/darkmode"; + +Chart.register(ChartDeferred); + +interface LineChartProps { + data: ChartData<"line">; + scales?: { [key: string]: ScaleOptions<"linear"> }; +} + +export function LineChart(props: LineChartProps) { + const darkMode = createDarkMode(); + + let ref: HTMLCanvasElement | undefined; + let chart: Chart | undefined; + + createEffect(() => { + chart?.destroy(); + + chart = new Chart(ref!, { + type: "line", + data: props.data, + options: { + scales: adjustScaleColor(darkMode(), { + ...props.scales, + }), + maintainAspectRatio: false, + plugins: { + // Defers rendering and animation until on screen. + deferred: { + yOffset: "30%", // defer until 50% of the canvas height are inside the viewport + delay: 200, // delay of 500 ms after the canvas is considered inside the viewport + }, + colors: { + enabled: true, + forceOverride: false, + }, + legend: { + position: "bottom", + labels: { + color: darkMode() ? "white" : undefined, + }, + }, + }, + interaction: { + mode: "nearest", + axis: "x", + intersect: false, + }, + }, + }); + }); + + onCleanup(() => chart?.destroy()); + + return ( +
+ +
+ ); +} + +function adjustScaleColor( + dark: boolean, + scales: { [key: string]: ScaleOptions<"linear"> }, +) { + for (const axis of Object.keys(scales)) { + const scale = scales[axis]; + + scale.ticks = { + ...scales[axis].ticks, + color: dark ? "white" : undefined, + }; + + scale.title = { + ...scale.title, + color: dark ? "white" : undefined, + }; + } + + return scales; +} diff --git a/docs/src/content/config.ts b/docs/src/content/config.ts new file mode 100644 index 0000000..a4eec59 --- /dev/null +++ b/docs/src/content/config.ts @@ -0,0 +1,6 @@ +import { defineCollection } from "astro:content"; +import { docsSchema } from "@astrojs/starlight/schema"; + +export const collections = { + docs: defineCollection({ schema: docsSchema() }), +}; diff --git a/docs/src/content/docs/_roadmap.md b/docs/src/content/docs/_roadmap.md new file mode 100644 index 0000000..2e860c1 --- /dev/null +++ b/docs/src/content/docs/_roadmap.md @@ -0,0 +1,21 @@ +Over time, we would like to make TrailBase the best application base it can be. +Tell us what's missing, what could be better, and what smells. +Independently, we're very open to contributions, just talk to us first so we +can figure out how any feature will fit into the overall picture and minimize +friction. +For context, some larger features we have on our Roadmap: + +- Realtime/notification APIs for subscribing to data changes. +- S3 buckets and other cloud storage. The backend already supports it but it isn't wired up. +- Support more Social/OAuth providers. +- More configurable authentication, more customizable auth UI, and multi-factor. +- Service-accounts for authenticating and authorizing backends not end-users. +- Custom scheduled operations. Also enabling more time series use-cases. +- Many SQLite databases: imagine a separate database by tenant or user. +- Maybe integrate an ES6 JavaScript runtime or similar. +- Streamline code-generation, the bindings life-cycle, and first-party + support for more languages. +- Geo-spatial extensions and Geo-Ip for logs. +- Maybe TLS termination and proxy capabilities. +- Consider a GraphQL layer to address fan-out and integrate external + resources. diff --git a/docs/src/content/docs/comparison/pocketbase.mdx b/docs/src/content/docs/comparison/pocketbase.mdx new file mode 100644 index 0000000..093fac7 --- /dev/null +++ b/docs/src/content/docs/comparison/pocketbase.mdx @@ -0,0 +1,96 @@ +--- +title: PocketBase +description: Comparing TrailBase & PocketBase. +--- + +Firstly, PocketBase is amazing! It based the trail for single-file, SQLite +application bases, is incredibly easy-to-use, and a polished experience. Gani, +the person behind it, is a mad scientist. + +At the surface-level there are a lot of similarities between PocketBase and +TrailBase. In this comparison, we'll dive a little deeper and have a closer +look at the technical as well as philosophical differences between the two. + +### Goals & Aspirations + +TrailBase was born out of admiration for PocketBase trying to move the needle +in a few areas: + +- Less abstraction, embracing standards (SQL[^1], JWT, UUID), and untethered access + to SQLite/libsql[^2] including features such as recursive CTEs, virtual tables + and vector search. + The goal is to not get in your way and avoid lock-in by bespoke solutions + making it easier adopt TrailBase either fully or as piece-meal as well as + getting rid of it based on your product needs. +- Be just as easy to self-host and be even easier to manage a fleet of + deployments across integration tests, development, and production by separating + data, configuration, and secrets. +- Super-powers through SQLite extensions (regex, GIS, ...) including your own [^3]. +- Be lightweight enough to rival plain SQLite performance at least for + higher-level languages. +- Be simple and flexible enough to be an attractive alternative to plain SQLite + for serving **and** data analysis use-cases. + +### Differences + +It's worth noting that PocketBase and TrailBase have a lot in common: they are +both single-file, static binaries providing data APIs, authentication and file +storage on top of SQLite. +That said and for the sake of this article, let's look at some of the +differences and extra features that PocketBase provides: + +- TrailBase does not yet provide realtime APIs allowing clients to subscribe to + data changes. +- PocketBase lets you register custom endpoints in + [ES5 JavaScript](https://pocketbase.io/docs/js-overview/). +- PocketBase can also be used as a Go framework, i.e. instead of using the + binary release one can build a custom binary with custom endpoints. + +Likewise, TrailBase has a few nifty tricks up its sleeve: + +- Language independent type-safety via JSON Schemas with strict typing + being enforced all the way down to the database level[^4]. +- First-class access to all of SQLite/libsql's features and capabilities. +- A simple auth UI. +- Stateless JWT auth-tokens for simple, hermetic authentication in other + backends. +- Efficient and stable cursor-based pagination. +- An admin UI that "works" on small screens and mobile :) + +### Language & Performance + +Another difference is that PocketBase and TrailBase are written in Go and Rust, +respectively, which may matter to you especially when modifying either or using +them as "frameworks". + +Beyond personal preferences, both languages are speedy options in practice. +That said, Rust's lack of a runtime and lower FFI overhead should make it the +more performant choice. +To our own surprise, we found a significant gap. TrailBase is roughly 3.5x to +7x faster, in our [simplistic micro-benchmarks](/reference/benchmarks) +depending on the use-case. +Not to toot our own horn, this is mostly thanks to combining a very low +overhead language, one of the fastest HTTP servers, and incredibly quick +SQLite/libsql. + +
+ +--- + +[^1]: Maybe more in line with SupaBase's philosophy. We suspect that PocketBase + relies on schema metadata by construction requiring alterations to be + mediated through PocketBase APIs to stay in sync. + +[^2]: We believe that SQL a ubiquitous evergreen technology, which in of itself + is already a high-level abstraction for efficient, unified cross-database + access. + Even higher-level abstractions, such as ORMs, often look nice for simple + examples but quickly fall flat for more complex ones. They're certainly + bespoke, non-transferable knowledge, and increase vendor lock-in. + +[^3]: + All extensions can be built into a small, standalone shared library and + imported by vanilla SQLite avoiding vendor lock-in. + +[^4]: SQLite is not strictly typed by default. Instead column types merely a + type affinity for value conversions. diff --git a/docs/src/content/docs/comparison/supabase.mdx b/docs/src/content/docs/comparison/supabase.mdx new file mode 100644 index 0000000..702cf71 --- /dev/null +++ b/docs/src/content/docs/comparison/supabase.mdx @@ -0,0 +1,44 @@ +--- +title: SupaBase +description: Comparing TrailBase & SupaBase. +--- + +Both SupaBase and Postgres are amazing. Comparing either to TrailBase and +SQLite, respectively, is challenging given how different they are +architecturally. + +For one, both Postgres and SupaBase are heck of a lot more modular. "Rule 34" of +the database world: if you can think of it, there's a Postgres extension for it. +And SupaBase doesn't an excellent job at making all that flexibility available +without getting in the way and giving you untethered access while further +expanding upon it. +In many ways, TrailBase is trying to evnetually do the same for SQLite: +combining PocketBase's simplicity with SupaBase's layering. + +One foundational difference is that Postgres itself is a multi-user, +client-server architecture already. +Extending it by building a layered services around it, like SupaBase did, +feels very natural. +However, SQLite is neither a multi-user system nor a server. Hence, extending +it by embedding it into a monolith, like PocketBase did, feels fairly natural +as well. +There are ups and downs to either approach. The layered service approach, for +example, allows for isolated failure domains and scaling of individual +components [^1]. The monolith, on the other hand, with its lesser need for modularity +can have fewer interaction points, fewer moving parts making it fundamentally +simpler, cheaper, and +[lower overhead (10+x performance difference)](/reference/benchmarks). + +Ultimately, the biggest difference is that SupaBase is a polished product with +a lot of mileage under its belt. Our simpler architecture will hopefully let us +get there but for now SupaBase is our north star. + +
+ +--- + +[^1]: + For example, in our performance testing we've found that PostgREST, + SupaBase's RESTful API layer in front of Postgres, is relatively resource + hungry. This might not be an issue since one can simply scale by pointing + many independent instances at the same database instance. diff --git a/docs/src/content/docs/contact.mdx b/docs/src/content/docs/contact.mdx new file mode 100644 index 0000000..732c7fe --- /dev/null +++ b/docs/src/content/docs/contact.mdx @@ -0,0 +1,11 @@ +--- +title: Contact +template: splash +--- + +
+ Sebastian + contact [at] trailbase.io + + 8047 Zurich, Switzerland +
diff --git a/docs/src/content/docs/documentation/APIs/query_apis.mdx b/docs/src/content/docs/documentation/APIs/query_apis.mdx new file mode 100644 index 0000000..1c9446e --- /dev/null +++ b/docs/src/content/docs/documentation/APIs/query_apis.mdx @@ -0,0 +1,56 @@ +--- +title: Query APIs +--- + +import { Aside } from "@astrojs/starlight/components"; + +Query APIs are a more free-form and type-unsafe way of exposing data using +virtual tables based on user inputs and stored procedures. Please make sure to +take a look at [record APIs](/documentation/apis/record_apis) first. Views and +generated columns may be a better fit for transforming data if no explicit user +input is required. + + + +## Example + +Using migrations and sqlean's `define` we can define a table query with unbound +inputs (see placeholder $1): + +```sql +CREATE VIRTUAL TABLE + _is_editor +USING + define((SELECT EXISTS (SELECT * FROM editors WHERE user = $1) AS is_editor)); +``` + +Subsequently, an API can be configured to query the newly created `VIRTUAL +TABLE`, also binding URL query parameters as inputs to above placeholders. + +```proto +query_apis: [ + { + name: "is_editor" + virtual_table_name: "_is_editor" + params: [ + { + name: "user" + type: BLOB + } + ] + acl: WORLD + } +] +``` + +Finally, we can query the API, e.g. using curl: + +```bash +curl -g 'localhost:4000/api/query/v1/is_editor?user=' +``` diff --git a/docs/src/content/docs/documentation/APIs/record_apis.mdx b/docs/src/content/docs/documentation/APIs/record_apis.mdx new file mode 100644 index 0000000..c60602b --- /dev/null +++ b/docs/src/content/docs/documentation/APIs/record_apis.mdx @@ -0,0 +1,299 @@ +--- +title: Record APIs +--- + +import { Aside } from "@astrojs/starlight/components"; + +The easiest and most type-safe path to access you `TABLE`s and `VIEW`s is to use +TrailBase's restful CRUD _Record APIs_. +The only requirements are: + +- Tables and views need to be `STRICT`ly[^1] typed to guarantee type-safety all the + way from your records, via JSON schema, to your client-side language bindings [^2]. +- They need to have a sequential primary key column to allow for stable sorting + and thus efficient cursor-based pagination. Either an explicit `INTEGER` or + UUIDv7 `PRIMARY KEY` will do, including `FOREIGN KEY` columns. + +## Configuring APIs + +Record APIs can be configured through the admin dashboard or immediately in +TrailBase's configuration file. +Note that there are certain features that aren't yet exposed in the dashboard, +like supporting multiple APIs based on the same table or view. +In this case you can drop down to the configuration to set up as many as you +like allowing for a lot of extra flexibility around permissions and visibility. + +An example API setup for managing user avatars: + +```json +record_apis: [ + { + name: "_user_avatar" + table_name: "_user_avatar" + conflict_resolution: REPLACE + autofill_missing_user_id_columns: true + acl_world: [READ] + acl_authenticated: [CREATE, READ, UPDATE, DELETE] + create_access_rule: "_REQ_.user IS NULL OR _REQ_.user = _USER_.id" + update_access_rule: "_ROW_.user = _USER_.id" + delete_access_rule: "_ROW_.user = _USER_.id" + } +] +``` + +A quick explanation: + +* The `name` needs to be unique. It's what is used to access the API via + `/api/v1/records//`. +* `table_name` references the table or view that is being exposed. +* `conflict_resolution` declares what should happen if a newly created record is + conflicting with an existing one. +* `autofill_missing_user_id_column` lets you omit fields for columns with a foreign + key relationship to `_user(id)`. The field will then be filled with the + credentials of the authenticated user. In most cases, this should probably be off, this + only useful if you cannot explicitly provide the user id yourself, e.g. in a + static HTML form. +* `acl_world` and `acl_authenticated` define that anyone can read avatars but + only authenticated users can modify them. The following `access_rules` further narrow + mutations to records where the `user` column (or request field for insertions) + match. In other words, user X cannot modify user Y's avatar. + + +### Access Control + +Access can be controlled through combination of a simple ACL-based system (a +matrix of who and what) and custom SQL access rules of the nature: +`f(req, user, row) -> bool`. +Generally, the ACLs are checked first and then the access rules are evaluated +when present. + +For example, to validate that the requestor provided a secret key and is member +of a group "mygroup": + +```sql +(_REQ_.secret = 'foo' AND EXISTS( + SELECT 1 FROM groups + WHERE + groups.member = _USER_.id + AND groups.name = 'mygroup' + )) +``` + +* `_REQ_` is an injected sub-query containing the request fields. It is + available in access rules for `CREATE` and `UPDATE` operations. +* Similarly, `_ROW_` is a sub-query of the target record. It is available in + access rules for `READ`, `UPDATE`, and `DELETE` operations. +* Lastly, `_USER_.id` references the id of the currently authenticated user and + `NULL` otherwise. + +Independently, you can use `VIEW`s to filter which rows and columns of +your `TABLE`s should be accessible. + +#### Building access groups and capabilities + +As hinted at by the example above, the SQL access rules can be used to +build higher-level access protection such as group ACLs or capabilities. +What makes the most sense in your case, is very application dependent. +The `/examples/blog` has an "editor" group to control who can write blog +posts. + +Somewhat on a tangent and pretty meta, group and capability tables can +themselves be exposed via Record APIs. +This can be used to programmatically manage permissions, e.g. for building a +moderation dashboard. +When exposing authorization primitives, make sure the permissions are +appropriately tight to avoid permission escalations. + +### Write-only columns + +Columns with names starting with an underscore can be written on insert or +update but are hidden on reads. This is meant as a convenient convention to +allow for internal data fields, e.g hiding the record owner in an otherwise public +data set or hiding a user's internal credit rating from their profile. A +similar effect could otherwise be achieved by exposing a table for inserts and +updates only while poxying reads through a VIEW. + + + +## Accessing Record APIs + +After configuring the APIs and setting up permissions, record APIs expose six +main endpoints[^3]: + +* **C**reate: endpoint for for inserting new and potentially overriding records + depending on conflict resolution strategy.
+ `POST /api/v1/records/` +* **R**ead: endpoint for reading specific records given the record id.
+ `GET /api/v1/records//` +* **U**pdate: partial updates to existing records given a record id and subset of fields
+ `PATCH /api/v1/records//` +* **D**elete: endpoints for deleting record given a record id.
+ `DELETE /api/v1/records//` +* List: endpoint for listing, filtering and sorting records based on the + configured read access rule and provided filters.
+ `GET /api/v1/records/?` +* Schema: endpoint for reading the APIs JSON schema definition. Can be used for + introspection and to drive code generation.
+ `GET /api/v1/records//schema` + +All of the above endpoints can be interacted with through requests that are +either JSON encoded, url-encoded, or `multipart/form-data` encoded, which makes +them accessible via rich client-side applications, progressive web apps, and +static HTML forms alike. + +### Listing, filtering & sorting records + +Using the `GET /api/v1/records/?` endpoint and given +sufficient permissions one can query records based the given `read_access_rule` +and query parameters. + +Parameters: + +* Pagination can be controlled with two parameters: `limit=N` (with a hard + limit of 1024) and `cursor=`. +* Ordering can be controlled via `order=[[+-]?]+`, e.g. + `order=created,-rank`, which would sort records first by their `created` + column in ascending order (same as "+") and then by the `rank` column in + descending order due to the "-". +* Lastly, one can filter records by matching against one or more columns like + `[op]=`, e.g. `revenue[gt]=0` to request only records + with revenue values "greater than" 0. The supported operators are: + * equal, is the empty operator, e.g. `?success=TRUE`. + * **not**|**ne**: not equal + * **gte**: greater-than-equal + * **gt**: greater-than + * **lte**: less-than-equal + * **lt**: less-than + * **like**: SQL `LIKE` operator + * **re**: SQL `REGEXP` operator + +For example, to query the 10 highest grossing movies with a watch time less +than 2 hours and an actor called John, one could query: + +```bash +curl -g '
/api/recrods/v1/movies?limit=10&order=grossing&watch_time_min[lt]=120&actors[like]=%John%' +``` + +## File Upload + +Record APIs can also support file uploads and downloads. There's some special +handling in place so that only metadata is stored in the underlying table while +the actual files are kept in an object store. + +By adding a `TEXT` column with a `CHECK(jsonschema('std.FileUpload'))` +constrained to your TABLE, you instruct TrailBase to store file metadata as +defined by the "std.FileUpload" JSON schema and write the contents off to +object storage. +Files can then be upload by sending the contents as part your JSON or +`multipart/form-data` POST request. +Downloading files is slightly different, since reading the column through +record APIs will only yield the metadata. There's a dedicated GET API endpoint +for file downloads: +`/api/v1/records///file/` + + + + +## Custom JSON Schemas + +Akin to `std.FileUpload` above, you can register your own nested JSON schemas +to be used with column `CHECK`s. +For now, the dashboard only allows viewing all registered JSON schemas, however +you can register schemas using the configuration: + +```json +schemas: [ + { + name: "simple_schema" + schema: + '{' + ' "type": "object",' + ' "properties": {' + ' "name": { "type": "string" },' + ' "obj": { "type": "object" }' + ' },' + ' "required": ["name"]' + '}' + } +] +``` + +Once registered, schemas can be added as column constraints: + +```sql +CREATE TALE test ( + simple TEXT CHECK(jsonschema('simple_schema')), + + -- ... +) STRICT; +``` + +When generating new client-side bindings for a table or view with such nested +schemas, they will be included ensuring type-safety all the way to the +client-side APIs. + +### Tangent: Querying JSON + +Independent of type-safety and Record APIs, +[SQLite](https://www.sqlite.org/json1.html) has first-class support for +querying nested properties of columns containing JSON in textual or binary +format [^4]. +For example, given a table: + +```sql +CREATE TABLE items (json TEXT NOT NULL); + +INSERT INTO items (json) VALUES ('{"name": "House", "color": "blue"}'); +INSERT INTO items (json) VALUES ('{"name": "Tent", "color": "red"}'); +``` + +You can query the names of red items: + +```sql +SELECT + json->>'name' AS name +FROM + items +WHERE + json->>'color' = 'red'; +``` + +Note that this requires SQLite to scan all rows and deserialize the JSON. +Instead, storing the color of items in a separate, indexed column and filter +on it would be a lot more efficient. +Yet, using JSON for complex structured or denormalized data can be powerful +addition to your toolbox. + + +
+ +--- + +[^1]: + By default, SQLite are not strictly typed. Column types merely express + type-affinities. Unless tables are explicitly created as `STRICT` columns can + store any data type. + +[^2]: + Views are more tricky to strictly type, since they're the result of an + arbitrary `SELECT` statement. TrailBase parses the `CREATE VIEW` statement + and will allow record APIs only on top of a conservative subset, where it + can infer the column types. Over time, TrailBase will be able to support + larger subsets. Let us know if you have provably strictly typed queries + that you think should be supported but aren't. + +[^3]: + There's also a few other endpoints, e.g. for downloading files as described + later in the document. + +[^4]: + Record APIs only support textual JSON. Binary JSON is more compact and more + efficient to parse, however its actual encoding is internal to SQLite and + thus opaque to TrailBase. diff --git a/docs/src/content/docs/documentation/_auth.svg b/docs/src/content/docs/documentation/_auth.svg new file mode 100644 index 0000000..87e95a5 --- /dev/null +++ b/docs/src/content/docs/documentation/_auth.svg @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + TrailBase + + + + + + auth token (JWT) + + locally authenticateand/or forward JWT + + + Your Backend + + refresh token + + auth token (JWT) + + + + + + + + + diff --git a/docs/src/content/docs/documentation/auth.mdx b/docs/src/content/docs/documentation/auth.mdx new file mode 100644 index 0000000..fba0cef --- /dev/null +++ b/docs/src/content/docs/documentation/auth.mdx @@ -0,0 +1,122 @@ +--- +title: Auth +description: Managing Users and Access +--- + +import { Image } from "astro:assets"; +import { Aside } from "@astrojs/starlight/components"; + +import implementation from "./_auth.svg"; + +TrailBase provides core authentication flows and a basic UI out of the box[^1]. +These primitives let you establish the identity of your users in order to +authorize or deny access to your data, let users change their email address, +reset their password, etc. + + + +## Implementation + +TrailBase tries to offer a standard, safe and versatile auth implementation out +of the box. It combines: + +- Asymmetric cryptography based on elliptic curves (ed25519) +- Stateless, short-lived auth tokens (JWT) +- Stateful, long-lived, opaque refresh tokens. + +Breaking this apart, __asymmetric cryptography__ means that tokens signed with a +private key by the TrailBase "auth server", which can then be validated by +others ("resource servers") using only the corresponding public key. +The __Statelesss JWTs__ contain metadata that identities the user w/o having to +talk to the auth server. +Combining the two, other back-ends can authenticate, validate & identify, users +hermetically. +This is very easy and efficient, however means that hermetic auth tokens cannot +be invalidated. +A hermetic auth token released into the wild is valid until it expires. +To balance the risks and benefits, TrailBase uses short-lived auth tokens +expiring frequently[^2]. +To avoid burdening users by constantly re-authenticating, TrailBase issues an +additional __opaque, stateful refresh token__. +Refresh tokens are simply a unique identifier the server keeps track of as +sessions. +Only refresh tokens that have not been revoked can be exchanged for a new auth +token. + +
+ Screenshot of TrailBase's admin dashboard +
+ +## Flows & UI + +TrailBase currently implements the following auth flows: + +- Email + password based user registration and email verification. +- User registration using social OAuth providers (Google, ...) +- Login & logout. +- Change & reset password. +- Change email. +- User deletion. +- Avatar management. + +Besides the flows above, TrailBase also ships with a set of simple UIs to +support the above flows. By default it's accessible via the route: +`/_/auth/login`. Check out the [demo](https://demo.trailbase.io/_/auth/login). +The built-in auth UIs can be disabled with `--disable-auth-ui` in case you +prefer rolling your own or have no need web-based authentication. + +## Usernames and other metadata + +Strictly speaking, authentication is merely responsible for uniquely +identifying who's on the other side. +This only requires a __unique identifier__ and one or more __secrets__ +(e.g. a password, hardware token, ...) for the peer to proof they're them. + +Any unique identifier will do: a random string (painful to remember), a phone +number, a username, or an email address. +Email addresses are a popular choice, since they do double duty as a +communication channel letting you reach out to your users, e.g. to reset their +password. + +Even from a product angle, building an online shop for example, email addresses +are the natural choice. +Asking your customers to think up and remember a globally unique username adds +extra friction especially since you need their email address anyway to send +receipts. +Additional profile data, like a shipment address, is something you can ask for +at a later time and is independent from auth. +In contrast, when building a social network, chat app or messaging board, you +typically don't want to leak everyone's email address. +You will likely want an additional, more opaque identifier such as a username +or handle. + +Long story short, modeling __profile__ data is very product dependent. +It's for you to figure out. +That said, it is straight forward to join auth data, such as the user's email +address, and custom custom profile data in TrailBase. +We suggest creating a separate profile table with a `_user.id` `FOREIGN KEY` +primary key column. You can then freely expose profiles as dedicated record API +endpoints or join them with other data `_user.id`. +The blog example in `/examples/blog` demonstrates this, joining blog +posts with user profiles on the author id to get an author's name. + +
+ +--- + +[^1]: + Which can be disabled using `--disable-auth-ui`, if you prefer rolling your + own or have no need for a web-based authentication UI. + +[^2]: + A one hour TTL by default. diff --git a/docs/src/content/docs/documentation/extending.mdx b/docs/src/content/docs/documentation/extending.mdx new file mode 100644 index 0000000..95cd7bb --- /dev/null +++ b/docs/src/content/docs/documentation/extending.mdx @@ -0,0 +1,121 @@ +--- +title: Extending +description: Collocating your logic +--- + +import { Aside } from "@astrojs/starlight/components"; + +This article explores different ways to extend TrailBase and integrate your own +custom logic. + +## The Elephant in the Room + +The question on where your code should run is as old as the modern internets +becoming ever present since moving away from a static mainframe model and +hermetic desktop applications. +With pushing more interactive applications to slow platforms, such as early +browsers or mobile phone, there was an increased need to distribute +applications with interactivity happening in the front-end and heavy lifting +happening in a back-end. +That's not to say that there aren't other good reasons to not just run all your +code in an untrusted, potentially slow client-side sandbox. + +In any case, having a rich client-side application like a mobile, desktop or +progressive web apps will reduce your need for server-side integrations. +They're often a good place to start [^1], even if over time you decide to move more +logic to a backend to address issues like high fan-out, initial load +times, and SEO for web applications. + +Inversely, if you have an existing application that is mostly running +server-side, you probably already have a database, auth, and are hosting your +own APIs, ... . +If so, there's intrinsically less any application base can help you with. +Remaining use-cases might be piece-meal adoption to speed up existing APIs or +delegate authentication. +One advantage of lightweight, self-hosted solutions is that they can be +co-locate with your existing stack to reduce costs and latency. + +## Bring your own Backend + +The most flexible and likewise de-coupled way of running your own code is to +deploy a separate service alongside TrailBase. This gives you full control over +your destiny: runtime, scaling, deployment, etc. + +TrailBase is designed with the explicit goal of running along a sea of other +services. +Its stateless tokens using asymmetric crypto make it easy for other resource +servers to hermetically authenticate your users. +TrailBase's APIs can be accessed transitively, simply by forwarding user +tokens. +Alternatively, you can fall back to raw SQLite for reads, writes and even +schema alterations[^2]. + + + +## Custom APIs in TrailBase + +TrailBase provides three main ways to embed your code and expose custom APIs: + +1. Rust/Axum handlers. +2. Stored procedures & [Query APIs](/documentation/apis/query_apis/) +3. SQLite extensions, virtual table modules & [Query APIs](/documentation/apis/query_apis/) + +Beware that the Rust APIs and [Query APIs](/documentation/apis/query_apis/) are +likely subject to change. We rely on semantic versioning to explicitly signal +breaking changes. +Eventually, we would like to lower the barrier of entry by providing stable +bindings to a higher-level runtime within TrailBase, likely a +TypeScript/ES6/JavaScript runtime. + +### Using Rust + +The Rust APIs aren't yet stable and fairly undocumented. +That said, similar to using PocketBase as a Go framework, you can build your +own TrailBase binary and register custom Axum handlers written in rust with the +main application router, see `/examples/custom-binary`. + +### Stored Procedures & Query APIs + +Unlike Postgres or MySQL, SQLite does not supported stored procedures out of +the box. +TrailBase has adopted sqlean's +[user-defined functions](https://github.com/nalgeon/sqlean/blob/main/docs/define.md) +to provide similar functionality and minimize lock-in over vanilla SQLite. +Check out [Query APIs](/documentation/apis/query_apis/), to see how stored +procedures can be hooked up. + +### SQLite extensions, virtual table modules & Query APIs + +Likely the most bespoke approach is to expose your functionality as a custom +SQLite extension or module similar to how TrailBase extends SQLite itself. + +This approach can be somewhat limiting in terms of dependencies you have +access to and things you can do especially for extensions. Modules are quite a bit +more flexible but also involved. +Take a look at [SQLite's list](https://www.sqlite.org/vtablist.html) and +[osquery](https://osquery.readthedocs.io/en/stable/) to get a sense of what's +possible. + +Besides their limitations, major advantages of using extensions or +modules are: +* you have extremely low-overhead access to your data, +* extensions and modules can also be used by services accessing the + underlying SQLite databases. + +
+ +--- +[^1]: + There are genuinely good properties in terms of latency, interactivity, offline + capabilities and privacy when processing your users' data locally on their + device. + +[^2]: + SQLite is running in WAL mode, which allows for parallel reads and + concurrent writes. That said, when possible you should probably use the APIs + since falling back to raw database access is a priviledge practically reserved + to processes with access to a shared file-system. diff --git a/docs/src/content/docs/documentation/production.mdx b/docs/src/content/docs/documentation/production.mdx new file mode 100644 index 0000000..ad67863 --- /dev/null +++ b/docs/src/content/docs/documentation/production.mdx @@ -0,0 +1,85 @@ +--- +title: Productionize +description: Going to production. +--- + +import { Aside } from "@astrojs/starlight/components"; + + + +Going to production and depending on your requirements things to think about +could be: + +- HTTPS/TLS termination +- locking down access +- setting up Email +- deployment +- introspection +- disaster recovery + +## TLS termination + +The most important thing alongside ensuring proper access protection is to set +up TLS termination ensuring that all traffic from your users to your +termination point is encrypted. +In practice, this means putting TrailBase behind a reverse proxy such as NGinx, +Caddy, ... . The main benefit of using an established reverse proxy is the +availability of auto-renewal of self-signed certificates with SSL authorities +Let's encrypt. + +## Access + +### API access + +Make sure to use record API's authorization primitives to tighten access to +data as much as possible. It's a good idea to check `_REQ_. == +_USER_.id` on record creations and updates to avoid users can impersonate or +touch on other users records. + +### Admin access + +You can expose TrailBase's admin APIs and UIs on a separate private port as an +extra precaution and to simply expose a smaller surface. + +### Protect Configuration + +You can prevent TrailBase configuration from being accidentally changed in +prod, e.g. when you think you're actually configuring a dev instances. To do +so, you can read-only mount the configuration directory. However, make sure the +data directory remains writable. + +## Email + +By default TrailBase will be using your machine's sendmail setup. This can lead +to messages not being sent at all and likely getting stuck in spam filters not +coming from a well-known Email server. + +You should likely set up TrailBase with an SMTP server that can send Email +coming from your domain. If you don't have an Email provider yet, an option +could be Brevo, Mailchimp, SendGrid, ... . + +## Deployment + +We recommend containerization (e.g. Docker) for convenience. You can also +consider to mount certain directories and files such as `/secrets` +and `/config.textproto` as read only. + +## Introspection + +TrailBase's introspection is fairly non-existent at this point. There is a +`/api/healthcheck` endpoint for container orchestration systems to probe. +You could also consider setting up probers probing other endpoints. + +## Disaster Recovery + +The simplest option is to mount anothjer local or remote drive and use +TrailBase's periodic backups. +However, this may lead to significant data loss in case of a disaster, which +may be acceptable for first party content but likely not for user-generated +content. + +A more comprehensive approach may be to use [Litestream](https://litestream.io/) +to continuously replicate your database. diff --git a/docs/src/content/docs/documentation/type_safety.mdx b/docs/src/content/docs/documentation/type_safety.mdx new file mode 100644 index 0000000..2d6323a --- /dev/null +++ b/docs/src/content/docs/documentation/type_safety.mdx @@ -0,0 +1,82 @@ +--- +title: Type-Safety +--- + +import { Aside } from "@astrojs/starlight/components"; + +TrailBase provides end-to-end type-safety from the database level, through the +HTTP APIs, all the way up to the client bindings relying on JSON schemas. +It's worth noting that the JSON schema is derived directly from the database +schema as the source of truth meaning that any schema change will be reflected +independent of whether they were applied via the admin dashboard, `sqlite3` or +other means. +This also means that you should regenerate your type definitions +after changing the schema. We therefore recommend to integrate type generation +into your build process or check the generated types in following your database +migrations. + +Using JSON schema and relying on off-the-shelf code generation tools, allows to +keep the client-libraries very thin making it easy to integrate virtually any +language in a type-safe fashion. +`/examples/blog` provides a glimpse at using [quicktype](https://quicktype.io/) +to generate type-safe TypeScript and Dart APIs. + +Type-safety is the main reason why TrailBase APIs require `STRICT`ly typed +tables. By default SQLite only has a notion of "type affinity" on +inserts and updates, generally allowing any data in any column. + +## Generating Types from JSON Schemas + +The generated JSON schemas depend on two aspects: + +1. The actual database schema mapping columns and column types to fields and + data types in a data structure of your target language. +2. The specific API operation: `CREATE`, `UPDATE`, `READ`. + +Expanding on 2., the notion of default values for columns means that data for +`NOT NULL` columns is optional when creating a new record but guaranteed to be +present on record read. +`UPDATE`s are point updates of existing records, thus only requiring specific +column values to be overridden. + +Concretely, looking at `/examples/blog`, the data structure for inserting a new +blog article is less strict than the equivalent for retrieving an existing +article: + +```typescript +// Input data type when creating a new article record. +export interface NewArticle { + author: string; + body: string; + created?: number; + id?: string; + image?: FileUpload; + // ... +} + +// Result data type when reading an article record. +export interface Article { + author: string; + body: string; + created: number; + id: string; + image?: FileUpload; + // ... +} +``` + +## Nested JSON Columns + +TrailBase also supports generating type-safe bindings for columns containing +JSON data and enforcing a specific JSON schema, see +[here](/documentation/apis/record_apis/#custom-json-schemas). + + + +
+ +--- + +[^1]: + We do not support binary JSON, i.e. SQLite's internal JSONB + representation at this point. diff --git a/docs/src/content/docs/getting-started/first-app.mdx b/docs/src/content/docs/getting-started/first-app.mdx new file mode 100644 index 0000000..f08670a --- /dev/null +++ b/docs/src/content/docs/getting-started/first-app.mdx @@ -0,0 +1,197 @@ +--- +title: First App +description: A guide in my new Starlight docs site. +--- + +import { Code } from "@astrojs/starlight/components"; +import { Aside } from "@astrojs/starlight/components"; + +{/* +import Readme from "../../../../../examples/tutorial/README.md"; + +*/} + +In this tutorial, we'll set up a database with an IMDB test dataset, spin up +TrailBase and write a small program to access the data. + +In an effort to demonstrate TrailBase's loose coupling and the possibility of +simply trying out TrailBase with an existing SQLite-based data analysis +project, we will also offer a alternative path to bootstrapping the database +using the vanilla `sqlite3` CLI. + + + +## Create the Schema + +By simply starting TrailBase, the migrations in `traildepot/migrations` will be +applied, including `U1728810800__create_table_movies.sql`: + +```sql +CREATE TABLE movies IF NOT EXISTS ( + rank INTEGER PRIMARY KEY, + name TEXT NOT NULL, + year ANY NOT NULL, + watch_time INTEGER NOT NULL, + rating REAL NOT NULL, + metascore ANY, + gross ANY, + votes TEXT NOT NULL, + description TEXT NOT NULL +) STRICT; +``` + +Note that the only schema requirement for exposing an API is: `STRICT` typing +and an integer (or UUIDv7) primary key column. + +The main benefit of relying on TrailBase to apply the above schema as migrations +over manually applying the schema yourself, is to: + +- document your database's schema alongside your code and +- even more importantly, letting TrailBase bootstrap from scratch and + sync-up databases across your dev setup, your colleague's, every time + integration tests run, QA stages, and in production. + +That said, TrailBase will happily work on existing datasets, in which +case it is your responsibility to provide a SQLite database file that +meets expectations expressed as configured TrailBase API endpoints. + +Feel free to run: + +```bash +$ mkdir traildepot/data +$ sqlite3 traildepot/data/main.db < traildepot/migrations/U1728810800__create_table_movies.sql +``` + +before starting TrailBase the first time, if you prefer bootstrapping the +database yourself. + +## Importing the Data + +After creating the schema above, either manually or starting TrailBase to apply +migrations, we're ready to import the IMDB test dataset. +We could now expose an API endpoint and write a small program to first read the +CSV file to then write movie database records... and we'll do that in a little +later. +For now, let's start by harnessing the fact that SQLite databases are simply a +local file and import the data using the `sqlite3` CLI side-stepping TrailBase: + +``` +$ sqlite3 traildepot/data/main.db +sqlite> .mode csv +sqlite> .import ./data/Top_1000_IMDb_movies_New_version.csv movies +``` + +There will be a warning for the first line of the CSV, which contains textual +table headers rather than data matching our schema. That's expected. +We can validate that we successfully imported 1000 movies by running: + +```sql +sqlite> SELECT COUNT(*) FROM movies; +1000 +``` + +## Accessing the Data + +With TrailBase up and running (`trail run`), the easiest way to explore your +data is go to the admin dashboard under +[http://localhost:4000](http://localhost:4000) +and log in with the admin credentials provided to you in the terminal upon +first start (you can also use the `trail` CLI to reset the password `trail user +reset-password admin@localhost`). + +In this tutorial we want to explore more programmatic access and using +TrailBase record APIs. + +```json +record_apis: [ + # ... + { + name: "movies" + table_name: "movies" + acl_world: [READ] + acl_authenticated: [CREATE, READ, UPDATE, DELETE] + } +] +``` + +By adding the above snippet to your configuration (which is already the case +for the checked-in configuration) you expose a world-readable API. We're using +the config here but you can also configure the API using the admin dashboard +via the +[tables view](http://localhost:4000/_/admin/tables?pageIndex=0&pageSize=20&table=movies) +and the "Record API" settings in the top right. + +Let's try it out by querying the top-3 ranked movies with less than 120min +watch time: + +```bash +curl -g 'localhost:4000/api/records/v1/movies?limit=3&order=rank&watch_time[lt]=120' +``` + +You can also use your browser. Either way, you should see some JSON output with +the respective movies. + +## Type-Safe APIs and Mutations + +Finally, let's authenticate and use privileged APIs to first delete all movies +and then add them pack using type-safe APIs rather than `sqlite3`. + +Let's first create the JSON Schema type definitions from the database schema we +added above. Note, that the type definition for creation, reading, and updating +are all different. Creating a new record requires values for all `NOT NULL` +columns w/o a default value, while reads guarantees values for all `NOT NULL` +columns, and updates only require values for columns that are being updated. +In this tutorial we'll "cheat" by using the same type definition for reading +existing and creating new records, since our schema doesn't define any default +values (except implicitly for the primary key), they're almost identical. + +In preparation for deleting and re-adding the movies, let's run: + +```bash +$ trail schema movies --mode insert +``` + +This will output a standard JSON schema type definition file. There's quite a few +code-generators you can use to generate bindings for your favorite language. +For this example we'll use _quicktype_ to generate _TypeScript_ definitions, +which also happens to support some other ~25 languages. You can install it, but +for the tutorial we'll stick with the [browser](https://app.quicktype.io/) +version and copy&paste the JSON schema from above. + +With the generated types, we can use the TrailBase TypeScript client to write +the following program: + +import fillCode from "../../../../../examples/tutorial/scripts/src/fill.ts?raw"; + + + +## What's Next? + +Thanks for making it to the end. +Beyond the basic example above, the repository contains a more involved Blog +example (`/examples/blog`) including both, a Web and Flutter UI. +The blog example also demonstrates more complex APIs, authorization, custom +user profiles, etc. + +Any questions or suggestions? Reach out on GitHub and help us improve the docs. +Thanks! diff --git a/docs/src/content/docs/getting-started/philosophy.mdx b/docs/src/content/docs/getting-started/philosophy.mdx new file mode 100644 index 0000000..e84b352 --- /dev/null +++ b/docs/src/content/docs/getting-started/philosophy.mdx @@ -0,0 +1,87 @@ +--- +title: Philosophy +description: A quick look at TrailBase's philosophy and goals. +--- + +The ambition of TrailBase is to help solve common problems with +established, standard solutions, while being blazingly fast, avoiding +lock-in, or getting in your way. +You shouldn't have to fight your framework due to evolving product needs. +Instead, you should be able to use SQLite to its fullest, extend it, or move on +entirely if necessary. + +The key for TrailBase to achieve this goal is to focus on _loose coupling_ and +_rigorous simplicity_. +Performance is merely a desirable side-effect of keeping it simple and +carefully picking the right components for doing the heavy lifting. + +### _Simplicity_ + +To avoid demoting _simplicity_ to just another popular marketing term, let's +start by clarify what we mean. +Simplicity is a relative property in the context of a problem: +a simple solution for a simple problem is straightforward to understand, +validate, extend or even replace. +A simple solution solution for a hard problem will naturally be more involved +but retains above properties within a more complex context. + +"Simple" is different from "easy". +An easy solution may be very complex in an effort to take on as much +responsibility as possible for very specific scenarios. +Easy solutions will sometimes yield pleasing but magic solutions that fall flat +when straying off the path. +Magic solutions will always lead to tight coupling and lock-in. +In contrast, simple solutions are explicit, apply in a wide range of scenarios +and lead to easy-to-understand, easy-to-change outcomes. + +Why should I care? We believe that there are material benefits to simplicity. +For example and tying back to TrailBase: + +- A simple, single-file backend dependency lets you set up **consistent** + production, pre-prod, testing and development environments, which will help + to improve velocity, catch issues sooner, and reduce cognitive overhead. +- Lets you change production deployments or cloud providers more easily to + address soaring bills, ToS changes, geopolitics and policy requirements such as + data governance. +- Lets you more easily adopt TrailBase, also selectively, and more easily drop + it if you choose to. + +### _Coupling_ + +The way we defined _simplicity_ above, loose coupling is already an important +property of a good-natured, simple solution. Yet, we believe it's a critical +property in its own right that should be called out explicitly helping to +illustrate the guiding principles underpinning TrailBase. +Looking at two examples: + +__Admin Dashboard__: TrailBase offers an easy-to-use, integrated admin dashboard. +It doesn't make TrailBase architecturally simpler but hopefully easier to use. +Importantly, it's loosely coupled to the rest of the system. It's neither +critical for serving production traffic nor setting up TrailBase. +Any dashboard task can be equally accomplished using the CLI, the configs, or +SQL. + +__SQL over ORM__: TrailBase embraces SQL instead of trying to hide it. Eventually +all paths lead to SQL as the only truly cross-platform, cross-database, +cross-language solution 😉. +ORMs often yield simple looking examples but then fall flat soon after going +beyond the tutorial, sometimes already when joining tables. +Your data model should never be driven by the short-comings of an abstraction +forced upon you. +ORMs aren't without merit. Often they will provide type-safe APIs for accessing +the database. While more constraint, TrailBase's end-to-end type-safety +provides similar benefits. +Leaning into HTTP, JSON and JSON schema to makes it easy for TrailBase to +provide consistent cross-language client-side type-safety [^1], giving you more +freedom in choosing the right tool for a specific job. + +
+ +--- + +[^1]: + Having only TypeScript and Dart bindings at the moment, this may sound more + aspirational than practical. + However, client bindings are only very thin layers around HTTP + JSON. + It is straight forward to add new bindings or just use `curl` in a bunch + of shell scripts. We're planning to add more bindings in the future. diff --git a/docs/src/content/docs/getting-started/starting-up.mdx b/docs/src/content/docs/getting-started/starting-up.mdx new file mode 100644 index 0000000..8a4a1d2 --- /dev/null +++ b/docs/src/content/docs/getting-started/starting-up.mdx @@ -0,0 +1,72 @@ +--- +title: Starting Up +description: A guide in my new Starlight docs site. +--- + +import { Aside } from "@astrojs/starlight/components"; +import { Icon } from 'astro-icon/components' + +In getting-started guide we'll bring up a local TrailBase instance, explore the +admin dashboard, and implement our first, small application. + +## Starting TrailBase + +The quickest way to get TrailBase up and running is to use docker: + +```bash + $ mkdir traildepot + $ docker run -p 4000:4000 --mount type=bind,source=$PWD/traildepot,target=/app/traildepot trailbase/trailbase +``` + +On first start, TrailBase will generate a `traildepot` folder in your working +directory containing its configuration, the database, secrets and a few more +things. +It will also generate a new admin user for you. The credentials will be printed +on the command line as follows: + +``` +Created new admin user: + email: 'admin@localhost' + password: '' +``` + +If you like, feel free to change the Email or password later in the dashboard. +Independently, if you ever forget your password, you can reset it using the +`trail user reset-password admin@localhost ` command. + +## The Admin Dashboard + +After successfully starting TrailBase, we can check out the admin dashboard under +[http://localhost:4000/\_/admin/](http://localhost:4000/_/admin/). +After logging in with the admin credentials from the terminal, there's a couple +of pages to explore. + +* First and maybe most importantly: the data browser + () + that let's you explore and alter both the data as well as table schemas. It + provides access to _tables_, _views_, _virtual tables_, _indexes_, _trggiers_ + as well as your TrailBase API settings. +* The simple SQL editor + () + lets you run arbitrary queries against the database and take full control. + It also lets you access SQLite features which aren't (yet) exposed via the + dashboard. +* The accounts page + () + lets you manage your registered users. +* The logs page + () + lets you see what's going on. At this early stage you're probably just seeing + your own interactions with the admin dashboard. +* The settings page + () + lets you configure instance-wide settings. + Alternatively, uou can also directly edit TrailBase's config file, however, unlike + the UI you'll need to restart the server to apply the changes. + TrailBase uses protobuf for its configuration. The schema can be + found [here](https://github.com/trailbaseio/trailbase/proto/config.proto). + +We encourage you to take a minute, click around, and maybe create a few tables. +Don't worry about breaking anything. Also note that when creating, altering, or +deleting a table a schema migration file will be created in +`traildepot/migrations`. diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx new file mode 100644 index 0000000..add020f --- /dev/null +++ b/docs/src/content/docs/index.mdx @@ -0,0 +1,167 @@ +--- +title: Welcome to TrailBase +description: Blazingly fast, single-file, open-source server for your Applications +template: splash +hero: + tagline: A blazingly fast, single-file, and open-source server for your application with APIs, auth, admin dashboard, ... + image: + file: ../../assets/logo_512.webp + actions: + - text: Documentation + link: /getting-started/starting-up + icon: right-arrow + - text: FAQ + link: /reference/faq/ + icon: external + variant: secondary +--- + +import { Image } from "astro:assets"; +import { Aside, Card, CardGrid } from "@astrojs/starlight/components"; + +import screenshot from "@/assets/screenshot.webp"; +import flutterLogo from "@/assets/flutter_logo.svg"; +import tsLogo from "@/assets/ts_logo.svg"; + +import { Duration100kInsertsChart } from "./reference/_benchmarks/benchmarks.tsx"; + + + +
+ + + + + Blazingly fast thanks to its constituents: + + * Rust: one of the lowest overhead languages, + * Axum: one of the fastest HTTP servers, + * SQLite/Libsql: one of the fastest full-SQL databases. + + TrailBase is [6-7x faster than PocketBase and 15x faster than SupaBase + needing only a fraction of the footprint](/reference/benchmarks), allowing + you to serve millions of customers from a tiny box. + + + + TrailBase is a small, single file, static binary that is incredibly easy + to deploy **consistently** across integration testing, development, pre-prod, + and production environments including edge. + Architecturally, TrailBase aims to be a simple, thin abstraction around + standards helping full or piece-meal adoption and avoiding lock-in. + + A simple architecture, both in your dependencies and your own App, will + let you move faster, more confidently and pivot when necessary. + + + + TrailBase ships with a builtin admin dashboard UI, see demo above, that + lets you quickly configure your instance and visually explore your data. + Following TrailBase's mantra of not getting in your way, the UI is + entirely optional letting you fall back to a purely config & + migration-based setup for integration tests or managing an entire fleet + of deployments. + + + + TrailBase comes with an authentication system and UI built-in supporting + both password-based and Social/OAuth (Google, Discord, ...) sign-ups. + + TrailBase authentication system follows standards and best-practices + combining short-lived, stateless JSON web tokens with long-lived stateful + refresh tokens letting you easily and efficiently authenticate your users + from any of your other back-ends relying on safe, asymmetric cryptography. + + + + Provide access to your tables and views through fast, flexible and + **type-safe** restful CRUD APIs. + Authorize users based on ACLs and SQL access rules letting you + easily build higher-level access management or moderation facilities + like groups or capabilities. + + + + Straightforward integration with any stack thanks to thin abstractions, + reliance on standards, and JSON Schema for type-safety allowing type-safe + bindings for virtually any language. + + Clients as well as code-generation examples for TypeScript and + Dart/Flutter are provided out of the box. + +
+ + TypeScript + + + Flutter + +
+
+ +
+
+ +import Roadmap from "./_roadmap.md"; + +
+
+ + +
+
+ +{/* Hero page footer */} + +
+
+ + diff --git a/docs/src/content/docs/license.mdx b/docs/src/content/docs/license.mdx new file mode 100644 index 0000000..3d6f5f6 --- /dev/null +++ b/docs/src/content/docs/license.mdx @@ -0,0 +1,108 @@ +--- +title: Functional Source License, Version 1.1, Apache 2.0 Future License +template: splash +--- + +## Abbreviation + +FSL-1.1-Apache-2.0 + +## Notice + +Copyright 2024 Sebastian Jeltsch + +## Terms and Conditions + +### Licensor ("We") + +The party offering the Software under these Terms and Conditions. + +### The Software + +The "Software" is each version of the software that we make available under +these Terms and Conditions, as indicated by our inclusion of these Terms and +Conditions with the Software. + +### License Grant + +Subject to your compliance with this License Grant and the Patents, +Redistribution and Trademark clauses below, we hereby grant you the right to +use, copy, modify, create derivative works, publicly perform, publicly display +and redistribute the Software for any Permitted Purpose identified below. + +### Permitted Purpose + +A Permitted Purpose is any purpose other than a Competing Use. A Competing Use +means making the Software available to others in a commercial product or +service that: + +1. substitutes for the Software; + +2. substitutes for any other product or service we offer using the Software + that exists as of the date we make the Software available; or + +3. offers the same or substantially similar functionality as the Software. + +Permitted Purposes specifically include using the Software: + +1. for your internal use and access; + +2. for non-commercial education; + +3. for non-commercial research; and + +4. in connection with professional services that you provide to a licensee + using the Software in accordance with these Terms and Conditions. + +### Patents + +To the extent your use for a Permitted Purpose would necessarily infringe our +patents, the license grant above includes a license under our patents. If you +make a claim against any party that the Software infringes or contributes to +the infringement of any patent, then your patent license to the Software ends +immediately. + +### Redistribution + +The Terms and Conditions apply to all copies, modifications and derivatives of +the Software. + +If you redistribute any copies, modifications or derivatives of the Software, +you must include a copy of or a link to these Terms and Conditions and not +remove any copyright notices provided in or with the Software. + +### Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR +PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT. + +IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE +SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, +EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE. + +### Trademarks + +Except for displaying the License Details and identifying us as the origin of +the Software, you have no right under these Terms and Conditions to use our +trademarks, trade names, service marks or product names. + +## Grant of Future License + +We hereby irrevocably grant you an additional license to use the Software under +the Apache License, Version 2.0 that is effective on the second anniversary of +the date we make the Software available. On or after that date, you may use the +Software under the Apache License, Version 2.0, in which case the following +will apply: + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. diff --git a/docs/src/content/docs/reference/_benchmarks/benchmarks.tsx b/docs/src/content/docs/reference/_benchmarks/benchmarks.tsx new file mode 100644 index 0000000..7b9621d --- /dev/null +++ b/docs/src/content/docs/reference/_benchmarks/benchmarks.tsx @@ -0,0 +1,378 @@ +import { type ChartData, type ChartDataset, type Tick } from "chart.js/auto"; + +import { BarChart } from "@/components/BarChart.tsx"; +import { LineChart } from "@/components/LineChart.tsx"; + +import { data as supabaseUtilization } from "./supabase_utilization"; +import { data as pocketbaseUtilization } from "./pocketbase_utilization"; +import { data as trailbaseUtilization } from "./trailbase_utilization"; + +const colors = { + supabase: "rgb(62, 207, 142)", + pocketbase0: "rgb(230, 128, 30)", + pocketbase1: "rgb(238, 175, 72)", + trailbase0: "rgb(0, 115, 170)", + trailbase1: "rgb(71, 161, 205)", + trailbase2: "rgb(146, 209, 242)", + drizzle: "rgb(249, 39, 100)", +}; + +function transformTimeTicks(factor: number = 0.5) { + return (_value: number | string, index: number): string | undefined => { + if (index % 10 === 0) { + // WARN: These are estimate time due to how we measure: periodic + // polling every 0.5s using `top` or `docker stats`, which themselves + // have sampling intervals. The actual value shouldn't matter that + // much, since we measure the actual duration in-situ. We do this + // transformation only to make the time scale more intuitive than + // just "time at sample X". + return `~${index * factor}s`; + } + }; +} + +const durations100k = [ + { + label: "SupaBase", + data: [151], + backgroundColor: colors.supabase, + }, + { + label: "PocketBase TS", + data: [67.721], + backgroundColor: colors.pocketbase0, + }, + // { + // label: "PocketBase Dart (AOT)", + // data: [62.8136], + // }, + { + label: "PocketBase Dart (JIT)", + data: [61.687], + backgroundColor: colors.pocketbase1, + }, + { + label: "TrailBase TS", + data: [16.742], + backgroundColor: colors.trailbase0, + }, + // { + // label: "TrailBase Dart (AOT)", + // data: [11.1], + // }, + { + // label: "TrailBase Dart (JIT)", + label: "TrailBase Dart", + data: [9.4247], + backgroundColor: colors.trailbase1, + }, + // { + // label: "TrailBase Dart (JIT + PGO)", + // data: [10.05], + // }, + // { + // label: "TrailBase Dart (INT PK)", + // data: [8.5249], + // backgroundColor: colors.trailbase2, + // }, + { + label: "In-process SQLite (Drizzle)", + data: [8.803], + backgroundColor: colors.drizzle, + }, +]; + +export function Duration100kInsertsChart() { + const data: ChartData<"bar"> = { + labels: ["Time [s] (lower is better)"], + datasets: durations100k as ChartDataset<"bar">[], + }; + + return ; +} + +export function PocketBaseAndTrailBaseReadLatencies() { + // 2024-10-12 + // Read 1000000 messages, took 0:00:57.952120 (limit=64) + const readTrailbaseMicroS = { + p50: 3504, + p75: 3947, + p90: 4393, + p95: 4725, + }; + + // 2024-10-12 + // Read 100000 messages, took 0:00:20.273054 (limit=64) + const readPocketbaseMicroS = { + p50: 12740, + p75: 13718, + p90: 14755, + p95: 15495, + }; + + const latenciesMs = (d: any) => + [d.p50, d.p75, d.p90, d.p95].map((p) => p / 1000); + + const data: ChartData<"bar"> = { + labels: ["p50", "p75", "p90", "p95"], + datasets: [ + { + label: "PocketBase", + data: latenciesMs(readPocketbaseMicroS), + backgroundColor: colors.pocketbase0, + }, + { + label: "TrailBase", + data: latenciesMs(readTrailbaseMicroS), + backgroundColor: colors.trailbase0, + }, + ], + }; + + return ( + + ); +} + +export function PocketBaseAndTrailBaseInsertLatencies() { + // 2024-10-12 + // Inserted 10000 messages, took 0:00:01.654810 (limit=64) + const insertTrailbaseMicroS = { + p50: 8107, + p75: 10897, + p90: 15327, + p95: 19627, + }; + // 2024-10-12 + //Inserted 10000 messages, took 0:00:07.759677 (limit=64) + const insertPocketbaseMicroS = { + p50: 28160, + p75: 58570, + p90: 108325, + p95: 157601, + }; + + const latenciesMs = (d: any) => + [d.p50, d.p75, d.p90, d.p95].map((p) => p / 1000); + + const data: ChartData<"bar"> = { + labels: ["p50", "p75", "p90", "p95"], + datasets: [ + { + label: "PocketBase", + data: latenciesMs(insertPocketbaseMicroS), + backgroundColor: colors.pocketbase0, + }, + { + label: "TrailBase", + data: latenciesMs(insertTrailbaseMicroS), + backgroundColor: colors.trailbase0, + }, + ], + }; + + return ( + + ); +} + +export function SupaBaseMemoryUsageChart() { + const data: ChartData<"line"> = { + labels: [...Array(330).keys()], + datasets: Object.keys(supabaseUtilization).map((key) => { + const data = supabaseUtilization[key].map((datum, index) => ({ + x: index, + y: datum.memUsageKb, + })); + + return { + label: key.replace("supabase-", ""), + data: data, + fill: true, + showLine: false, + pointStyle: false, + }; + }), + }; + + return ( + { + const v = value as number; + return `${(v / 1024 / 1024).toFixed(0)}`; + }, + }, + }, + x: { + ticks: { + display: true, + callback: transformTimeTicks(), + }, + }, + }} + /> + ); +} + +export function SupaBaseCpuUsageChart() { + const data: ChartData<"line"> = { + labels: [...Array(330).keys()], + datasets: Object.keys(supabaseUtilization).map((key) => { + const data = supabaseUtilization[key].map((datum, index) => ({ + x: index, + y: datum.cpuPercent ?? 0, + })); + + return { + label: key.replace("supabase-", ""), + data: data, + fill: true, + showLine: false, + pointStyle: false, + }; + }), + }; + + return ( + + ); +} + +export function PocketBaseAndTrailBaseUsageChart() { + // To roughly align start of benchmark on the time axis. + const xOffset = 3; + + const data: ChartData<"line"> = { + labels: [...Array(134).keys()], + datasets: [ + { + yAxisID: "yLeft", + label: "PocketBase CPU", + data: pocketbaseUtilization.slice(xOffset).map((datum, index) => ({ + x: index, + y: datum.cpu, + })), + borderColor: colors.pocketbase0, + backgroundColor: colors.pocketbase0, + }, + { + yAxisID: "yRight", + label: "PocketBase RSS", + data: pocketbaseUtilization.slice(xOffset).map((datum, index) => ({ + x: index, + y: datum.rss, + })), + borderColor: colors.pocketbase1, + backgroundColor: colors.pocketbase1, + }, + { + yAxisID: "yLeft", + label: "TrailBase CPU", + data: trailbaseUtilization.map((datum, index) => ({ + x: index, + y: datum.cpu, + })), + borderColor: colors.trailbase0, + backgroundColor: colors.trailbase0, + }, + { + yAxisID: "yRight", + label: "TrailBase RSS", + data: trailbaseUtilization.map((datum, index) => ({ + x: index, + y: datum.rss, + })), + borderColor: colors.trailbase1, + backgroundColor: colors.trailbase1, + }, + ], + }; + + return ( + { + const v = value as number; + return `${(v / 1024).toFixed(0)}`; + }, + }, + }, + x: { + ticks: { + display: true, + callback: transformTimeTicks(0.6), + }, + }, + }} + /> + ); +} diff --git a/docs/src/content/docs/reference/_benchmarks/pocketbase_utilization.ts b/docs/src/content/docs/reference/_benchmarks/pocketbase_utilization.ts new file mode 100644 index 0000000..3f7f11d --- /dev/null +++ b/docs/src/content/docs/reference/_benchmarks/pocketbase_utilization.ts @@ -0,0 +1,507 @@ +type Datum = { + cpu: number; + rss: number; +}; + +export const data: Datum[] = [ + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 35476, + }, + { + cpu: 0, + rss: 37140, + }, + { + cpu: 2.1, + rss: 88196, + }, + { + cpu: 3, + rss: 110108, + }, + { + cpu: 2.5, + rss: 118060, + }, + { + cpu: 2.6, + rss: 123776, + }, + { + cpu: 2.6, + rss: 127716, + }, + { + cpu: 2.3, + rss: 131548, + }, + { + cpu: 2.4, + rss: 134740, + }, + { + cpu: 2.2, + rss: 138208, + }, + { + cpu: 2.7, + rss: 139436, + }, + { + cpu: 2.818, + rss: 141788, + }, + { + cpu: 2.8, + rss: 142532, + }, + { + cpu: 2.545, + rss: 142652, + }, + { + cpu: 2.4, + rss: 142796, + }, + { + cpu: 2.182, + rss: 143012, + }, + { + cpu: 3.1, + rss: 143072, + }, + { + cpu: 2.8, + rss: 142660, + }, + { + cpu: 2.7, + rss: 142292, + }, + { + cpu: 2.2, + rss: 143560, + }, + { + cpu: 2.7, + rss: 143236, + }, + { + cpu: 3.3, + rss: 143200, + }, + { + cpu: 2.636, + rss: 143136, + }, + { + cpu: 2.8, + rss: 143068, + }, + { + cpu: 2.8, + rss: 143144, + }, + { + cpu: 2.4, + rss: 142832, + }, + { + cpu: 2.4, + rss: 143120, + }, + { + cpu: 3.2, + rss: 143020, + }, + { + cpu: 2.9, + rss: 142884, + }, + { + cpu: 2.8, + rss: 143068, + }, + { + cpu: 2.8, + rss: 143024, + }, + { + cpu: 3, + rss: 143392, + }, + { + cpu: 2.636, + rss: 143276, + }, + { + cpu: 3.2, + rss: 143264, + }, + { + cpu: 2.3, + rss: 142436, + }, + { + cpu: 2.3, + rss: 142812, + }, + { + cpu: 3.1, + rss: 142564, + }, + { + cpu: 3, + rss: 142624, + }, + { + cpu: 2.8, + rss: 143296, + }, + { + cpu: 3, + rss: 142000, + }, + { + cpu: 2.9, + rss: 142264, + }, + { + cpu: 2.8, + rss: 143004, + }, + { + cpu: 2.273, + rss: 142336, + }, + { + cpu: 2.5, + rss: 142420, + }, + { + cpu: 2.5, + rss: 142696, + }, + { + cpu: 3, + rss: 141480, + }, + { + cpu: 3.2, + rss: 142084, + }, + { + cpu: 2.455, + rss: 142428, + }, + { + cpu: 3, + rss: 144056, + }, + { + cpu: 2.9, + rss: 143800, + }, + { + cpu: 2.9, + rss: 143408, + }, + { + cpu: 2.5, + rss: 143144, + }, + { + cpu: 2.7, + rss: 143076, + }, + { + cpu: 2.6, + rss: 143080, + }, + { + cpu: 2.636, + rss: 142248, + }, + { + cpu: 2.8, + rss: 142812, + }, + { + cpu: 2.9, + rss: 143836, + }, + { + cpu: 2.8, + rss: 142564, + }, + { + cpu: 3.2, + rss: 142868, + }, + { + cpu: 2.7, + rss: 143088, + }, + { + cpu: 2.3, + rss: 143516, + }, + { + cpu: 2.6, + rss: 142912, + }, + { + cpu: 2.636, + rss: 143428, + }, + { + cpu: 2.9, + rss: 142660, + }, + { + cpu: 3.3, + rss: 143012, + }, + { + cpu: 2.9, + rss: 143404, + }, + { + cpu: 2.9, + rss: 143512, + }, + { + cpu: 2.7, + rss: 143048, + }, + { + cpu: 2.3, + rss: 142480, + }, + { + cpu: 2.545, + rss: 142628, + }, + { + cpu: 3.2, + rss: 142744, + }, + { + cpu: 2.9, + rss: 143576, + }, + { + cpu: 3, + rss: 143284, + }, + { + cpu: 3, + rss: 143588, + }, + { + cpu: 2.7, + rss: 143340, + }, + { + cpu: 2.9, + rss: 142944, + }, + { + cpu: 2.5, + rss: 142972, + }, + { + cpu: 2.7, + rss: 142940, + }, + { + cpu: 2.6, + rss: 144108, + }, + { + cpu: 2.545, + rss: 143676, + }, + { + cpu: 2.9, + rss: 143480, + }, + { + cpu: 3, + rss: 143228, + }, + { + cpu: 3, + rss: 143420, + }, + { + cpu: 3.1, + rss: 143316, + }, + { + cpu: 2.8, + rss: 143324, + }, + { + cpu: 2.6, + rss: 143376, + }, + { + cpu: 2.4, + rss: 142712, + }, + { + cpu: 2.182, + rss: 142896, + }, + { + cpu: 2.9, + rss: 143616, + }, + { + cpu: 2.8, + rss: 144012, + }, + { + cpu: 3.2, + rss: 142724, + }, + { + cpu: 3, + rss: 142240, + }, + { + cpu: 2.9, + rss: 144172, + }, + { + cpu: 3, + rss: 143712, + }, + { + cpu: 2.6, + rss: 143144, + }, + { + cpu: 2.6, + rss: 142732, + }, + { + cpu: 2.6, + rss: 142924, + }, + { + cpu: 2.9, + rss: 142632, + }, + { + cpu: 2.9, + rss: 143912, + }, + { + cpu: 2.727, + rss: 143132, + }, + { + cpu: 2.8, + rss: 143212, + }, + { + cpu: 3, + rss: 143420, + }, + { + cpu: 2.3, + rss: 143480, + }, + { + cpu: 2.6, + rss: 143212, + }, + { + cpu: 2.455, + rss: 142700, + }, + { + cpu: 2.9, + rss: 142812, + }, + { + cpu: 2.7, + rss: 143088, + }, + { + cpu: 2.8, + rss: 143492, + }, + { + cpu: 2.9, + rss: 143276, + }, + { + cpu: 3.2, + rss: 143004, + }, + { + cpu: 0, + rss: 142328, + }, + { + cpu: 0, + rss: 142328, + }, + { + cpu: 0, + rss: 142328, + }, + { + cpu: 0, + rss: 142328, + }, + { + cpu: 0.1, + rss: 142328, + }, + { + cpu: 0, + rss: 142328, + }, +]; diff --git a/docs/src/content/docs/reference/_benchmarks/supabase_utilization.ts b/docs/src/content/docs/reference/_benchmarks/supabase_utilization.ts new file mode 100644 index 0000000..6d1d20c --- /dev/null +++ b/docs/src/content/docs/reference/_benchmarks/supabase_utilization.ts @@ -0,0 +1,15343 @@ +type Datum = { + cpuPercent: number | null; + memUsageKb: number; +}; + +export const data: Record = { + "supabase-storage": [ + { + cpuPercent: 0, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0178, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0178, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0043, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0043, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.019799999999999998, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.019799999999999998, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0046, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0046, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0212, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0212, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.022000000000000002, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.022000000000000002, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021400000000000002, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021400000000000002, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021099999999999997, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021099999999999997, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0226, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0226, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.02, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.02, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0046, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0046, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0042, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0042, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0218, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0218, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0213, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0213, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0222, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0222, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0246, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0246, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021400000000000002, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021400000000000002, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0233, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0233, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.024399999999999998, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.024399999999999998, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0219, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0219, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0219, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0199, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0199, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0215, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0215, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 129126.4, + }, + { + cpuPercent: 0.021099999999999997, + memUsageKb: 128307.2, + }, + { + cpuPercent: 0.021099999999999997, + memUsageKb: 128307.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128307.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128307.2, + }, + { + cpuPercent: 0.004, + memUsageKb: 128307.2, + }, + { + cpuPercent: 0.004, + memUsageKb: 128307.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0189, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0189, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.004, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.004, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.004, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0207, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0207, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.022400000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.022400000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.023799999999999998, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.023799999999999998, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128409.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0046, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0046, + memUsageKb: 128512, + }, + { + cpuPercent: 0.022099999999999998, + memUsageKb: 128512, + }, + { + cpuPercent: 0.022099999999999998, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128512, + }, + { + cpuPercent: 0.004, + memUsageKb: 128512, + }, + { + cpuPercent: 0.004, + memUsageKb: 128512, + }, + { + cpuPercent: 0.004, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0263, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0263, + memUsageKb: 128512, + }, + { + cpuPercent: 0.004, + memUsageKb: 128512, + }, + { + cpuPercent: 0.004, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0219, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0219, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128512, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128512, + }, + { + cpuPercent: 0.004, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0231, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0231, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0233, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0233, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0151, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0151, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0022, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0022, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0022, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0022, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0022, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0022, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0028000000000000004, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.0028000000000000004, + memUsageKb: 128614.4, + }, + { + cpuPercent: 0.015700000000000002, + memUsageKb: 128716.8, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-edge-functions": [ + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: 0, + memUsageKb: 99676.16, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "realtime-dev.supabase-realtime": [ + { + cpuPercent: 0, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0311, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0311, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0042, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0042, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0075, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0075, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0333, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0333, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0053, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0053, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0388, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0388, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0146, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0146, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0206, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0206, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0097, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0097, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0361, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0361, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0070999999999999995, + memUsageKb: 260608, + }, + { + cpuPercent: 0.0070999999999999995, + memUsageKb: 260608, + }, + { + cpuPercent: 0.018799999999999997, + memUsageKb: 260608, + }, + { + cpuPercent: 0.018799999999999997, + memUsageKb: 260608, + }, + { + cpuPercent: 0.027999999999999997, + memUsageKb: 260608, + }, + { + cpuPercent: 0.027999999999999997, + memUsageKb: 260608, + }, + { + cpuPercent: 0.011899999999999999, + memUsageKb: 260608, + }, + { + cpuPercent: 0.011899999999999999, + memUsageKb: 260608, + }, + { + cpuPercent: 0.044500000000000005, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.044500000000000005, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0231, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0231, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0076, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0076, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.037000000000000005, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.037000000000000005, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0026, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0026, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0263, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0263, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.005, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.005, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.005, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0067, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0067, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0321, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0321, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0032, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0032, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0321, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0321, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0034000000000000002, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0034000000000000002, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0074, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0074, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.11259999999999999, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.11259999999999999, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0077, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0077, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0225, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0225, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0022, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0022, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0055000000000000005, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0055000000000000005, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0359, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0359, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0075, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0075, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0462, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0462, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0025, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0025, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0097, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0097, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0437, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0437, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 260710.4, + }, + { + cpuPercent: 0.0348, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0348, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0089, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0089, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0089, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0066, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0066, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0361, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0361, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.011699999999999999, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.011699999999999999, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.024300000000000002, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.024300000000000002, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.005600000000000001, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.005600000000000001, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0374, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0374, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0144, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0144, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.023399999999999997, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.023399999999999997, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0103, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0103, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0394, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.0394, + memUsageKb: 261017.6, + }, + { + cpuPercent: 0.019299999999999998, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.019299999999999998, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.015700000000000002, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.015700000000000002, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.009399999999999999, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.009399999999999999, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0087, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0087, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0362, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0362, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.027200000000000002, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.027200000000000002, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0060999999999999995, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0060999999999999995, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0077, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0077, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.006999999999999999, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.006999999999999999, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.037599999999999995, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.037599999999999995, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.037599999999999995, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0371, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0371, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0058, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0058, + memUsageKb: 260812.8, + }, + { + cpuPercent: 0.0097, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0097, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.005699999999999999, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.005699999999999999, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.036000000000000004, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.036000000000000004, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0331, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0331, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0063, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0063, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0060999999999999995, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0060999999999999995, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0033, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0033, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0421, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0421, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.024900000000000002, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.024900000000000002, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.008199999999999999, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.008199999999999999, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.008100000000000001, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.008100000000000001, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0379, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0379, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0364, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0364, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0021, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0021, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0067, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0067, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0027, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0027, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0344, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0344, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0344, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.031400000000000004, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.031400000000000004, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0077, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0077, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0091, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0091, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0069, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0069, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0342, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0342, + memUsageKb: 260915.2, + }, + { + cpuPercent: 0.0262, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0262, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0034000000000000002, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0034000000000000002, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0097, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0097, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0032, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0032, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.049800000000000004, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.049800000000000004, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.018000000000000002, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.018000000000000002, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0069, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0069, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0026, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0026, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.051500000000000004, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.051500000000000004, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0152, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.0152, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.005699999999999999, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.005699999999999999, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.0046, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.0046, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.0027, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.0027, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.0785, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.0785, + memUsageKb: 263065.6, + }, + { + cpuPercent: 0.0098, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0098, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0072, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0072, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0072, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0078000000000000005, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0078000000000000005, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0072, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0072, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.06480000000000001, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.06480000000000001, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0024, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0024, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0087, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0087, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0649, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0649, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0068000000000000005, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0068000000000000005, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0059, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0059, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0074, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0074, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.060599999999999994, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.060599999999999994, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0095, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0095, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0023, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0023, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.008, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.008, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0632, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0632, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0029, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0029, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0083, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0083, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0083, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0075, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0075, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.003, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.003, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0608, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0608, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0021, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0021, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0073, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0073, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0043, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0043, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0073, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0073, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0652, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0652, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0033, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0033, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0075, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0075, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.006999999999999999, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.006999999999999999, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0143, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0143, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.053, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.053, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0031, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0031, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0058, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0058, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0073, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0073, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.033, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.033, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.033, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.030600000000000002, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.030600000000000002, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0026, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0026, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0067, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0067, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.024700000000000003, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.024700000000000003, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0287, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0287, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0062, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0062, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0043, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0043, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0079, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.0079, + memUsageKb: 262963.2, + }, + { + cpuPercent: 0.042199999999999994, + memUsageKb: 262963.2, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-meta": [ + { + cpuPercent: 0, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0046, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0046, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0043, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0043, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.222, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.222, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.004, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.004, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.1469, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.1469, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.11259999999999999, + memUsageKb: 159334.4, + }, + { + cpuPercent: 0.11259999999999999, + memUsageKb: 159334.4, + }, + { + cpuPercent: 0.1186, + memUsageKb: 139776, + }, + { + cpuPercent: 0.1186, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0034000000000000002, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0034000000000000002, + memUsageKb: 139776, + }, + { + cpuPercent: 0.004699999999999999, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.004699999999999999, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.24239999999999998, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.24239999999999998, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.20550000000000002, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.20550000000000002, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.2041, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.2041, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0037, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.2327, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.2327, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.2457, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.2457, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0664, + memUsageKb: 149606.4, + }, + { + cpuPercent: 0.0664, + memUsageKb: 149606.4, + }, + { + cpuPercent: 0.1558, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.1558, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.2232, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.2232, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.22769999999999999, + memUsageKb: 139264, + }, + { + cpuPercent: 0.22769999999999999, + memUsageKb: 139264, + }, + { + cpuPercent: 0.004, + memUsageKb: 139264, + }, + { + cpuPercent: 0.004, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 139264, + }, + { + cpuPercent: 0.2206, + memUsageKb: 139264, + }, + { + cpuPercent: 0.2206, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139264, + }, + { + cpuPercent: 0.004, + memUsageKb: 139264, + }, + { + cpuPercent: 0.004, + memUsageKb: 139264, + }, + { + cpuPercent: 0.004, + memUsageKb: 139264, + }, + { + cpuPercent: 0.2155, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.2155, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.004, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.25120000000000003, + memUsageKb: 144281.6, + }, + { + cpuPercent: 0.25120000000000003, + memUsageKb: 144281.6, + }, + { + cpuPercent: 0.0074, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0074, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139366.4, + }, + { + cpuPercent: 0.0391, + memUsageKb: 145510.4, + }, + { + cpuPercent: 0.0391, + memUsageKb: 145510.4, + }, + { + cpuPercent: 0.1973, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.1973, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.2202, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.2202, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.004, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.004, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139468.8, + }, + { + cpuPercent: 0.2169, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.2169, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.2125, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.2125, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0040999999999999995, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.004, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.004, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139571.2, + }, + { + cpuPercent: 0.2336, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.2336, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.004, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.004, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.2238, + memUsageKb: 139878.4, + }, + { + cpuPercent: 0.2238, + memUsageKb: 139878.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0036, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139673.6, + }, + { + cpuPercent: 0.0582, + memUsageKb: 148275.2, + }, + { + cpuPercent: 0.0582, + memUsageKb: 148275.2, + }, + { + cpuPercent: 0.0582, + memUsageKb: 148275.2, + }, + { + cpuPercent: 0.1663, + memUsageKb: 139776, + }, + { + cpuPercent: 0.1663, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139776, + }, + { + cpuPercent: 0.2155, + memUsageKb: 139776, + }, + { + cpuPercent: 0.2155, + memUsageKb: 139776, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0045000000000000005, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0038, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.26530000000000004, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.26530000000000004, + memUsageKb: 138854.4, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0036, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.2273, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.2273, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0038, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0038, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0034999999999999996, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 138956.8, + }, + { + cpuPercent: 0.20800000000000002, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.20800000000000002, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.20800000000000002, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.23850000000000002, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.23850000000000002, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139059.2, + }, + { + cpuPercent: 0.1158, + memUsageKb: 154009.6, + }, + { + cpuPercent: 0.1158, + memUsageKb: 154009.6, + }, + { + cpuPercent: 0.1359, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.1359, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.004, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.004, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.2249, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.2249, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.2249, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0039000000000000003, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0037, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0038, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.14400000000000002, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.14400000000000002, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0023, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0023, + memUsageKb: 139161.6, + }, + { + cpuPercent: 0.0022, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0022, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0021, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0021, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0024, + memUsageKb: 139264, + }, + { + cpuPercent: 0.0024, + memUsageKb: 139264, + }, + { + cpuPercent: 0.1499, + memUsageKb: 139264, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-studio": [ + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0542, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0542, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0694, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0694, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0684, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0684, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0669, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0669, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.060899999999999996, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.060899999999999996, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0663, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0663, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0706, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0706, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0005, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0005, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0725, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0725, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0662, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0662, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0678, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0678, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0632, + memUsageKb: 136089.6, + }, + { + cpuPercent: 0.0632, + memUsageKb: 136089.6, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.063, + memUsageKb: 136089.6, + }, + { + cpuPercent: 0.063, + memUsageKb: 136089.6, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0642, + memUsageKb: 136192, + }, + { + cpuPercent: 0.0642, + memUsageKb: 136192, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0002, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0002, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0002, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0622, + memUsageKb: 136089.6, + }, + { + cpuPercent: 0.0622, + memUsageKb: 136089.6, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0355, + memUsageKb: 141619.2, + }, + { + cpuPercent: 0.0355, + memUsageKb: 141619.2, + }, + { + cpuPercent: 0.0346, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0346, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0409, + memUsageKb: 142336, + }, + { + cpuPercent: 0.0409, + memUsageKb: 142336, + }, + { + cpuPercent: 0.029900000000000003, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.029900000000000003, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0437, + memUsageKb: 141824, + }, + { + cpuPercent: 0.0437, + memUsageKb: 141824, + }, + { + cpuPercent: 0.030899999999999997, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.030899999999999997, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.008199999999999999, + memUsageKb: 136908.8, + }, + { + cpuPercent: 0.008199999999999999, + memUsageKb: 136908.8, + }, + { + cpuPercent: 0.051399999999999994, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.051399999999999994, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0682, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0682, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0003, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0003, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0658, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0658, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0667, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0667, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0613, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0613, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0639, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0639, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0698, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0698, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0751, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0751, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0003, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0003, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0757, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0757, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0757, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0716, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0716, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0669, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0669, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0705, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0705, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0687, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.0687, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.042300000000000004, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0.042300000000000004, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: 0, + memUsageKb: 135987.2, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-kong": [ + { + cpuPercent: 0.0001, + memUsageKb: 2112880.64, + }, + { + cpuPercent: 0.0001, + memUsageKb: 2112880.64, + }, + { + cpuPercent: 0.0024, + memUsageKb: 2112880.64, + }, + { + cpuPercent: 0.0024, + memUsageKb: 2112880.64, + }, + { + cpuPercent: 0.003, + memUsageKb: 2112880.64, + }, + { + cpuPercent: 0.003, + memUsageKb: 2112880.64, + }, + { + cpuPercent: 0.2606, + memUsageKb: 2119172.096, + }, + { + cpuPercent: 0.2606, + memUsageKb: 2119172.096, + }, + { + cpuPercent: 0.3128, + memUsageKb: 2125463.552, + }, + { + cpuPercent: 0.3128, + memUsageKb: 2125463.552, + }, + { + cpuPercent: 0.3066, + memUsageKb: 2130706.432, + }, + { + cpuPercent: 0.3066, + memUsageKb: 2130706.432, + }, + { + cpuPercent: 0.3169, + memUsageKb: 2134900.736, + }, + { + cpuPercent: 0.3169, + memUsageKb: 2134900.736, + }, + { + cpuPercent: 0.3298, + memUsageKb: 2140143.616, + }, + { + cpuPercent: 0.3298, + memUsageKb: 2140143.616, + }, + { + cpuPercent: 0.3332, + memUsageKb: 2145386.496, + }, + { + cpuPercent: 0.3332, + memUsageKb: 2145386.496, + }, + { + cpuPercent: 0.2928, + memUsageKb: 2149580.8, + }, + { + cpuPercent: 0.2928, + memUsageKb: 2149580.8, + }, + { + cpuPercent: 0.3768, + memUsageKb: 2151677.952, + }, + { + cpuPercent: 0.3768, + memUsageKb: 2151677.952, + }, + { + cpuPercent: 0.3194, + memUsageKb: 2159017.984, + }, + { + cpuPercent: 0.3194, + memUsageKb: 2159017.984, + }, + { + cpuPercent: 0.3432, + memUsageKb: 2165309.44, + }, + { + cpuPercent: 0.3432, + memUsageKb: 2165309.44, + }, + { + cpuPercent: 0.36460000000000004, + memUsageKb: 2170552.32, + }, + { + cpuPercent: 0.36460000000000004, + memUsageKb: 2170552.32, + }, + { + cpuPercent: 0.3331, + memUsageKb: 2175795.2, + }, + { + cpuPercent: 0.3331, + memUsageKb: 2175795.2, + }, + { + cpuPercent: 0.34869999999999995, + memUsageKb: 2182086.656, + }, + { + cpuPercent: 0.34869999999999995, + memUsageKb: 2182086.656, + }, + { + cpuPercent: 0.319, + memUsageKb: 2187329.536, + }, + { + cpuPercent: 0.319, + memUsageKb: 2187329.536, + }, + { + cpuPercent: 0.322, + memUsageKb: 2192572.416, + }, + { + cpuPercent: 0.322, + memUsageKb: 2192572.416, + }, + { + cpuPercent: 0.32, + memUsageKb: 2197815.296, + }, + { + cpuPercent: 0.32, + memUsageKb: 2197815.296, + }, + { + cpuPercent: 0.3521, + memUsageKb: 2203058.176, + }, + { + cpuPercent: 0.3521, + memUsageKb: 2203058.176, + }, + { + cpuPercent: 0.4495, + memUsageKb: 2208301.056, + }, + { + cpuPercent: 0.4495, + memUsageKb: 2208301.056, + }, + { + cpuPercent: 0.32530000000000003, + memUsageKb: 2213543.936, + }, + { + cpuPercent: 0.32530000000000003, + memUsageKb: 2213543.936, + }, + { + cpuPercent: 0.3037, + memUsageKb: 2218786.816, + }, + { + cpuPercent: 0.3037, + memUsageKb: 2218786.816, + }, + { + cpuPercent: 0.3262, + memUsageKb: 2224029.696, + }, + { + cpuPercent: 0.3262, + memUsageKb: 2224029.696, + }, + { + cpuPercent: 0.3486, + memUsageKb: 2230321.152, + }, + { + cpuPercent: 0.3486, + memUsageKb: 2230321.152, + }, + { + cpuPercent: 0.3486, + memUsageKb: 2230321.152, + }, + { + cpuPercent: 0.3239, + memUsageKb: 2234515.456, + }, + { + cpuPercent: 0.3239, + memUsageKb: 2234515.456, + }, + { + cpuPercent: 0.3367, + memUsageKb: 2239758.336, + }, + { + cpuPercent: 0.3367, + memUsageKb: 2239758.336, + }, + { + cpuPercent: 0.29410000000000003, + memUsageKb: 2245001.216, + }, + { + cpuPercent: 0.29410000000000003, + memUsageKb: 2245001.216, + }, + { + cpuPercent: 0.34979999999999994, + memUsageKb: 2250244.096, + }, + { + cpuPercent: 0.34979999999999994, + memUsageKb: 2250244.096, + }, + { + cpuPercent: 0.34340000000000004, + memUsageKb: 2256535.552, + }, + { + cpuPercent: 0.34340000000000004, + memUsageKb: 2256535.552, + }, + { + cpuPercent: 0.42, + memUsageKb: 2261778.432, + }, + { + cpuPercent: 0.42, + memUsageKb: 2261778.432, + }, + { + cpuPercent: 0.297, + memUsageKb: 2265972.736, + }, + { + cpuPercent: 0.297, + memUsageKb: 2265972.736, + }, + { + cpuPercent: 0.3345, + memUsageKb: 2272264.192, + }, + { + cpuPercent: 0.3345, + memUsageKb: 2272264.192, + }, + { + cpuPercent: 0.32530000000000003, + memUsageKb: 2277507.072, + }, + { + cpuPercent: 0.32530000000000003, + memUsageKb: 2277507.072, + }, + { + cpuPercent: 0.31379999999999997, + memUsageKb: 2282749.952, + }, + { + cpuPercent: 0.31379999999999997, + memUsageKb: 2282749.952, + }, + { + cpuPercent: 0.34740000000000004, + memUsageKb: 2287992.832, + }, + { + cpuPercent: 0.34740000000000004, + memUsageKb: 2287992.832, + }, + { + cpuPercent: 0.3195, + memUsageKb: 2293235.712, + }, + { + cpuPercent: 0.3195, + memUsageKb: 2293235.712, + }, + { + cpuPercent: 0.3326, + memUsageKb: 2299527.168, + }, + { + cpuPercent: 0.3326, + memUsageKb: 2299527.168, + }, + { + cpuPercent: 0.32420000000000004, + memUsageKb: 2302672.896, + }, + { + cpuPercent: 0.32420000000000004, + memUsageKb: 2302672.896, + }, + { + cpuPercent: 0.33390000000000003, + memUsageKb: 2307915.776, + }, + { + cpuPercent: 0.33390000000000003, + memUsageKb: 2307915.776, + }, + { + cpuPercent: 0.45130000000000003, + memUsageKb: 2313158.656, + }, + { + cpuPercent: 0.45130000000000003, + memUsageKb: 2313158.656, + }, + { + cpuPercent: 0.3421, + memUsageKb: 2318401.536, + }, + { + cpuPercent: 0.3421, + memUsageKb: 2318401.536, + }, + { + cpuPercent: 0.3309, + memUsageKb: 2323644.416, + }, + { + cpuPercent: 0.3309, + memUsageKb: 2323644.416, + }, + { + cpuPercent: 0.3262, + memUsageKb: 2329935.872, + }, + { + cpuPercent: 0.3262, + memUsageKb: 2329935.872, + }, + { + cpuPercent: 0.3344, + memUsageKb: 2335178.752, + }, + { + cpuPercent: 0.3344, + memUsageKb: 2335178.752, + }, + { + cpuPercent: 0.3344, + memUsageKb: 2335178.752, + }, + { + cpuPercent: 0.31329999999999997, + memUsageKb: 2339373.056, + }, + { + cpuPercent: 0.31329999999999997, + memUsageKb: 2339373.056, + }, + { + cpuPercent: 0.30920000000000003, + memUsageKb: 2344615.936, + }, + { + cpuPercent: 0.30920000000000003, + memUsageKb: 2344615.936, + }, + { + cpuPercent: 0.2966, + memUsageKb: 2348810.24, + }, + { + cpuPercent: 0.2966, + memUsageKb: 2348810.24, + }, + { + cpuPercent: 0.3132, + memUsageKb: 2355101.696, + }, + { + cpuPercent: 0.3132, + memUsageKb: 2355101.696, + }, + { + cpuPercent: 0.28190000000000004, + memUsageKb: 2359296, + }, + { + cpuPercent: 0.28190000000000004, + memUsageKb: 2359296, + }, + { + cpuPercent: 0.4122, + memUsageKb: 2364538.88, + }, + { + cpuPercent: 0.4122, + memUsageKb: 2364538.88, + }, + { + cpuPercent: 0.3206, + memUsageKb: 2369781.76, + }, + { + cpuPercent: 0.3206, + memUsageKb: 2369781.76, + }, + { + cpuPercent: 0.3126, + memUsageKb: 2375024.64, + }, + { + cpuPercent: 0.3126, + memUsageKb: 2375024.64, + }, + { + cpuPercent: 0.3148, + memUsageKb: 2379218.944, + }, + { + cpuPercent: 0.3148, + memUsageKb: 2379218.944, + }, + { + cpuPercent: 0.3282, + memUsageKb: 2384461.824, + }, + { + cpuPercent: 0.3282, + memUsageKb: 2384461.824, + }, + { + cpuPercent: 0.3431, + memUsageKb: 2389704.704, + }, + { + cpuPercent: 0.3431, + memUsageKb: 2389704.704, + }, + { + cpuPercent: 0.3215, + memUsageKb: 2394947.584, + }, + { + cpuPercent: 0.3215, + memUsageKb: 2394947.584, + }, + { + cpuPercent: 0.322, + memUsageKb: 2400190.464, + }, + { + cpuPercent: 0.322, + memUsageKb: 2400190.464, + }, + { + cpuPercent: 0.32409999999999994, + memUsageKb: 2405433.344, + }, + { + cpuPercent: 0.32409999999999994, + memUsageKb: 2405433.344, + }, + { + cpuPercent: 0.321, + memUsageKb: 2409627.648, + }, + { + cpuPercent: 0.321, + memUsageKb: 2409627.648, + }, + { + cpuPercent: 0.42219999999999996, + memUsageKb: 2415919.104, + }, + { + cpuPercent: 0.42219999999999996, + memUsageKb: 2415919.104, + }, + { + cpuPercent: 0.2615, + memUsageKb: 2418016.256, + }, + { + cpuPercent: 0.2615, + memUsageKb: 2418016.256, + }, + { + cpuPercent: 0.34659999999999996, + memUsageKb: 2425356.288, + }, + { + cpuPercent: 0.34659999999999996, + memUsageKb: 2425356.288, + }, + { + cpuPercent: 0.318, + memUsageKb: 2430599.168, + }, + { + cpuPercent: 0.318, + memUsageKb: 2430599.168, + }, + { + cpuPercent: 0.3369, + memUsageKb: 2435842.048, + }, + { + cpuPercent: 0.3369, + memUsageKb: 2435842.048, + }, + { + cpuPercent: 0.36, + memUsageKb: 2441084.928, + }, + { + cpuPercent: 0.36, + memUsageKb: 2441084.928, + }, + { + cpuPercent: 0.3563, + memUsageKb: 2446327.808, + }, + { + cpuPercent: 0.3563, + memUsageKb: 2446327.808, + }, + { + cpuPercent: 0.3563, + memUsageKb: 2446327.808, + }, + { + cpuPercent: 0.32770000000000005, + memUsageKb: 2450522.112, + }, + { + cpuPercent: 0.32770000000000005, + memUsageKb: 2450522.112, + }, + { + cpuPercent: 0.348, + memUsageKb: 2455764.992, + }, + { + cpuPercent: 0.348, + memUsageKb: 2455764.992, + }, + { + cpuPercent: 0.3381, + memUsageKb: 2459959.296, + }, + { + cpuPercent: 0.3381, + memUsageKb: 2459959.296, + }, + { + cpuPercent: 0.4092, + memUsageKb: 2464153.6, + }, + { + cpuPercent: 0.4092, + memUsageKb: 2464153.6, + }, + { + cpuPercent: 0.34020000000000006, + memUsageKb: 2469396.48, + }, + { + cpuPercent: 0.34020000000000006, + memUsageKb: 2469396.48, + }, + { + cpuPercent: 0.3325, + memUsageKb: 2473590.784, + }, + { + cpuPercent: 0.3325, + memUsageKb: 2473590.784, + }, + { + cpuPercent: 0.3232, + memUsageKb: 2478833.664, + }, + { + cpuPercent: 0.3232, + memUsageKb: 2478833.664, + }, + { + cpuPercent: 0.3232, + memUsageKb: 2484076.544, + }, + { + cpuPercent: 0.3232, + memUsageKb: 2484076.544, + }, + { + cpuPercent: 0.32, + memUsageKb: 2488270.848, + }, + { + cpuPercent: 0.32, + memUsageKb: 2488270.848, + }, + { + cpuPercent: 0.3297, + memUsageKb: 2493513.728, + }, + { + cpuPercent: 0.3297, + memUsageKb: 2493513.728, + }, + { + cpuPercent: 0.3095, + memUsageKb: 2497708.032, + }, + { + cpuPercent: 0.3095, + memUsageKb: 2497708.032, + }, + { + cpuPercent: 0.3367, + memUsageKb: 2502950.912, + }, + { + cpuPercent: 0.3367, + memUsageKb: 2502950.912, + }, + { + cpuPercent: 0.3627, + memUsageKb: 2508193.792, + }, + { + cpuPercent: 0.3627, + memUsageKb: 2508193.792, + }, + { + cpuPercent: 0.44299999999999995, + memUsageKb: 2511339.52, + }, + { + cpuPercent: 0.44299999999999995, + memUsageKb: 2511339.52, + }, + { + cpuPercent: 0.33020000000000005, + memUsageKb: 2515533.824, + }, + { + cpuPercent: 0.33020000000000005, + memUsageKb: 2515533.824, + }, + { + cpuPercent: 0.3371, + memUsageKb: 2518679.552, + }, + { + cpuPercent: 0.3371, + memUsageKb: 2518679.552, + }, + { + cpuPercent: 0.35369999999999996, + memUsageKb: 2522873.856, + }, + { + cpuPercent: 0.35369999999999996, + memUsageKb: 2522873.856, + }, + { + cpuPercent: 0.3444, + memUsageKb: 2527068.16, + }, + { + cpuPercent: 0.3444, + memUsageKb: 2527068.16, + }, + { + cpuPercent: 0.31370000000000003, + memUsageKb: 2530213.888, + }, + { + cpuPercent: 0.31370000000000003, + memUsageKb: 2530213.888, + }, + { + cpuPercent: 0.34850000000000003, + memUsageKb: 2535456.768, + }, + { + cpuPercent: 0.34850000000000003, + memUsageKb: 2535456.768, + }, + { + cpuPercent: 0.34850000000000003, + memUsageKb: 2535456.768, + }, + { + cpuPercent: 0.34850000000000003, + memUsageKb: 2538602.496, + }, + { + cpuPercent: 0.34850000000000003, + memUsageKb: 2538602.496, + }, + { + cpuPercent: 0.3417, + memUsageKb: 2540699.648, + }, + { + cpuPercent: 0.3417, + memUsageKb: 2540699.648, + }, + { + cpuPercent: 0.3419, + memUsageKb: 2543845.376, + }, + { + cpuPercent: 0.3419, + memUsageKb: 2543845.376, + }, + { + cpuPercent: 0.3836, + memUsageKb: 2546991.104, + }, + { + cpuPercent: 0.3836, + memUsageKb: 2546991.104, + }, + { + cpuPercent: 0.3933, + memUsageKb: 2550136.832, + }, + { + cpuPercent: 0.3933, + memUsageKb: 2550136.832, + }, + { + cpuPercent: 0.35100000000000003, + memUsageKb: 2553282.56, + }, + { + cpuPercent: 0.35100000000000003, + memUsageKb: 2553282.56, + }, + { + cpuPercent: 0.3643, + memUsageKb: 2555379.712, + }, + { + cpuPercent: 0.3643, + memUsageKb: 2555379.712, + }, + { + cpuPercent: 0.3932, + memUsageKb: 2558525.44, + }, + { + cpuPercent: 0.3932, + memUsageKb: 2558525.44, + }, + { + cpuPercent: 0.341, + memUsageKb: 2561671.168, + }, + { + cpuPercent: 0.341, + memUsageKb: 2561671.168, + }, + { + cpuPercent: 0.38079999999999997, + memUsageKb: 2563768.32, + }, + { + cpuPercent: 0.38079999999999997, + memUsageKb: 2563768.32, + }, + { + cpuPercent: 0.32770000000000005, + memUsageKb: 2565865.472, + }, + { + cpuPercent: 0.32770000000000005, + memUsageKb: 2565865.472, + }, + { + cpuPercent: 0.3833, + memUsageKb: 2567962.624, + }, + { + cpuPercent: 0.3833, + memUsageKb: 2567962.624, + }, + { + cpuPercent: 0.37799999999999995, + memUsageKb: 2570059.776, + }, + { + cpuPercent: 0.37799999999999995, + memUsageKb: 2570059.776, + }, + { + cpuPercent: 0.5159, + memUsageKb: 2572156.928, + }, + { + cpuPercent: 0.5159, + memUsageKb: 2572156.928, + }, + { + cpuPercent: 0.35950000000000004, + memUsageKb: 2575302.656, + }, + { + cpuPercent: 0.35950000000000004, + memUsageKb: 2575302.656, + }, + { + cpuPercent: 0.3354, + memUsageKb: 2576351.232, + }, + { + cpuPercent: 0.3354, + memUsageKb: 2576351.232, + }, + { + cpuPercent: 0.34090000000000004, + memUsageKb: 2578448.384, + }, + { + cpuPercent: 0.34090000000000004, + memUsageKb: 2578448.384, + }, + { + cpuPercent: 0.34299999999999997, + memUsageKb: 2580545.536, + }, + { + cpuPercent: 0.34299999999999997, + memUsageKb: 2580545.536, + }, + { + cpuPercent: 0.3439, + memUsageKb: 2581594.112, + }, + { + cpuPercent: 0.3439, + memUsageKb: 2581594.112, + }, + { + cpuPercent: 0.3161, + memUsageKb: 2583691.264, + }, + { + cpuPercent: 0.3161, + memUsageKb: 2583691.264, + }, + { + cpuPercent: 0.3333, + memUsageKb: 2585788.416, + }, + { + cpuPercent: 0.3333, + memUsageKb: 2585788.416, + }, + { + cpuPercent: 0.34340000000000004, + memUsageKb: 2587885.568, + }, + { + cpuPercent: 0.34340000000000004, + memUsageKb: 2587885.568, + }, + { + cpuPercent: 0.34340000000000004, + memUsageKb: 2587885.568, + }, + { + cpuPercent: 0.3372, + memUsageKb: 2587885.568, + }, + { + cpuPercent: 0.3372, + memUsageKb: 2587885.568, + }, + { + cpuPercent: 0.42829999999999996, + memUsageKb: 2589982.72, + }, + { + cpuPercent: 0.42829999999999996, + memUsageKb: 2589982.72, + }, + { + cpuPercent: 0.3136, + memUsageKb: 2592079.872, + }, + { + cpuPercent: 0.3136, + memUsageKb: 2592079.872, + }, + { + cpuPercent: 0.3211, + memUsageKb: 2594177.024, + }, + { + cpuPercent: 0.3211, + memUsageKb: 2594177.024, + }, + { + cpuPercent: 0.3236, + memUsageKb: 2596274.176, + }, + { + cpuPercent: 0.3236, + memUsageKb: 2596274.176, + }, + { + cpuPercent: 0.32170000000000004, + memUsageKb: 2599419.904, + }, + { + cpuPercent: 0.32170000000000004, + memUsageKb: 2599419.904, + }, + { + cpuPercent: 0.2937, + memUsageKb: 2601517.056, + }, + { + cpuPercent: 0.2937, + memUsageKb: 2601517.056, + }, + { + cpuPercent: 0.3005, + memUsageKb: 2603614.208, + }, + { + cpuPercent: 0.3005, + memUsageKb: 2603614.208, + }, + { + cpuPercent: 0.3361, + memUsageKb: 2605711.36, + }, + { + cpuPercent: 0.3361, + memUsageKb: 2605711.36, + }, + { + cpuPercent: 0.33630000000000004, + memUsageKb: 2608857.088, + }, + { + cpuPercent: 0.33630000000000004, + memUsageKb: 2608857.088, + }, + { + cpuPercent: 0.35090000000000005, + memUsageKb: 2612002.816, + }, + { + cpuPercent: 0.35090000000000005, + memUsageKb: 2612002.816, + }, + { + cpuPercent: 0.401, + memUsageKb: 2614099.968, + }, + { + cpuPercent: 0.401, + memUsageKb: 2614099.968, + }, + { + cpuPercent: 0.3481, + memUsageKb: 2618294.272, + }, + { + cpuPercent: 0.3481, + memUsageKb: 2618294.272, + }, + { + cpuPercent: 0.2988, + memUsageKb: 2619342.848, + }, + { + cpuPercent: 0.2988, + memUsageKb: 2619342.848, + }, + { + cpuPercent: 0.3429, + memUsageKb: 2621440, + }, + { + cpuPercent: 0.3429, + memUsageKb: 2621440, + }, + { + cpuPercent: 0.3234, + memUsageKb: 2622488.576, + }, + { + cpuPercent: 0.3234, + memUsageKb: 2622488.576, + }, + { + cpuPercent: 0.31920000000000004, + memUsageKb: 2624585.728, + }, + { + cpuPercent: 0.31920000000000004, + memUsageKb: 2624585.728, + }, + { + cpuPercent: 0.29460000000000003, + memUsageKb: 2626682.88, + }, + { + cpuPercent: 0.29460000000000003, + memUsageKb: 2626682.88, + }, + { + cpuPercent: 0.308, + memUsageKb: 2627731.456, + }, + { + cpuPercent: 0.308, + memUsageKb: 2627731.456, + }, + { + cpuPercent: 0.3148, + memUsageKb: 2629828.608, + }, + { + cpuPercent: 0.3148, + memUsageKb: 2629828.608, + }, + { + cpuPercent: 0.42090000000000005, + memUsageKb: 2637168.64, + }, + { + cpuPercent: 0.42090000000000005, + memUsageKb: 2637168.64, + }, + { + cpuPercent: 0.42090000000000005, + memUsageKb: 2637168.64, + }, + { + cpuPercent: 0.3553, + memUsageKb: 2632974.336, + }, + { + cpuPercent: 0.3553, + memUsageKb: 2632974.336, + }, + { + cpuPercent: 0.3583, + memUsageKb: 2634022.912, + }, + { + cpuPercent: 0.3583, + memUsageKb: 2634022.912, + }, + { + cpuPercent: 0.35100000000000003, + memUsageKb: 2635071.488, + }, + { + cpuPercent: 0.35100000000000003, + memUsageKb: 2635071.488, + }, + { + cpuPercent: 0.3206, + memUsageKb: 2636120.064, + }, + { + cpuPercent: 0.3206, + memUsageKb: 2636120.064, + }, + { + cpuPercent: 0.3336, + memUsageKb: 2637168.64, + }, + { + cpuPercent: 0.3336, + memUsageKb: 2637168.64, + }, + { + cpuPercent: 0.3442, + memUsageKb: 2638217.216, + }, + { + cpuPercent: 0.3442, + memUsageKb: 2638217.216, + }, + { + cpuPercent: 0.3574, + memUsageKb: 2640314.368, + }, + { + cpuPercent: 0.3574, + memUsageKb: 2640314.368, + }, + { + cpuPercent: 0.3439, + memUsageKb: 2641362.944, + }, + { + cpuPercent: 0.3439, + memUsageKb: 2641362.944, + }, + { + cpuPercent: 0.3528, + memUsageKb: 2642411.52, + }, + { + cpuPercent: 0.3528, + memUsageKb: 2642411.52, + }, + { + cpuPercent: 0.4374, + memUsageKb: 2643460.096, + }, + { + cpuPercent: 0.4374, + memUsageKb: 2643460.096, + }, + { + cpuPercent: 0.3215, + memUsageKb: 2644508.672, + }, + { + cpuPercent: 0.3215, + memUsageKb: 2644508.672, + }, + { + cpuPercent: 0.32020000000000004, + memUsageKb: 2645557.248, + }, + { + cpuPercent: 0.32020000000000004, + memUsageKb: 2645557.248, + }, + { + cpuPercent: 0.3319, + memUsageKb: 2647654.4, + }, + { + cpuPercent: 0.3319, + memUsageKb: 2647654.4, + }, + { + cpuPercent: 0.3472, + memUsageKb: 2647654.4, + }, + { + cpuPercent: 0.3472, + memUsageKb: 2647654.4, + }, + { + cpuPercent: 0.3552, + memUsageKb: 2648702.976, + }, + { + cpuPercent: 0.3552, + memUsageKb: 2648702.976, + }, + { + cpuPercent: 0.3461, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.3461, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.3461, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.3389, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.3389, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.3189, + memUsageKb: 2650800.128, + }, + { + cpuPercent: 0.3189, + memUsageKb: 2650800.128, + }, + { + cpuPercent: 0.3342, + memUsageKb: 2651848.704, + }, + { + cpuPercent: 0.3342, + memUsageKb: 2651848.704, + }, + { + cpuPercent: 0.2829, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.2829, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0017000000000000001, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0017000000000000001, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0015, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0015, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0015, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0015, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0014000000000000002, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0014000000000000002, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0014000000000000002, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0014000000000000002, + memUsageKb: 2649751.552, + }, + { + cpuPercent: 0.0013, + memUsageKb: 2649751.552, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-auth": [ + { + cpuPercent: 0, + memUsageKb: 34775.04, + }, + { + cpuPercent: 0, + memUsageKb: 34775.04, + }, + { + cpuPercent: 0.04769999999999999, + memUsageKb: 34785.28, + }, + { + cpuPercent: 0.04769999999999999, + memUsageKb: 34785.28, + }, + { + cpuPercent: 0.008199999999999999, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0.008199999999999999, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0.0181, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0.0181, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0.0001, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0.0001, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0, + memUsageKb: 34836.48, + }, + { + cpuPercent: 0.0197, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0197, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0194, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0194, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.021, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.021, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0.0197, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0197, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0187, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0187, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0189, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0189, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0, + memUsageKb: 34846.72, + }, + { + cpuPercent: 0.0184, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0184, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0187, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0187, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0202, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0202, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0, + memUsageKb: 34856.96, + }, + { + cpuPercent: 0.0173, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0173, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.019799999999999998, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.019799999999999998, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0197, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0197, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0197, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0208, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0208, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0222, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0222, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0177, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.0177, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0, + memUsageKb: 34887.68, + }, + { + cpuPercent: 0.018600000000000002, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.018600000000000002, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.018600000000000002, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.016, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.016, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.0002, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.0002, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.019, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.019, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.0189, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.0189, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.0204, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.0204, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.019799999999999998, + memUsageKb: 34918.4, + }, + { + cpuPercent: 0.019799999999999998, + memUsageKb: 34918.4, + }, + { + cpuPercent: 0, + memUsageKb: 34918.4, + }, + { + cpuPercent: 0, + memUsageKb: 34918.4, + }, + { + cpuPercent: 0, + memUsageKb: 34918.4, + }, + { + cpuPercent: 0, + memUsageKb: 34918.4, + }, + { + cpuPercent: 0, + memUsageKb: 34918.4, + }, + { + cpuPercent: 0, + memUsageKb: 34918.4, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0, + memUsageKb: 34908.16, + }, + { + cpuPercent: 0.022000000000000002, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.022000000000000002, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0196, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0196, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.023700000000000002, + memUsageKb: 35031.04, + }, + { + cpuPercent: 0.023700000000000002, + memUsageKb: 35031.04, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0184, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0184, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.018000000000000002, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.018000000000000002, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0206, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0206, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0208, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0208, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0151, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0151, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0001, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0001, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0127, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0.0127, + memUsageKb: 34959.36, + }, + { + cpuPercent: 0, + memUsageKb: 34959.36, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-rest": [ + { + cpuPercent: 0.0023, + memUsageKb: 122572.8, + }, + { + cpuPercent: 0.0023, + memUsageKb: 122572.8, + }, + { + cpuPercent: 0.0007000000000000001, + memUsageKb: 122572.8, + }, + { + cpuPercent: 0.0007000000000000001, + memUsageKb: 122572.8, + }, + { + cpuPercent: 0.008, + memUsageKb: 122572.8, + }, + { + cpuPercent: 0.008, + memUsageKb: 122572.8, + }, + { + cpuPercent: 5.4510000000000005, + memUsageKb: 123494.4, + }, + { + cpuPercent: 5.4510000000000005, + memUsageKb: 123494.4, + }, + { + cpuPercent: 7.515, + memUsageKb: 123801.6, + }, + { + cpuPercent: 7.515, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.941599999999999, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.941599999999999, + memUsageKb: 124108.8, + }, + { + cpuPercent: 7.1073, + memUsageKb: 124313.6, + }, + { + cpuPercent: 7.1073, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.7280999999999995, + memUsageKb: 123187.2, + }, + { + cpuPercent: 6.7280999999999995, + memUsageKb: 123187.2, + }, + { + cpuPercent: 6.824299999999999, + memUsageKb: 123289.6, + }, + { + cpuPercent: 6.824299999999999, + memUsageKb: 123289.6, + }, + { + cpuPercent: 7.532, + memUsageKb: 123289.6, + }, + { + cpuPercent: 7.532, + memUsageKb: 123289.6, + }, + { + cpuPercent: 4.9386, + memUsageKb: 123801.6, + }, + { + cpuPercent: 4.9386, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.198099999999999, + memUsageKb: 124518.4, + }, + { + cpuPercent: 6.198099999999999, + memUsageKb: 124518.4, + }, + { + cpuPercent: 6.644500000000001, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.644500000000001, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.5789, + memUsageKb: 125030.4, + }, + { + cpuPercent: 6.5789, + memUsageKb: 125030.4, + }, + { + cpuPercent: 6.8591, + memUsageKb: 124620.8, + }, + { + cpuPercent: 6.8591, + memUsageKb: 124620.8, + }, + { + cpuPercent: 6.5525, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.5525, + memUsageKb: 124211.2, + }, + { + cpuPercent: 7.3416, + memUsageKb: 124006.4, + }, + { + cpuPercent: 7.3416, + memUsageKb: 124006.4, + }, + { + cpuPercent: 7.3687000000000005, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.3687000000000005, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.0484, + memUsageKb: 124313.6, + }, + { + cpuPercent: 7.0484, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.1887, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.1887, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.5864, + memUsageKb: 123904, + }, + { + cpuPercent: 6.5864, + memUsageKb: 123904, + }, + { + cpuPercent: 6.9802, + memUsageKb: 123699.2, + }, + { + cpuPercent: 6.9802, + memUsageKb: 123699.2, + }, + { + cpuPercent: 7.2010000000000005, + memUsageKb: 124108.8, + }, + { + cpuPercent: 7.2010000000000005, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.9484, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.9484, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.395599999999999, + memUsageKb: 123392, + }, + { + cpuPercent: 6.395599999999999, + memUsageKb: 123392, + }, + { + cpuPercent: 6.395599999999999, + memUsageKb: 123392, + }, + { + cpuPercent: 7.3609, + memUsageKb: 125235.2, + }, + { + cpuPercent: 7.3609, + memUsageKb: 125235.2, + }, + { + cpuPercent: 6.316599999999999, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.316599999999999, + memUsageKb: 124006.4, + }, + { + cpuPercent: 7.896, + memUsageKb: 124928, + }, + { + cpuPercent: 7.896, + memUsageKb: 124928, + }, + { + cpuPercent: 6.6251, + memUsageKb: 124928, + }, + { + cpuPercent: 6.6251, + memUsageKb: 124928, + }, + { + cpuPercent: 6.3812999999999995, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.3812999999999995, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.4813, + memUsageKb: 124518.4, + }, + { + cpuPercent: 6.4813, + memUsageKb: 124518.4, + }, + { + cpuPercent: 7.0246, + memUsageKb: 124006.4, + }, + { + cpuPercent: 7.0246, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.5925, + memUsageKb: 124723.2, + }, + { + cpuPercent: 6.5925, + memUsageKb: 124723.2, + }, + { + cpuPercent: 6.704, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.704, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.9665, + memUsageKb: 124620.8, + }, + { + cpuPercent: 6.9665, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.0328, + memUsageKb: 124723.2, + }, + { + cpuPercent: 7.0328, + memUsageKb: 124723.2, + }, + { + cpuPercent: 7.056699999999999, + memUsageKb: 124928, + }, + { + cpuPercent: 7.056699999999999, + memUsageKb: 124928, + }, + { + cpuPercent: 6.902200000000001, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.902200000000001, + memUsageKb: 124211.2, + }, + { + cpuPercent: 7.3953, + memUsageKb: 124006.4, + }, + { + cpuPercent: 7.3953, + memUsageKb: 124006.4, + }, + { + cpuPercent: 7.3386000000000005, + memUsageKb: 125030.4, + }, + { + cpuPercent: 7.3386000000000005, + memUsageKb: 125030.4, + }, + { + cpuPercent: 6.5895, + memUsageKb: 125030.4, + }, + { + cpuPercent: 6.5895, + memUsageKb: 125030.4, + }, + { + cpuPercent: 7.1568, + memUsageKb: 123904, + }, + { + cpuPercent: 7.1568, + memUsageKb: 123904, + }, + { + cpuPercent: 7.0473, + memUsageKb: 124313.6, + }, + { + cpuPercent: 7.0473, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.8214999999999995, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.8214999999999995, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.4877, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.4877, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.4877, + memUsageKb: 124313.6, + }, + { + cpuPercent: 7.285900000000001, + memUsageKb: 124723.2, + }, + { + cpuPercent: 7.285900000000001, + memUsageKb: 124723.2, + }, + { + cpuPercent: 7.0164, + memUsageKb: 124928, + }, + { + cpuPercent: 7.0164, + memUsageKb: 124928, + }, + { + cpuPercent: 7.8789, + memUsageKb: 125030.4, + }, + { + cpuPercent: 7.8789, + memUsageKb: 125030.4, + }, + { + cpuPercent: 6.8986, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.8986, + memUsageKb: 124006.4, + }, + { + cpuPercent: 7.1722, + memUsageKb: 124313.6, + }, + { + cpuPercent: 7.1722, + memUsageKb: 124313.6, + }, + { + cpuPercent: 7.0626999999999995, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.0626999999999995, + memUsageKb: 124620.8, + }, + { + cpuPercent: 6.653300000000001, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.653300000000001, + memUsageKb: 124108.8, + }, + { + cpuPercent: 7.4682, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.4682, + memUsageKb: 124620.8, + }, + { + cpuPercent: 6.981599999999999, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.981599999999999, + memUsageKb: 124211.2, + }, + { + cpuPercent: 7.1088, + memUsageKb: 125235.2, + }, + { + cpuPercent: 7.1088, + memUsageKb: 125235.2, + }, + { + cpuPercent: 6.5026, + memUsageKb: 124416, + }, + { + cpuPercent: 6.5026, + memUsageKb: 124416, + }, + { + cpuPercent: 7.13, + memUsageKb: 123904, + }, + { + cpuPercent: 7.13, + memUsageKb: 123904, + }, + { + cpuPercent: 6.8833, + memUsageKb: 123392, + }, + { + cpuPercent: 6.8833, + memUsageKb: 123392, + }, + { + cpuPercent: 7.424099999999999, + memUsageKb: 124108.8, + }, + { + cpuPercent: 7.424099999999999, + memUsageKb: 124108.8, + }, + { + cpuPercent: 7.0035, + memUsageKb: 124928, + }, + { + cpuPercent: 7.0035, + memUsageKb: 124928, + }, + { + cpuPercent: 6.6013, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.6013, + memUsageKb: 124313.6, + }, + { + cpuPercent: 5.494199999999999, + memUsageKb: 124211.2, + }, + { + cpuPercent: 5.494199999999999, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.8574, + memUsageKb: 123494.4, + }, + { + cpuPercent: 6.8574, + memUsageKb: 123494.4, + }, + { + cpuPercent: 7.738300000000001, + memUsageKb: 124108.8, + }, + { + cpuPercent: 7.738300000000001, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.9263, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.9263, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.4091, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.4091, + memUsageKb: 123801.6, + }, + { + cpuPercent: 7.27, + memUsageKb: 123494.4, + }, + { + cpuPercent: 7.27, + memUsageKb: 123494.4, + }, + { + cpuPercent: 7.27, + memUsageKb: 123494.4, + }, + { + cpuPercent: 7.5438, + memUsageKb: 123596.8, + }, + { + cpuPercent: 7.5438, + memUsageKb: 123596.8, + }, + { + cpuPercent: 6.8561000000000005, + memUsageKb: 123904, + }, + { + cpuPercent: 6.8561000000000005, + memUsageKb: 123904, + }, + { + cpuPercent: 7.2033000000000005, + memUsageKb: 123801.6, + }, + { + cpuPercent: 7.2033000000000005, + memUsageKb: 123801.6, + }, + { + cpuPercent: 7.889600000000001, + memUsageKb: 124825.6, + }, + { + cpuPercent: 7.889600000000001, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.5516, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.5516, + memUsageKb: 124108.8, + }, + { + cpuPercent: 7.3026, + memUsageKb: 123801.6, + }, + { + cpuPercent: 7.3026, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.9462, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.9462, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.8298000000000005, + memUsageKb: 123392, + }, + { + cpuPercent: 6.8298000000000005, + memUsageKb: 123392, + }, + { + cpuPercent: 7.132000000000001, + memUsageKb: 124211.2, + }, + { + cpuPercent: 7.132000000000001, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.864199999999999, + memUsageKb: 124928, + }, + { + cpuPercent: 6.864199999999999, + memUsageKb: 124928, + }, + { + cpuPercent: 6.7101999999999995, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.7101999999999995, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.931799999999999, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.931799999999999, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.9380999999999995, + memUsageKb: 123392, + }, + { + cpuPercent: 6.9380999999999995, + memUsageKb: 123392, + }, + { + cpuPercent: 6.3809000000000005, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.3809000000000005, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.9635, + memUsageKb: 123699.2, + }, + { + cpuPercent: 6.9635, + memUsageKb: 123699.2, + }, + { + cpuPercent: 6.9297, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.9297, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.8013, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.8013, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.601, + memUsageKb: 123392, + }, + { + cpuPercent: 6.601, + memUsageKb: 123392, + }, + { + cpuPercent: 7.3151, + memUsageKb: 124211.2, + }, + { + cpuPercent: 7.3151, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.898, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.898, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.898, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.9572, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.9572, + memUsageKb: 124108.8, + }, + { + cpuPercent: 6.636799999999999, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.636799999999999, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.5948, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.5948, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.635, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.635, + memUsageKb: 123801.6, + }, + { + cpuPercent: 7.0016, + memUsageKb: 123699.2, + }, + { + cpuPercent: 7.0016, + memUsageKb: 123699.2, + }, + { + cpuPercent: 6.9712, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.9712, + memUsageKb: 124211.2, + }, + { + cpuPercent: 6.7277, + memUsageKb: 123392, + }, + { + cpuPercent: 6.7277, + memUsageKb: 123392, + }, + { + cpuPercent: 6.7533, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.7533, + memUsageKb: 123801.6, + }, + { + cpuPercent: 7.2961, + memUsageKb: 123392, + }, + { + cpuPercent: 7.2961, + memUsageKb: 123392, + }, + { + cpuPercent: 6.5612, + memUsageKb: 123801.6, + }, + { + cpuPercent: 6.5612, + memUsageKb: 123801.6, + }, + { + cpuPercent: 5.6952, + memUsageKb: 123699.2, + }, + { + cpuPercent: 5.6952, + memUsageKb: 123699.2, + }, + { + cpuPercent: 6.3475, + memUsageKb: 124518.4, + }, + { + cpuPercent: 6.3475, + memUsageKb: 124518.4, + }, + { + cpuPercent: 6.8290999999999995, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.8290999999999995, + memUsageKb: 124006.4, + }, + { + cpuPercent: 6.9786, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.9786, + memUsageKb: 124313.6, + }, + { + cpuPercent: 6.6979999999999995, + memUsageKb: 124518.4, + }, + { + cpuPercent: 6.6979999999999995, + memUsageKb: 124518.4, + }, + { + cpuPercent: 7.2346, + memUsageKb: 124416, + }, + { + cpuPercent: 7.2346, + memUsageKb: 124416, + }, + { + cpuPercent: 6.916799999999999, + memUsageKb: 124416, + }, + { + cpuPercent: 6.916799999999999, + memUsageKb: 124416, + }, + { + cpuPercent: 6.6924, + memUsageKb: 125440, + }, + { + cpuPercent: 6.6924, + memUsageKb: 125440, + }, + { + cpuPercent: 7.0098, + memUsageKb: 125542.4, + }, + { + cpuPercent: 7.0098, + memUsageKb: 125542.4, + }, + { + cpuPercent: 7.2993, + memUsageKb: 124518.4, + }, + { + cpuPercent: 7.2993, + memUsageKb: 124518.4, + }, + { + cpuPercent: 7.369800000000001, + memUsageKb: 125235.2, + }, + { + cpuPercent: 7.369800000000001, + memUsageKb: 125235.2, + }, + { + cpuPercent: 6.4396, + memUsageKb: 124723.2, + }, + { + cpuPercent: 6.4396, + memUsageKb: 124723.2, + }, + { + cpuPercent: 6.4396, + memUsageKb: 124723.2, + }, + { + cpuPercent: 6.945399999999999, + memUsageKb: 124518.4, + }, + { + cpuPercent: 6.945399999999999, + memUsageKb: 124518.4, + }, + { + cpuPercent: 6.8262, + memUsageKb: 125337.6, + }, + { + cpuPercent: 6.8262, + memUsageKb: 125337.6, + }, + { + cpuPercent: 6.7144, + memUsageKb: 126976, + }, + { + cpuPercent: 6.7144, + memUsageKb: 126976, + }, + { + cpuPercent: 6.5632, + memUsageKb: 125644.8, + }, + { + cpuPercent: 6.5632, + memUsageKb: 125644.8, + }, + { + cpuPercent: 6.5489, + memUsageKb: 125747.2, + }, + { + cpuPercent: 6.5489, + memUsageKb: 125747.2, + }, + { + cpuPercent: 7.063300000000001, + memUsageKb: 125235.2, + }, + { + cpuPercent: 7.063300000000001, + memUsageKb: 125235.2, + }, + { + cpuPercent: 7.2982000000000005, + memUsageKb: 124825.6, + }, + { + cpuPercent: 7.2982000000000005, + memUsageKb: 124825.6, + }, + { + cpuPercent: 7.100599999999999, + memUsageKb: 126054.4, + }, + { + cpuPercent: 7.100599999999999, + memUsageKb: 126054.4, + }, + { + cpuPercent: 6.265499999999999, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.265499999999999, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.5175, + memUsageKb: 125644.8, + }, + { + cpuPercent: 6.5175, + memUsageKb: 125644.8, + }, + { + cpuPercent: 6.8184000000000005, + memUsageKb: 125440, + }, + { + cpuPercent: 6.8184000000000005, + memUsageKb: 125440, + }, + { + cpuPercent: 6.863200000000001, + memUsageKb: 125132.8, + }, + { + cpuPercent: 6.863200000000001, + memUsageKb: 125132.8, + }, + { + cpuPercent: 5.761699999999999, + memUsageKb: 125132.8, + }, + { + cpuPercent: 5.761699999999999, + memUsageKb: 125132.8, + }, + { + cpuPercent: 7.2849, + memUsageKb: 124723.2, + }, + { + cpuPercent: 7.2849, + memUsageKb: 124723.2, + }, + { + cpuPercent: 7.2735, + memUsageKb: 124723.2, + }, + { + cpuPercent: 7.2735, + memUsageKb: 124723.2, + }, + { + cpuPercent: 7.450399999999999, + memUsageKb: 125337.6, + }, + { + cpuPercent: 7.450399999999999, + memUsageKb: 125337.6, + }, + { + cpuPercent: 7.306900000000001, + memUsageKb: 125440, + }, + { + cpuPercent: 7.306900000000001, + memUsageKb: 125440, + }, + { + cpuPercent: 7.0162, + memUsageKb: 124928, + }, + { + cpuPercent: 7.0162, + memUsageKb: 124928, + }, + { + cpuPercent: 6.882899999999999, + memUsageKb: 125132.8, + }, + { + cpuPercent: 6.882899999999999, + memUsageKb: 125132.8, + }, + { + cpuPercent: 7.2808, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.2808, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.2808, + memUsageKb: 124620.8, + }, + { + cpuPercent: 6.579400000000001, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.579400000000001, + memUsageKb: 124825.6, + }, + { + cpuPercent: 7.4912, + memUsageKb: 125235.2, + }, + { + cpuPercent: 7.4912, + memUsageKb: 125235.2, + }, + { + cpuPercent: 7.0318, + memUsageKb: 125337.6, + }, + { + cpuPercent: 7.0318, + memUsageKb: 125337.6, + }, + { + cpuPercent: 7.333600000000001, + memUsageKb: 125644.8, + }, + { + cpuPercent: 7.333600000000001, + memUsageKb: 125644.8, + }, + { + cpuPercent: 7.358300000000001, + memUsageKb: 125132.8, + }, + { + cpuPercent: 7.358300000000001, + memUsageKb: 125132.8, + }, + { + cpuPercent: 6.936, + memUsageKb: 125849.6, + }, + { + cpuPercent: 6.936, + memUsageKb: 125849.6, + }, + { + cpuPercent: 7.0741, + memUsageKb: 124928, + }, + { + cpuPercent: 7.0741, + memUsageKb: 124928, + }, + { + cpuPercent: 7.0439, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.0439, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.263, + memUsageKb: 125337.6, + }, + { + cpuPercent: 7.263, + memUsageKb: 125337.6, + }, + { + cpuPercent: 7.0471, + memUsageKb: 124928, + }, + { + cpuPercent: 7.0471, + memUsageKb: 124928, + }, + { + cpuPercent: 7.1725, + memUsageKb: 124518.4, + }, + { + cpuPercent: 7.1725, + memUsageKb: 124518.4, + }, + { + cpuPercent: 7.3908000000000005, + memUsageKb: 125440, + }, + { + cpuPercent: 7.3908000000000005, + memUsageKb: 125440, + }, + { + cpuPercent: 7.0539, + memUsageKb: 124518.4, + }, + { + cpuPercent: 7.0539, + memUsageKb: 124518.4, + }, + { + cpuPercent: 7.1299, + memUsageKb: 124928, + }, + { + cpuPercent: 7.1299, + memUsageKb: 124928, + }, + { + cpuPercent: 6.9987, + memUsageKb: 124620.8, + }, + { + cpuPercent: 6.9987, + memUsageKb: 124620.8, + }, + { + cpuPercent: 6.1738, + memUsageKb: 124928, + }, + { + cpuPercent: 6.1738, + memUsageKb: 124928, + }, + { + cpuPercent: 6.4686, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.4686, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.4686, + memUsageKb: 124825.6, + }, + { + cpuPercent: 6.6322, + memUsageKb: 123699.2, + }, + { + cpuPercent: 6.6322, + memUsageKb: 123699.2, + }, + { + cpuPercent: 7.3991999999999996, + memUsageKb: 124620.8, + }, + { + cpuPercent: 7.3991999999999996, + memUsageKb: 124620.8, + }, + { + cpuPercent: 6.7237, + memUsageKb: 124416, + }, + { + cpuPercent: 6.7237, + memUsageKb: 124416, + }, + { + cpuPercent: 3.0658, + memUsageKb: 123392, + }, + { + cpuPercent: 3.0658, + memUsageKb: 123392, + }, + { + cpuPercent: 0.0062, + memUsageKb: 123392, + }, + { + cpuPercent: 0.0062, + memUsageKb: 123392, + }, + { + cpuPercent: 0.004699999999999999, + memUsageKb: 123392, + }, + { + cpuPercent: 0.004699999999999999, + memUsageKb: 123392, + }, + { + cpuPercent: 0.0049, + memUsageKb: 123392, + }, + { + cpuPercent: 0.0049, + memUsageKb: 123392, + }, + { + cpuPercent: 0.0046, + memUsageKb: 123392, + }, + { + cpuPercent: 0.0046, + memUsageKb: 123392, + }, + { + cpuPercent: 0.0052, + memUsageKb: 123392, + }, + { + cpuPercent: 0.0052, + memUsageKb: 123392, + }, + { + cpuPercent: 0.0049, + memUsageKb: 123392, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-analytics": [ + { + cpuPercent: 0.0003, + memUsageKb: 2079326.208, + }, + { + cpuPercent: 0.0003, + memUsageKb: 2079326.208, + }, + { + cpuPercent: 0.34990000000000004, + memUsageKb: 2079326.208, + }, + { + cpuPercent: 0.34990000000000004, + memUsageKb: 2079326.208, + }, + { + cpuPercent: 0.3788, + memUsageKb: 2079326.208, + }, + { + cpuPercent: 0.3788, + memUsageKb: 2079326.208, + }, + { + cpuPercent: 0.2747, + memUsageKb: 2079326.208, + }, + { + cpuPercent: 0.2747, + memUsageKb: 2079326.208, + }, + { + cpuPercent: 0.5447, + memUsageKb: 2087714.816, + }, + { + cpuPercent: 0.5447, + memUsageKb: 2087714.816, + }, + { + cpuPercent: 0.6021, + memUsageKb: 2098200.576, + }, + { + cpuPercent: 0.6021, + memUsageKb: 2098200.576, + }, + { + cpuPercent: 0.5385, + memUsageKb: 2104492.032, + }, + { + cpuPercent: 0.5385, + memUsageKb: 2104492.032, + }, + { + cpuPercent: 0.55, + memUsageKb: 2111832.064, + }, + { + cpuPercent: 0.55, + memUsageKb: 2111832.064, + }, + { + cpuPercent: 0.6314, + memUsageKb: 2146435.072, + }, + { + cpuPercent: 0.6314, + memUsageKb: 2146435.072, + }, + { + cpuPercent: 0.5783, + memUsageKb: 1977614.336, + }, + { + cpuPercent: 0.5783, + memUsageKb: 1977614.336, + }, + { + cpuPercent: 0.6244, + memUsageKb: 1946157.056, + }, + { + cpuPercent: 0.6244, + memUsageKb: 1946157.056, + }, + { + cpuPercent: 0.5526, + memUsageKb: 1983905.792, + }, + { + cpuPercent: 0.5526, + memUsageKb: 1983905.792, + }, + { + cpuPercent: 0.5512, + memUsageKb: 1944059.904, + }, + { + cpuPercent: 0.5512, + memUsageKb: 1944059.904, + }, + { + cpuPercent: 0.5717, + memUsageKb: 1956642.816, + }, + { + cpuPercent: 0.5717, + memUsageKb: 1956642.816, + }, + { + cpuPercent: 0.6275999999999999, + memUsageKb: 1990197.248, + }, + { + cpuPercent: 0.6275999999999999, + memUsageKb: 1990197.248, + }, + { + cpuPercent: 0.6591, + memUsageKb: 1996488.704, + }, + { + cpuPercent: 0.6591, + memUsageKb: 1996488.704, + }, + { + cpuPercent: 0.7243999999999999, + memUsageKb: 2015363.072, + }, + { + cpuPercent: 0.7243999999999999, + memUsageKb: 2015363.072, + }, + { + cpuPercent: 0.5687, + memUsageKb: 2060451.84, + }, + { + cpuPercent: 0.5687, + memUsageKb: 2060451.84, + }, + { + cpuPercent: 0.6327, + memUsageKb: 2060451.84, + }, + { + cpuPercent: 0.6327, + memUsageKb: 2060451.84, + }, + { + cpuPercent: 0.6433, + memUsageKb: 2068840.448, + }, + { + cpuPercent: 0.6433, + memUsageKb: 2068840.448, + }, + { + cpuPercent: 0.713, + memUsageKb: 2027945.984, + }, + { + cpuPercent: 0.713, + memUsageKb: 2027945.984, + }, + { + cpuPercent: 0.7051999999999999, + memUsageKb: 2077229.056, + }, + { + cpuPercent: 0.7051999999999999, + memUsageKb: 2077229.056, + }, + { + cpuPercent: 0.6173, + memUsageKb: 2100297.728, + }, + { + cpuPercent: 0.6173, + memUsageKb: 2100297.728, + }, + { + cpuPercent: 0.6018, + memUsageKb: 2097152, + }, + { + cpuPercent: 0.6018, + memUsageKb: 2097152, + }, + { + cpuPercent: 0.6724, + memUsageKb: 2100297.728, + }, + { + cpuPercent: 0.6724, + memUsageKb: 2100297.728, + }, + { + cpuPercent: 0.6724, + memUsageKb: 2100297.728, + }, + { + cpuPercent: 0.7857, + memUsageKb: 2168455.168, + }, + { + cpuPercent: 0.7857, + memUsageKb: 2168455.168, + }, + { + cpuPercent: 0.6920000000000001, + memUsageKb: 2146435.072, + }, + { + cpuPercent: 0.6920000000000001, + memUsageKb: 2146435.072, + }, + { + cpuPercent: 0.6822, + memUsageKb: 2140143.616, + }, + { + cpuPercent: 0.6822, + memUsageKb: 2140143.616, + }, + { + cpuPercent: 0.6543000000000001, + memUsageKb: 2144337.92, + }, + { + cpuPercent: 0.6543000000000001, + memUsageKb: 2144337.92, + }, + { + cpuPercent: 0.6986, + memUsageKb: 2146435.072, + }, + { + cpuPercent: 0.6986, + memUsageKb: 2146435.072, + }, + { + cpuPercent: 0.6836, + memUsageKb: 2104492.032, + }, + { + cpuPercent: 0.6836, + memUsageKb: 2104492.032, + }, + { + cpuPercent: 0.7555, + memUsageKb: 2174746.624, + }, + { + cpuPercent: 0.7555, + memUsageKb: 2174746.624, + }, + { + cpuPercent: 0.5365, + memUsageKb: 2188378.112, + }, + { + cpuPercent: 0.5365, + memUsageKb: 2188378.112, + }, + { + cpuPercent: 0.8197, + memUsageKb: 2174746.624, + }, + { + cpuPercent: 0.8197, + memUsageKb: 2174746.624, + }, + { + cpuPercent: 0.6381, + memUsageKb: 2165309.44, + }, + { + cpuPercent: 0.6381, + memUsageKb: 2165309.44, + }, + { + cpuPercent: 0.7326999999999999, + memUsageKb: 2181038.08, + }, + { + cpuPercent: 0.7326999999999999, + memUsageKb: 2181038.08, + }, + { + cpuPercent: 0.7961, + memUsageKb: 2129657.856, + }, + { + cpuPercent: 0.7961, + memUsageKb: 2129657.856, + }, + { + cpuPercent: 0.6969, + memUsageKb: 2136997.888, + }, + { + cpuPercent: 0.6969, + memUsageKb: 2136997.888, + }, + { + cpuPercent: 0.6526000000000001, + memUsageKb: 2227175.424, + }, + { + cpuPercent: 0.6526000000000001, + memUsageKb: 2227175.424, + }, + { + cpuPercent: 0.7486, + memUsageKb: 2247098.368, + }, + { + cpuPercent: 0.7486, + memUsageKb: 2247098.368, + }, + { + cpuPercent: 0.7058, + memUsageKb: 2250244.096, + }, + { + cpuPercent: 0.7058, + memUsageKb: 2250244.096, + }, + { + cpuPercent: 0.7474, + memUsageKb: 2256535.552, + }, + { + cpuPercent: 0.7474, + memUsageKb: 2256535.552, + }, + { + cpuPercent: 0.6092, + memUsageKb: 2249195.52, + }, + { + cpuPercent: 0.6092, + memUsageKb: 2249195.52, + }, + { + cpuPercent: 0.7182, + memUsageKb: 2254438.4, + }, + { + cpuPercent: 0.7182, + memUsageKb: 2254438.4, + }, + { + cpuPercent: 0.6047, + memUsageKb: 2188378.112, + }, + { + cpuPercent: 0.6047, + memUsageKb: 2188378.112, + }, + { + cpuPercent: 0.6047, + memUsageKb: 2188378.112, + }, + { + cpuPercent: 0.7743000000000001, + memUsageKb: 2186280.96, + }, + { + cpuPercent: 0.7743000000000001, + memUsageKb: 2186280.96, + }, + { + cpuPercent: 0.6785, + memUsageKb: 2251292.672, + }, + { + cpuPercent: 0.6785, + memUsageKb: 2251292.672, + }, + { + cpuPercent: 0.6227, + memUsageKb: 2257584.128, + }, + { + cpuPercent: 0.6227, + memUsageKb: 2257584.128, + }, + { + cpuPercent: 0.6747, + memUsageKb: 2262827.008, + }, + { + cpuPercent: 0.6747, + memUsageKb: 2262827.008, + }, + { + cpuPercent: 0.557, + memUsageKb: 2161115.136, + }, + { + cpuPercent: 0.557, + memUsageKb: 2161115.136, + }, + { + cpuPercent: 0.7212000000000001, + memUsageKb: 2167406.592, + }, + { + cpuPercent: 0.7212000000000001, + memUsageKb: 2167406.592, + }, + { + cpuPercent: 0.6074, + memUsageKb: 2144337.92, + }, + { + cpuPercent: 0.6074, + memUsageKb: 2144337.92, + }, + { + cpuPercent: 0.7323999999999999, + memUsageKb: 2148532.224, + }, + { + cpuPercent: 0.7323999999999999, + memUsageKb: 2148532.224, + }, + { + cpuPercent: 0.628, + memUsageKb: 2156920.832, + }, + { + cpuPercent: 0.628, + memUsageKb: 2156920.832, + }, + { + cpuPercent: 0.6475, + memUsageKb: 2144337.92, + }, + { + cpuPercent: 0.6475, + memUsageKb: 2144337.92, + }, + { + cpuPercent: 0.7868, + memUsageKb: 2149580.8, + }, + { + cpuPercent: 0.7868, + memUsageKb: 2149580.8, + }, + { + cpuPercent: 0.644, + memUsageKb: 2161115.136, + }, + { + cpuPercent: 0.644, + memUsageKb: 2161115.136, + }, + { + cpuPercent: 0.7264, + memUsageKb: 2265972.736, + }, + { + cpuPercent: 0.7264, + memUsageKb: 2265972.736, + }, + { + cpuPercent: 0.7322, + memUsageKb: 2198863.872, + }, + { + cpuPercent: 0.7322, + memUsageKb: 2198863.872, + }, + { + cpuPercent: 0.6534, + memUsageKb: 2177892.352, + }, + { + cpuPercent: 0.6534, + memUsageKb: 2177892.352, + }, + { + cpuPercent: 0.7541, + memUsageKb: 2190475.264, + }, + { + cpuPercent: 0.7541, + memUsageKb: 2190475.264, + }, + { + cpuPercent: 0.6814, + memUsageKb: 2186280.96, + }, + { + cpuPercent: 0.6814, + memUsageKb: 2186280.96, + }, + { + cpuPercent: 0.5697, + memUsageKb: 2182086.656, + }, + { + cpuPercent: 0.5697, + memUsageKb: 2182086.656, + }, + { + cpuPercent: 0.7661, + memUsageKb: 2183135.232, + }, + { + cpuPercent: 0.7661, + memUsageKb: 2183135.232, + }, + { + cpuPercent: 0.6331, + memUsageKb: 2171600.896, + }, + { + cpuPercent: 0.6331, + memUsageKb: 2171600.896, + }, + { + cpuPercent: 0.7271, + memUsageKb: 2183135.232, + }, + { + cpuPercent: 0.7271, + memUsageKb: 2183135.232, + }, + { + cpuPercent: 0.7996, + memUsageKb: 2188378.112, + }, + { + cpuPercent: 0.7996, + memUsageKb: 2188378.112, + }, + { + cpuPercent: 0.7996, + memUsageKb: 2188378.112, + }, + { + cpuPercent: 0.7903, + memUsageKb: 2199912.448, + }, + { + cpuPercent: 0.7903, + memUsageKb: 2199912.448, + }, + { + cpuPercent: 0.6593000000000001, + memUsageKb: 2190475.264, + }, + { + cpuPercent: 0.6593000000000001, + memUsageKb: 2190475.264, + }, + { + cpuPercent: 0.7315, + memUsageKb: 2195718.144, + }, + { + cpuPercent: 0.7315, + memUsageKb: 2195718.144, + }, + { + cpuPercent: 0.775, + memUsageKb: 2344615.936, + }, + { + cpuPercent: 0.775, + memUsageKb: 2344615.936, + }, + { + cpuPercent: 0.715, + memUsageKb: 2258632.704, + }, + { + cpuPercent: 0.715, + memUsageKb: 2258632.704, + }, + { + cpuPercent: 0.6586, + memUsageKb: 2239758.336, + }, + { + cpuPercent: 0.6586, + memUsageKb: 2239758.336, + }, + { + cpuPercent: 0.6707, + memUsageKb: 2248146.944, + }, + { + cpuPercent: 0.6707, + memUsageKb: 2248146.944, + }, + { + cpuPercent: 0.6416, + memUsageKb: 2239758.336, + }, + { + cpuPercent: 0.6416, + memUsageKb: 2239758.336, + }, + { + cpuPercent: 0.8136, + memUsageKb: 2222981.12, + }, + { + cpuPercent: 0.8136, + memUsageKb: 2222981.12, + }, + { + cpuPercent: 0.6307, + memUsageKb: 2243952.64, + }, + { + cpuPercent: 0.6307, + memUsageKb: 2243952.64, + }, + { + cpuPercent: 0.6889, + memUsageKb: 2225078.272, + }, + { + cpuPercent: 0.6889, + memUsageKb: 2225078.272, + }, + { + cpuPercent: 0.7904000000000001, + memUsageKb: 2229272.576, + }, + { + cpuPercent: 0.7904000000000001, + memUsageKb: 2229272.576, + }, + { + cpuPercent: 0.7531, + memUsageKb: 2275409.92, + }, + { + cpuPercent: 0.7531, + memUsageKb: 2275409.92, + }, + { + cpuPercent: 0.7404000000000001, + memUsageKb: 2247098.368, + }, + { + cpuPercent: 0.7404000000000001, + memUsageKb: 2247098.368, + }, + { + cpuPercent: 0.6898000000000001, + memUsageKb: 2252341.248, + }, + { + cpuPercent: 0.6898000000000001, + memUsageKb: 2252341.248, + }, + { + cpuPercent: 0.7926000000000001, + memUsageKb: 2277507.072, + }, + { + cpuPercent: 0.7926000000000001, + memUsageKb: 2277507.072, + }, + { + cpuPercent: 0.6744, + memUsageKb: 2256535.552, + }, + { + cpuPercent: 0.6744, + memUsageKb: 2256535.552, + }, + { + cpuPercent: 0.6614, + memUsageKb: 2403336.192, + }, + { + cpuPercent: 0.6614, + memUsageKb: 2403336.192, + }, + { + cpuPercent: 0.8509, + memUsageKb: 2494562.304, + }, + { + cpuPercent: 0.8509, + memUsageKb: 2494562.304, + }, + { + cpuPercent: 0.8445999999999999, + memUsageKb: 2338324.48, + }, + { + cpuPercent: 0.8445999999999999, + memUsageKb: 2338324.48, + }, + { + cpuPercent: 0.8445999999999999, + memUsageKb: 2338324.48, + }, + { + cpuPercent: 0.5904, + memUsageKb: 2305818.624, + }, + { + cpuPercent: 0.5904, + memUsageKb: 2305818.624, + }, + { + cpuPercent: 0.5605, + memUsageKb: 2332033.024, + }, + { + cpuPercent: 0.5605, + memUsageKb: 2332033.024, + }, + { + cpuPercent: 0.7279000000000001, + memUsageKb: 2306867.2, + }, + { + cpuPercent: 0.7279000000000001, + memUsageKb: 2306867.2, + }, + { + cpuPercent: 0.58, + memUsageKb: 2291138.56, + }, + { + cpuPercent: 0.58, + memUsageKb: 2291138.56, + }, + { + cpuPercent: 0.7089, + memUsageKb: 2306867.2, + }, + { + cpuPercent: 0.7089, + memUsageKb: 2306867.2, + }, + { + cpuPercent: 0.6679, + memUsageKb: 2296381.44, + }, + { + cpuPercent: 0.6679, + memUsageKb: 2296381.44, + }, + { + cpuPercent: 0.6881999999999999, + memUsageKb: 2313158.656, + }, + { + cpuPercent: 0.6881999999999999, + memUsageKb: 2313158.656, + }, + { + cpuPercent: 0.7053, + memUsageKb: 2307915.776, + }, + { + cpuPercent: 0.7053, + memUsageKb: 2307915.776, + }, + { + cpuPercent: 0.8199, + memUsageKb: 2310012.928, + }, + { + cpuPercent: 0.8199, + memUsageKb: 2310012.928, + }, + { + cpuPercent: 0.7471, + memUsageKb: 2356150.272, + }, + { + cpuPercent: 0.7471, + memUsageKb: 2356150.272, + }, + { + cpuPercent: 0.7667, + memUsageKb: 2330984.448, + }, + { + cpuPercent: 0.7667, + memUsageKb: 2330984.448, + }, + { + cpuPercent: 0.6620999999999999, + memUsageKb: 2327838.72, + }, + { + cpuPercent: 0.6620999999999999, + memUsageKb: 2327838.72, + }, + { + cpuPercent: 0.7234999999999999, + memUsageKb: 2343567.36, + }, + { + cpuPercent: 0.7234999999999999, + memUsageKb: 2343567.36, + }, + { + cpuPercent: 0.7609, + memUsageKb: 2321547.264, + }, + { + cpuPercent: 0.7609, + memUsageKb: 2321547.264, + }, + { + cpuPercent: 0.7615000000000001, + memUsageKb: 2328887.296, + }, + { + cpuPercent: 0.7615000000000001, + memUsageKb: 2328887.296, + }, + { + cpuPercent: 0.7401000000000001, + memUsageKb: 2345664.512, + }, + { + cpuPercent: 0.7401000000000001, + memUsageKb: 2345664.512, + }, + { + cpuPercent: 0.7006999999999999, + memUsageKb: 2530213.888, + }, + { + cpuPercent: 0.7006999999999999, + memUsageKb: 2530213.888, + }, + { + cpuPercent: 0.8412000000000001, + memUsageKb: 2415919.104, + }, + { + cpuPercent: 0.8412000000000001, + memUsageKb: 2415919.104, + }, + { + cpuPercent: 0.6992, + memUsageKb: 2381316.096, + }, + { + cpuPercent: 0.6992, + memUsageKb: 2381316.096, + }, + { + cpuPercent: 0.5501, + memUsageKb: 2377121.792, + }, + { + cpuPercent: 0.5501, + memUsageKb: 2377121.792, + }, + { + cpuPercent: 0.7148, + memUsageKb: 2384461.824, + }, + { + cpuPercent: 0.7148, + memUsageKb: 2384461.824, + }, + { + cpuPercent: 0.6323, + memUsageKb: 2380267.52, + }, + { + cpuPercent: 0.6323, + memUsageKb: 2380267.52, + }, + { + cpuPercent: 0.6323, + memUsageKb: 2380267.52, + }, + { + cpuPercent: 0.7606, + memUsageKb: 2379218.944, + }, + { + cpuPercent: 0.7606, + memUsageKb: 2379218.944, + }, + { + cpuPercent: 0.8291, + memUsageKb: 2372927.488, + }, + { + cpuPercent: 0.8291, + memUsageKb: 2372927.488, + }, + { + cpuPercent: 0.7552, + memUsageKb: 2427453.44, + }, + { + cpuPercent: 0.7552, + memUsageKb: 2427453.44, + }, + { + cpuPercent: 0.6537000000000001, + memUsageKb: 2387607.552, + }, + { + cpuPercent: 0.6537000000000001, + memUsageKb: 2387607.552, + }, + { + cpuPercent: 0.7237, + memUsageKb: 2386558.976, + }, + { + cpuPercent: 0.7237, + memUsageKb: 2386558.976, + }, + { + cpuPercent: 0.6781, + memUsageKb: 2387607.552, + }, + { + cpuPercent: 0.6781, + memUsageKb: 2387607.552, + }, + { + cpuPercent: 0.774, + memUsageKb: 2392850.432, + }, + { + cpuPercent: 0.774, + memUsageKb: 2392850.432, + }, + { + cpuPercent: 0.7618, + memUsageKb: 2393899.008, + }, + { + cpuPercent: 0.7618, + memUsageKb: 2393899.008, + }, + { + cpuPercent: 0.8120999999999999, + memUsageKb: 2446327.808, + }, + { + cpuPercent: 0.8120999999999999, + memUsageKb: 2446327.808, + }, + { + cpuPercent: 0.7631999999999999, + memUsageKb: 2416967.68, + }, + { + cpuPercent: 0.7631999999999999, + memUsageKb: 2416967.68, + }, + { + cpuPercent: 0.8240000000000001, + memUsageKb: 2405433.344, + }, + { + cpuPercent: 0.8240000000000001, + memUsageKb: 2405433.344, + }, + { + cpuPercent: 0.7419, + memUsageKb: 2444230.656, + }, + { + cpuPercent: 0.7419, + memUsageKb: 2444230.656, + }, + { + cpuPercent: 0.6911, + memUsageKb: 2405433.344, + }, + { + cpuPercent: 0.6911, + memUsageKb: 2405433.344, + }, + { + cpuPercent: 0.8689, + memUsageKb: 2413821.952, + }, + { + cpuPercent: 0.8689, + memUsageKb: 2413821.952, + }, + { + cpuPercent: 0.7767000000000001, + memUsageKb: 2438987.776, + }, + { + cpuPercent: 0.7767000000000001, + memUsageKb: 2438987.776, + }, + { + cpuPercent: 0.8805, + memUsageKb: 2656043.008, + }, + { + cpuPercent: 0.8805, + memUsageKb: 2656043.008, + }, + { + cpuPercent: 0.8592, + memUsageKb: 2519728.128, + }, + { + cpuPercent: 0.8592, + memUsageKb: 2519728.128, + }, + { + cpuPercent: 0.639, + memUsageKb: 2475687.936, + }, + { + cpuPercent: 0.639, + memUsageKb: 2475687.936, + }, + { + cpuPercent: 0.502, + memUsageKb: 2471493.632, + }, + { + cpuPercent: 0.502, + memUsageKb: 2471493.632, + }, + { + cpuPercent: 0.787, + memUsageKb: 2469396.48, + }, + { + cpuPercent: 0.787, + memUsageKb: 2469396.48, + }, + { + cpuPercent: 0.787, + memUsageKb: 2469396.48, + }, + { + cpuPercent: 0.7484999999999999, + memUsageKb: 2478833.664, + }, + { + cpuPercent: 0.7484999999999999, + memUsageKb: 2478833.664, + }, + { + cpuPercent: 0.9120999999999999, + memUsageKb: 2528116.736, + }, + { + cpuPercent: 0.9120999999999999, + memUsageKb: 2528116.736, + }, + { + cpuPercent: 0.7403, + memUsageKb: 2487222.272, + }, + { + cpuPercent: 0.7403, + memUsageKb: 2487222.272, + }, + { + cpuPercent: 0.8059000000000001, + memUsageKb: 2535456.768, + }, + { + cpuPercent: 0.8059000000000001, + memUsageKb: 2535456.768, + }, + { + cpuPercent: 0.7117, + memUsageKb: 2487222.272, + }, + { + cpuPercent: 0.7117, + memUsageKb: 2487222.272, + }, + { + cpuPercent: 0.8903, + memUsageKb: 2478833.664, + }, + { + cpuPercent: 0.8903, + memUsageKb: 2478833.664, + }, + { + cpuPercent: 0.7193999999999999, + memUsageKb: 2488270.848, + }, + { + cpuPercent: 0.7193999999999999, + memUsageKb: 2488270.848, + }, + { + cpuPercent: 0.47869999999999996, + memUsageKb: 2437939.2, + }, + { + cpuPercent: 0.47869999999999996, + memUsageKb: 2437939.2, + }, + { + cpuPercent: 1.0264, + memUsageKb: 2499805.184, + }, + { + cpuPercent: 1.0264, + memUsageKb: 2499805.184, + }, + { + cpuPercent: 0.8217, + memUsageKb: 2492465.152, + }, + { + cpuPercent: 0.8217, + memUsageKb: 2492465.152, + }, + { + cpuPercent: 0.6928, + memUsageKb: 2289041.408, + }, + { + cpuPercent: 0.6928, + memUsageKb: 2289041.408, + }, + { + cpuPercent: 0.9349, + memUsageKb: 2501902.336, + }, + { + cpuPercent: 0.9349, + memUsageKb: 2501902.336, + }, + { + cpuPercent: 0.6809999999999999, + memUsageKb: 2502950.912, + }, + { + cpuPercent: 0.6809999999999999, + memUsageKb: 2502950.912, + }, + { + cpuPercent: 0.7722, + memUsageKb: 2502950.912, + }, + { + cpuPercent: 0.7722, + memUsageKb: 2502950.912, + }, + { + cpuPercent: 0.6617000000000001, + memUsageKb: 2505048.064, + }, + { + cpuPercent: 0.6617000000000001, + memUsageKb: 2505048.064, + }, + { + cpuPercent: 0.8517, + memUsageKb: 2500853.76, + }, + { + cpuPercent: 0.8517, + memUsageKb: 2500853.76, + }, + { + cpuPercent: 0.7594, + memUsageKb: 2503999.488, + }, + { + cpuPercent: 0.7594, + memUsageKb: 2503999.488, + }, + { + cpuPercent: 0.7474, + memUsageKb: 2509242.368, + }, + { + cpuPercent: 0.7474, + memUsageKb: 2509242.368, + }, + { + cpuPercent: 0.7474, + memUsageKb: 2509242.368, + }, + { + cpuPercent: 0.8697, + memUsageKb: 2769289.216, + }, + { + cpuPercent: 0.8697, + memUsageKb: 2769289.216, + }, + { + cpuPercent: 0.6163000000000001, + memUsageKb: 2537553.92, + }, + { + cpuPercent: 0.6163000000000001, + memUsageKb: 2537553.92, + }, + { + cpuPercent: 0.7704000000000001, + memUsageKb: 2582642.688, + }, + { + cpuPercent: 0.7704000000000001, + memUsageKb: 2582642.688, + }, + { + cpuPercent: 0.3479, + memUsageKb: 2577399.808, + }, + { + cpuPercent: 0.3479, + memUsageKb: 2577399.808, + }, + { + cpuPercent: 0.3417, + memUsageKb: 2217738.24, + }, + { + cpuPercent: 0.3417, + memUsageKb: 2217738.24, + }, + { + cpuPercent: 0.3986, + memUsageKb: 2212495.36, + }, + { + cpuPercent: 0.3986, + memUsageKb: 2212495.36, + }, + { + cpuPercent: 0.3189, + memUsageKb: 2211446.784, + }, + { + cpuPercent: 0.3189, + memUsageKb: 2211446.784, + }, + { + cpuPercent: 0.33590000000000003, + memUsageKb: 2211446.784, + }, + { + cpuPercent: 0.33590000000000003, + memUsageKb: 2211446.784, + }, + { + cpuPercent: 0.32289999999999996, + memUsageKb: 2210398.208, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-db": [ + { + cpuPercent: 0.0003, + memUsageKb: 410419.2, + }, + { + cpuPercent: 0.0003, + memUsageKb: 410419.2, + }, + { + cpuPercent: 0.2738, + memUsageKb: 411136, + }, + { + cpuPercent: 0.2738, + memUsageKb: 411136, + }, + { + cpuPercent: 0.2944, + memUsageKb: 414003.2, + }, + { + cpuPercent: 0.2944, + memUsageKb: 414003.2, + }, + { + cpuPercent: 0.6394, + memUsageKb: 439296, + }, + { + cpuPercent: 0.6394, + memUsageKb: 439296, + }, + { + cpuPercent: 0.6523, + memUsageKb: 438476.8, + }, + { + cpuPercent: 0.6523, + memUsageKb: 438476.8, + }, + { + cpuPercent: 0.7079000000000001, + memUsageKb: 438476.8, + }, + { + cpuPercent: 0.7079000000000001, + memUsageKb: 438476.8, + }, + { + cpuPercent: 0.6388, + memUsageKb: 439500.8, + }, + { + cpuPercent: 0.6388, + memUsageKb: 439500.8, + }, + { + cpuPercent: 0.6716, + memUsageKb: 438988.8, + }, + { + cpuPercent: 0.6716, + memUsageKb: 438988.8, + }, + { + cpuPercent: 0.6779000000000001, + memUsageKb: 439705.6, + }, + { + cpuPercent: 0.6779000000000001, + memUsageKb: 439705.6, + }, + { + cpuPercent: 0.5957, + memUsageKb: 447590.4, + }, + { + cpuPercent: 0.5957, + memUsageKb: 447590.4, + }, + { + cpuPercent: 0.6731999999999999, + memUsageKb: 447897.6, + }, + { + cpuPercent: 0.6731999999999999, + memUsageKb: 447897.6, + }, + { + cpuPercent: 0.6221, + memUsageKb: 448204.8, + }, + { + cpuPercent: 0.6221, + memUsageKb: 448204.8, + }, + { + cpuPercent: 0.6494, + memUsageKb: 448409.6, + }, + { + cpuPercent: 0.6494, + memUsageKb: 448409.6, + }, + { + cpuPercent: 0.6849, + memUsageKb: 449024, + }, + { + cpuPercent: 0.6849, + memUsageKb: 449024, + }, + { + cpuPercent: 0.645, + memUsageKb: 450560, + }, + { + cpuPercent: 0.645, + memUsageKb: 450560, + }, + { + cpuPercent: 0.7167, + memUsageKb: 450355.2, + }, + { + cpuPercent: 0.7167, + memUsageKb: 450355.2, + }, + { + cpuPercent: 0.6301, + memUsageKb: 449945.6, + }, + { + cpuPercent: 0.6301, + memUsageKb: 449945.6, + }, + { + cpuPercent: 0.6274000000000001, + memUsageKb: 449945.6, + }, + { + cpuPercent: 0.6274000000000001, + memUsageKb: 449945.6, + }, + { + cpuPercent: 0.6162, + memUsageKb: 450048, + }, + { + cpuPercent: 0.6162, + memUsageKb: 450048, + }, + { + cpuPercent: 0.6607, + memUsageKb: 450662.4, + }, + { + cpuPercent: 0.6607, + memUsageKb: 450662.4, + }, + { + cpuPercent: 0.7099, + memUsageKb: 451072, + }, + { + cpuPercent: 0.7099, + memUsageKb: 451072, + }, + { + cpuPercent: 0.6386, + memUsageKb: 451481.6, + }, + { + cpuPercent: 0.6386, + memUsageKb: 451481.6, + }, + { + cpuPercent: 0.6109, + memUsageKb: 451584, + }, + { + cpuPercent: 0.6109, + memUsageKb: 451584, + }, + { + cpuPercent: 1.0002, + memUsageKb: 452710.4, + }, + { + cpuPercent: 1.0002, + memUsageKb: 452710.4, + }, + { + cpuPercent: 1.0002, + memUsageKb: 452710.4, + }, + { + cpuPercent: 0.6728000000000001, + memUsageKb: 452710.4, + }, + { + cpuPercent: 0.6728000000000001, + memUsageKb: 452710.4, + }, + { + cpuPercent: 0.7143999999999999, + memUsageKb: 453222.4, + }, + { + cpuPercent: 0.7143999999999999, + memUsageKb: 453222.4, + }, + { + cpuPercent: 0.6566, + memUsageKb: 453324.8, + }, + { + cpuPercent: 0.6566, + memUsageKb: 453324.8, + }, + { + cpuPercent: 0.5898, + memUsageKb: 454041.6, + }, + { + cpuPercent: 0.5898, + memUsageKb: 454041.6, + }, + { + cpuPercent: 0.6912, + memUsageKb: 453939.2, + }, + { + cpuPercent: 0.6912, + memUsageKb: 453939.2, + }, + { + cpuPercent: 0.6566, + memUsageKb: 454246.4, + }, + { + cpuPercent: 0.6566, + memUsageKb: 454246.4, + }, + { + cpuPercent: 0.652, + memUsageKb: 447488, + }, + { + cpuPercent: 0.652, + memUsageKb: 447488, + }, + { + cpuPercent: 0.5947, + memUsageKb: 453324.8, + }, + { + cpuPercent: 0.5947, + memUsageKb: 453324.8, + }, + { + cpuPercent: 0.6533, + memUsageKb: 453324.8, + }, + { + cpuPercent: 0.6533, + memUsageKb: 453324.8, + }, + { + cpuPercent: 0.6244, + memUsageKb: 453939.2, + }, + { + cpuPercent: 0.6244, + memUsageKb: 453939.2, + }, + { + cpuPercent: 0.6134000000000001, + memUsageKb: 455065.6, + }, + { + cpuPercent: 0.6134000000000001, + memUsageKb: 455065.6, + }, + { + cpuPercent: 0.7304, + memUsageKb: 454963.2, + }, + { + cpuPercent: 0.7304, + memUsageKb: 454963.2, + }, + { + cpuPercent: 0.6225999999999999, + memUsageKb: 455577.6, + }, + { + cpuPercent: 0.6225999999999999, + memUsageKb: 455577.6, + }, + { + cpuPercent: 0.6531999999999999, + memUsageKb: 455782.4, + }, + { + cpuPercent: 0.6531999999999999, + memUsageKb: 455782.4, + }, + { + cpuPercent: 0.6406000000000001, + memUsageKb: 459264, + }, + { + cpuPercent: 0.6406000000000001, + memUsageKb: 459264, + }, + { + cpuPercent: 0.6666, + memUsageKb: 458956.8, + }, + { + cpuPercent: 0.6666, + memUsageKb: 458956.8, + }, + { + cpuPercent: 0.7178, + memUsageKb: 459468.8, + }, + { + cpuPercent: 0.7178, + memUsageKb: 459468.8, + }, + { + cpuPercent: 0.6746, + memUsageKb: 460492.8, + }, + { + cpuPercent: 0.6746, + memUsageKb: 460492.8, + }, + { + cpuPercent: 0.6557999999999999, + memUsageKb: 460800, + }, + { + cpuPercent: 0.6557999999999999, + memUsageKb: 460800, + }, + { + cpuPercent: 0.6283, + memUsageKb: 462028.8, + }, + { + cpuPercent: 0.6283, + memUsageKb: 462028.8, + }, + { + cpuPercent: 0.6431999999999999, + memUsageKb: 461619.2, + }, + { + cpuPercent: 0.6431999999999999, + memUsageKb: 461619.2, + }, + { + cpuPercent: 0.6431999999999999, + memUsageKb: 461619.2, + }, + { + cpuPercent: 0.6859999999999999, + memUsageKb: 462233.6, + }, + { + cpuPercent: 0.6859999999999999, + memUsageKb: 462233.6, + }, + { + cpuPercent: 0.6086, + memUsageKb: 462438.4, + }, + { + cpuPercent: 0.6086, + memUsageKb: 462438.4, + }, + { + cpuPercent: 0.5899, + memUsageKb: 462438.4, + }, + { + cpuPercent: 0.5899, + memUsageKb: 462438.4, + }, + { + cpuPercent: 0.6063000000000001, + memUsageKb: 463155.2, + }, + { + cpuPercent: 0.6063000000000001, + memUsageKb: 463155.2, + }, + { + cpuPercent: 0.5665, + memUsageKb: 463564.8, + }, + { + cpuPercent: 0.5665, + memUsageKb: 463564.8, + }, + { + cpuPercent: 0.667, + memUsageKb: 464281.6, + }, + { + cpuPercent: 0.667, + memUsageKb: 464281.6, + }, + { + cpuPercent: 0.6385000000000001, + memUsageKb: 463872, + }, + { + cpuPercent: 0.6385000000000001, + memUsageKb: 463872, + }, + { + cpuPercent: 0.6379, + memUsageKb: 464281.6, + }, + { + cpuPercent: 0.6379, + memUsageKb: 464281.6, + }, + { + cpuPercent: 0.6165999999999999, + memUsageKb: 464896, + }, + { + cpuPercent: 0.6165999999999999, + memUsageKb: 464896, + }, + { + cpuPercent: 0.655, + memUsageKb: 464588.8, + }, + { + cpuPercent: 0.655, + memUsageKb: 464588.8, + }, + { + cpuPercent: 0.7437, + memUsageKb: 465715.2, + }, + { + cpuPercent: 0.7437, + memUsageKb: 465715.2, + }, + { + cpuPercent: 0.6462, + memUsageKb: 464998.4, + }, + { + cpuPercent: 0.6462, + memUsageKb: 464998.4, + }, + { + cpuPercent: 0.6598999999999999, + memUsageKb: 466022.4, + }, + { + cpuPercent: 0.6598999999999999, + memUsageKb: 466022.4, + }, + { + cpuPercent: 0.6498, + memUsageKb: 465510.4, + }, + { + cpuPercent: 0.6498, + memUsageKb: 465510.4, + }, + { + cpuPercent: 0.6225, + memUsageKb: 466636.8, + }, + { + cpuPercent: 0.6225, + memUsageKb: 466636.8, + }, + { + cpuPercent: 0.6579, + memUsageKb: 466022.4, + }, + { + cpuPercent: 0.6579, + memUsageKb: 466022.4, + }, + { + cpuPercent: 0.5274, + memUsageKb: 466432, + }, + { + cpuPercent: 0.5274, + memUsageKb: 466432, + }, + { + cpuPercent: 0.626, + memUsageKb: 466841.6, + }, + { + cpuPercent: 0.626, + memUsageKb: 466841.6, + }, + { + cpuPercent: 0.6154999999999999, + memUsageKb: 467660.8, + }, + { + cpuPercent: 0.6154999999999999, + memUsageKb: 467660.8, + }, + { + cpuPercent: 0.662, + memUsageKb: 467148.8, + }, + { + cpuPercent: 0.662, + memUsageKb: 467148.8, + }, + { + cpuPercent: 0.748, + memUsageKb: 467968, + }, + { + cpuPercent: 0.748, + memUsageKb: 467968, + }, + { + cpuPercent: 0.748, + memUsageKb: 467968, + }, + { + cpuPercent: 0.6711, + memUsageKb: 467865.6, + }, + { + cpuPercent: 0.6711, + memUsageKb: 467865.6, + }, + { + cpuPercent: 0.6278, + memUsageKb: 468275.2, + }, + { + cpuPercent: 0.6278, + memUsageKb: 468275.2, + }, + { + cpuPercent: 0.645, + memUsageKb: 469299.2, + }, + { + cpuPercent: 0.645, + memUsageKb: 469299.2, + }, + { + cpuPercent: 0.6378, + memUsageKb: 469504, + }, + { + cpuPercent: 0.6378, + memUsageKb: 469504, + }, + { + cpuPercent: 0.6328, + memUsageKb: 469196.8, + }, + { + cpuPercent: 0.6328, + memUsageKb: 469196.8, + }, + { + cpuPercent: 0.6246, + memUsageKb: 469913.6, + }, + { + cpuPercent: 0.6246, + memUsageKb: 469913.6, + }, + { + cpuPercent: 0.6386, + memUsageKb: 470220.8, + }, + { + cpuPercent: 0.6386, + memUsageKb: 470220.8, + }, + { + cpuPercent: 0.6107, + memUsageKb: 469811.2, + }, + { + cpuPercent: 0.6107, + memUsageKb: 469811.2, + }, + { + cpuPercent: 0.6253, + memUsageKb: 470937.6, + }, + { + cpuPercent: 0.6253, + memUsageKb: 470937.6, + }, + { + cpuPercent: 0.6929000000000001, + memUsageKb: 471654.4, + }, + { + cpuPercent: 0.6929000000000001, + memUsageKb: 471654.4, + }, + { + cpuPercent: 0.6336999999999999, + memUsageKb: 471142.4, + }, + { + cpuPercent: 0.6336999999999999, + memUsageKb: 471142.4, + }, + { + cpuPercent: 0.5957, + memUsageKb: 471654.4, + }, + { + cpuPercent: 0.5957, + memUsageKb: 471654.4, + }, + { + cpuPercent: 0.6249, + memUsageKb: 472678.4, + }, + { + cpuPercent: 0.6249, + memUsageKb: 472678.4, + }, + { + cpuPercent: 0.6453, + memUsageKb: 472985.6, + }, + { + cpuPercent: 0.6453, + memUsageKb: 472985.6, + }, + { + cpuPercent: 0.6868000000000001, + memUsageKb: 472780.8, + }, + { + cpuPercent: 0.6868000000000001, + memUsageKb: 472780.8, + }, + { + cpuPercent: 0.6655, + memUsageKb: 479129.6, + }, + { + cpuPercent: 0.6655, + memUsageKb: 479129.6, + }, + { + cpuPercent: 0.7781, + memUsageKb: 474419.2, + }, + { + cpuPercent: 0.7781, + memUsageKb: 474419.2, + }, + { + cpuPercent: 0.649, + memUsageKb: 474112, + }, + { + cpuPercent: 0.649, + memUsageKb: 474112, + }, + { + cpuPercent: 0.6537999999999999, + memUsageKb: 473600, + }, + { + cpuPercent: 0.6537999999999999, + memUsageKb: 473600, + }, + { + cpuPercent: 0.6845, + memUsageKb: 474316.8, + }, + { + cpuPercent: 0.6845, + memUsageKb: 474316.8, + }, + { + cpuPercent: 0.6589, + memUsageKb: 474726.4, + }, + { + cpuPercent: 0.6589, + memUsageKb: 474726.4, + }, + { + cpuPercent: 0.6589, + memUsageKb: 474726.4, + }, + { + cpuPercent: 0.6362, + memUsageKb: 474624, + }, + { + cpuPercent: 0.6362, + memUsageKb: 474624, + }, + { + cpuPercent: 0.6043, + memUsageKb: 475545.6, + }, + { + cpuPercent: 0.6043, + memUsageKb: 475545.6, + }, + { + cpuPercent: 0.603, + memUsageKb: 475238.4, + }, + { + cpuPercent: 0.603, + memUsageKb: 475238.4, + }, + { + cpuPercent: 0.5559000000000001, + memUsageKb: 475648, + }, + { + cpuPercent: 0.5559000000000001, + memUsageKb: 475648, + }, + { + cpuPercent: 0.6189, + memUsageKb: 475750.4, + }, + { + cpuPercent: 0.6189, + memUsageKb: 475750.4, + }, + { + cpuPercent: 0.5713, + memUsageKb: 476364.8, + }, + { + cpuPercent: 0.5713, + memUsageKb: 476364.8, + }, + { + cpuPercent: 0.625, + memUsageKb: 475852.8, + }, + { + cpuPercent: 0.625, + memUsageKb: 475852.8, + }, + { + cpuPercent: 0.6531999999999999, + memUsageKb: 477388.8, + }, + { + cpuPercent: 0.6531999999999999, + memUsageKb: 477388.8, + }, + { + cpuPercent: 0.6559, + memUsageKb: 478105.6, + }, + { + cpuPercent: 0.6559, + memUsageKb: 478105.6, + }, + { + cpuPercent: 0.6541, + memUsageKb: 477081.6, + }, + { + cpuPercent: 0.6541, + memUsageKb: 477081.6, + }, + { + cpuPercent: 0.5623, + memUsageKb: 477491.2, + }, + { + cpuPercent: 0.5623, + memUsageKb: 477491.2, + }, + { + cpuPercent: 0.6665000000000001, + memUsageKb: 477798.4, + }, + { + cpuPercent: 0.6665000000000001, + memUsageKb: 477798.4, + }, + { + cpuPercent: 0.6336999999999999, + memUsageKb: 477696, + }, + { + cpuPercent: 0.6336999999999999, + memUsageKb: 477696, + }, + { + cpuPercent: 0.7311, + memUsageKb: 479334.4, + }, + { + cpuPercent: 0.7311, + memUsageKb: 479334.4, + }, + { + cpuPercent: 0.6564, + memUsageKb: 480256, + }, + { + cpuPercent: 0.6564, + memUsageKb: 480256, + }, + { + cpuPercent: 0.6448999999999999, + memUsageKb: 478924.8, + }, + { + cpuPercent: 0.6448999999999999, + memUsageKb: 478924.8, + }, + { + cpuPercent: 0.6351, + memUsageKb: 479027.2, + }, + { + cpuPercent: 0.6351, + memUsageKb: 479027.2, + }, + { + cpuPercent: 0.6193, + memUsageKb: 479539.2, + }, + { + cpuPercent: 0.6193, + memUsageKb: 479539.2, + }, + { + cpuPercent: 0.7127, + memUsageKb: 479846.4, + }, + { + cpuPercent: 0.7127, + memUsageKb: 479846.4, + }, + { + cpuPercent: 0.6078, + memUsageKb: 480256, + }, + { + cpuPercent: 0.6078, + memUsageKb: 480256, + }, + { + cpuPercent: 0.6119, + memUsageKb: 480051.2, + }, + { + cpuPercent: 0.6119, + memUsageKb: 480051.2, + }, + { + cpuPercent: 0.6382, + memUsageKb: 480358.4, + }, + { + cpuPercent: 0.6382, + memUsageKb: 480358.4, + }, + { + cpuPercent: 0.6382, + memUsageKb: 480358.4, + }, + { + cpuPercent: 0.6346, + memUsageKb: 480870.4, + }, + { + cpuPercent: 0.6346, + memUsageKb: 480870.4, + }, + { + cpuPercent: 0.6881999999999999, + memUsageKb: 481280, + }, + { + cpuPercent: 0.6881999999999999, + memUsageKb: 481280, + }, + { + cpuPercent: 0.632, + memUsageKb: 481382.4, + }, + { + cpuPercent: 0.632, + memUsageKb: 481382.4, + }, + { + cpuPercent: 0.6347999999999999, + memUsageKb: 481280, + }, + { + cpuPercent: 0.6347999999999999, + memUsageKb: 481280, + }, + { + cpuPercent: 0.64, + memUsageKb: 481689.6, + }, + { + cpuPercent: 0.64, + memUsageKb: 481689.6, + }, + { + cpuPercent: 0.6351, + memUsageKb: 482713.6, + }, + { + cpuPercent: 0.6351, + memUsageKb: 482713.6, + }, + { + cpuPercent: 0.6644, + memUsageKb: 482201.6, + }, + { + cpuPercent: 0.6644, + memUsageKb: 482201.6, + }, + { + cpuPercent: 0.59, + memUsageKb: 482611.2, + }, + { + cpuPercent: 0.59, + memUsageKb: 482611.2, + }, + { + cpuPercent: 0.6461, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.6461, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.6542, + memUsageKb: 483430.4, + }, + { + cpuPercent: 0.6542, + memUsageKb: 483430.4, + }, + { + cpuPercent: 0.6869, + memUsageKb: 483123.2, + }, + { + cpuPercent: 0.6869, + memUsageKb: 483123.2, + }, + { + cpuPercent: 0.6077, + memUsageKb: 482713.6, + }, + { + cpuPercent: 0.6077, + memUsageKb: 482713.6, + }, + { + cpuPercent: 0.6345000000000001, + memUsageKb: 483737.6, + }, + { + cpuPercent: 0.6345000000000001, + memUsageKb: 483737.6, + }, + { + cpuPercent: 0.5525, + memUsageKb: 483225.6, + }, + { + cpuPercent: 0.5525, + memUsageKb: 483225.6, + }, + { + cpuPercent: 0.6448, + memUsageKb: 483532.8, + }, + { + cpuPercent: 0.6448, + memUsageKb: 483532.8, + }, + { + cpuPercent: 0.6058, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.6058, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.6774, + memUsageKb: 483430.4, + }, + { + cpuPercent: 0.6774, + memUsageKb: 483430.4, + }, + { + cpuPercent: 0.5785, + memUsageKb: 483225.6, + }, + { + cpuPercent: 0.5785, + memUsageKb: 483225.6, + }, + { + cpuPercent: 0.611, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.611, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.625, + memUsageKb: 483840, + }, + { + cpuPercent: 0.625, + memUsageKb: 483840, + }, + { + cpuPercent: 0.625, + memUsageKb: 483840, + }, + { + cpuPercent: 0.6273, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.6273, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.6478, + memUsageKb: 483225.6, + }, + { + cpuPercent: 0.6478, + memUsageKb: 483225.6, + }, + { + cpuPercent: 0.6496999999999999, + memUsageKb: 483532.8, + }, + { + cpuPercent: 0.6496999999999999, + memUsageKb: 483532.8, + }, + { + cpuPercent: 0.6261, + memUsageKb: 483430.4, + }, + { + cpuPercent: 0.6261, + memUsageKb: 483430.4, + }, + { + cpuPercent: 0.5893999999999999, + memUsageKb: 482918.4, + }, + { + cpuPercent: 0.5893999999999999, + memUsageKb: 482918.4, + }, + { + cpuPercent: 0.5954, + memUsageKb: 483123.2, + }, + { + cpuPercent: 0.5954, + memUsageKb: 483123.2, + }, + { + cpuPercent: 0.6999, + memUsageKb: 482918.4, + }, + { + cpuPercent: 0.6999, + memUsageKb: 482918.4, + }, + { + cpuPercent: 0.6706, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.6706, + memUsageKb: 483020.8, + }, + { + cpuPercent: 0.6247, + memUsageKb: 483840, + }, + { + cpuPercent: 0.6247, + memUsageKb: 483840, + }, + { + cpuPercent: 0.643, + memUsageKb: 483328, + }, + { + cpuPercent: 0.643, + memUsageKb: 483328, + }, + { + cpuPercent: 0.5916, + memUsageKb: 483123.2, + }, + { + cpuPercent: 0.5916, + memUsageKb: 483123.2, + }, + { + cpuPercent: 0.9490999999999999, + memUsageKb: 518246.4, + }, + { + cpuPercent: 0.9490999999999999, + memUsageKb: 518246.4, + }, + { + cpuPercent: 0.9478, + memUsageKb: 483532.8, + }, + { + cpuPercent: 0.9478, + memUsageKb: 483532.8, + }, + { + cpuPercent: 0.6048, + memUsageKb: 483737.6, + }, + { + cpuPercent: 0.6048, + memUsageKb: 483737.6, + }, + { + cpuPercent: 0.644, + memUsageKb: 483328, + }, + { + cpuPercent: 0.644, + memUsageKb: 483328, + }, + { + cpuPercent: 0.6485, + memUsageKb: 483328, + }, + { + cpuPercent: 0.6485, + memUsageKb: 483328, + }, + { + cpuPercent: 0.7028, + memUsageKb: 483328, + }, + { + cpuPercent: 0.7028, + memUsageKb: 483328, + }, + { + cpuPercent: 0.7028, + memUsageKb: 483328, + }, + { + cpuPercent: 0.618, + memUsageKb: 483430.4, + }, + { + cpuPercent: 0.618, + memUsageKb: 483430.4, + }, + { + cpuPercent: 0.5779, + memUsageKb: 483840, + }, + { + cpuPercent: 0.5779, + memUsageKb: 483840, + }, + { + cpuPercent: 0.6301, + memUsageKb: 483840, + }, + { + cpuPercent: 0.6301, + memUsageKb: 483840, + }, + { + cpuPercent: 0.40990000000000004, + memUsageKb: 491622.4, + }, + { + cpuPercent: 0.40990000000000004, + memUsageKb: 491622.4, + }, + { + cpuPercent: 0.2556, + memUsageKb: 489062.4, + }, + { + cpuPercent: 0.2556, + memUsageKb: 489062.4, + }, + { + cpuPercent: 0.1816, + memUsageKb: 489267.2, + }, + { + cpuPercent: 0.1816, + memUsageKb: 489267.2, + }, + { + cpuPercent: 0.1888, + memUsageKb: 489779.2, + }, + { + cpuPercent: 0.1888, + memUsageKb: 489779.2, + }, + { + cpuPercent: 0.1981, + memUsageKb: 489369.6, + }, + { + cpuPercent: 0.1981, + memUsageKb: 489369.6, + }, + { + cpuPercent: 0.21309999999999998, + memUsageKb: 489984, + }, + { + cpuPercent: 0.21309999999999998, + memUsageKb: 489984, + }, + { + cpuPercent: 0.2673, + memUsageKb: 489574.4, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-vector": [ + { + cpuPercent: 0.0001, + memUsageKb: 188416, + }, + { + cpuPercent: 0.0001, + memUsageKb: 188416, + }, + { + cpuPercent: 0.0079, + memUsageKb: 188108.8, + }, + { + cpuPercent: 0.0079, + memUsageKb: 188108.8, + }, + { + cpuPercent: 0.0248, + memUsageKb: 188211.2, + }, + { + cpuPercent: 0.0248, + memUsageKb: 188211.2, + }, + { + cpuPercent: 0.1439, + memUsageKb: 188416, + }, + { + cpuPercent: 0.1439, + memUsageKb: 188416, + }, + { + cpuPercent: 0.1948, + memUsageKb: 188518.4, + }, + { + cpuPercent: 0.1948, + memUsageKb: 188518.4, + }, + { + cpuPercent: 0.1841, + memUsageKb: 188518.4, + }, + { + cpuPercent: 0.1841, + memUsageKb: 188518.4, + }, + { + cpuPercent: 0.1977, + memUsageKb: 189030.4, + }, + { + cpuPercent: 0.1977, + memUsageKb: 189030.4, + }, + { + cpuPercent: 0.2206, + memUsageKb: 189644.8, + }, + { + cpuPercent: 0.2206, + memUsageKb: 189644.8, + }, + { + cpuPercent: 0.2023, + memUsageKb: 189440, + }, + { + cpuPercent: 0.2023, + memUsageKb: 189440, + }, + { + cpuPercent: 0.1746, + memUsageKb: 189235.2, + }, + { + cpuPercent: 0.1746, + memUsageKb: 189235.2, + }, + { + cpuPercent: 0.1664, + memUsageKb: 189235.2, + }, + { + cpuPercent: 0.1664, + memUsageKb: 189235.2, + }, + { + cpuPercent: 0.1753, + memUsageKb: 189030.4, + }, + { + cpuPercent: 0.1753, + memUsageKb: 189030.4, + }, + { + cpuPercent: 0.2271, + memUsageKb: 189132.8, + }, + { + cpuPercent: 0.2271, + memUsageKb: 189132.8, + }, + { + cpuPercent: 0.2157, + memUsageKb: 189132.8, + }, + { + cpuPercent: 0.2157, + memUsageKb: 189132.8, + }, + { + cpuPercent: 0.196, + memUsageKb: 190054.4, + }, + { + cpuPercent: 0.196, + memUsageKb: 190054.4, + }, + { + cpuPercent: 0.20579999999999998, + memUsageKb: 191283.2, + }, + { + cpuPercent: 0.20579999999999998, + memUsageKb: 191283.2, + }, + { + cpuPercent: 0.193, + memUsageKb: 191488, + }, + { + cpuPercent: 0.193, + memUsageKb: 191488, + }, + { + cpuPercent: 0.2065, + memUsageKb: 191283.2, + }, + { + cpuPercent: 0.2065, + memUsageKb: 191283.2, + }, + { + cpuPercent: 0.1868, + memUsageKb: 190976, + }, + { + cpuPercent: 0.1868, + memUsageKb: 190976, + }, + { + cpuPercent: 0.20929999999999999, + memUsageKb: 191590.4, + }, + { + cpuPercent: 0.20929999999999999, + memUsageKb: 191590.4, + }, + { + cpuPercent: 0.19699999999999998, + memUsageKb: 191180.8, + }, + { + cpuPercent: 0.19699999999999998, + memUsageKb: 191180.8, + }, + { + cpuPercent: 0.18710000000000002, + memUsageKb: 192819.2, + }, + { + cpuPercent: 0.18710000000000002, + memUsageKb: 192819.2, + }, + { + cpuPercent: 0.2, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.2, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1856, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1856, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.2007, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.2007, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.2007, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1886, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1886, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1978, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1978, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1984, + memUsageKb: 193024, + }, + { + cpuPercent: 0.1984, + memUsageKb: 193024, + }, + { + cpuPercent: 0.20309999999999997, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.20309999999999997, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.2078, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.2078, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1805, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1805, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1838, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1838, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.2192, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.2192, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1898, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1898, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.18989999999999999, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.18989999999999999, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.20559999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.20559999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1883, + memUsageKb: 193228.8, + }, + { + cpuPercent: 0.1883, + memUsageKb: 193228.8, + }, + { + cpuPercent: 0.2151, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.2151, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1873, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1873, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.19269999999999998, + memUsageKb: 193536, + }, + { + cpuPercent: 0.19269999999999998, + memUsageKb: 193536, + }, + { + cpuPercent: 0.2026, + memUsageKb: 193536, + }, + { + cpuPercent: 0.2026, + memUsageKb: 193536, + }, + { + cpuPercent: 0.209, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.209, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.21559999999999999, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.21559999999999999, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1954, + memUsageKb: 192819.2, + }, + { + cpuPercent: 0.1954, + memUsageKb: 192819.2, + }, + { + cpuPercent: 0.2002, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.2002, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.2002, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1841, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1841, + memUsageKb: 193536, + }, + { + cpuPercent: 0.18359999999999999, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.18359999999999999, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1985, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1985, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1891, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.1891, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.16670000000000001, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.16670000000000001, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1917, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1917, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1891, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1891, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.2165, + memUsageKb: 193536, + }, + { + cpuPercent: 0.2165, + memUsageKb: 193536, + }, + { + cpuPercent: 0.18739999999999998, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.18739999999999998, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.18969999999999998, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.18969999999999998, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1975, + memUsageKb: 193024, + }, + { + cpuPercent: 0.1975, + memUsageKb: 193024, + }, + { + cpuPercent: 0.1891, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1891, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.21239999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.21239999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1884, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1884, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.19079999999999997, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.19079999999999997, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.18059999999999998, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.18059999999999998, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.16949999999999998, + memUsageKb: 193536, + }, + { + cpuPercent: 0.16949999999999998, + memUsageKb: 193536, + }, + { + cpuPercent: 0.2194, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.2194, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1856, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.1856, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.20370000000000002, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.20370000000000002, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.20079999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.20079999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.2032, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.2032, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.2032, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.2043, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.2043, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1883, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1883, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.193, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.193, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1747, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1747, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1973, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1973, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.2094, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.2094, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.187, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.187, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.187, + memUsageKb: 193536, + }, + { + cpuPercent: 0.187, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1857, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1857, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.203, + memUsageKb: 194150.4, + }, + { + cpuPercent: 0.203, + memUsageKb: 194150.4, + }, + { + cpuPercent: 0.1973, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1973, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.183, + memUsageKb: 194252.8, + }, + { + cpuPercent: 0.183, + memUsageKb: 194252.8, + }, + { + cpuPercent: 0.19469999999999998, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.19469999999999998, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.187, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.187, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1797, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1797, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.20129999999999998, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.20129999999999998, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.2025, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.2025, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.1967, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.1967, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.18239999999999998, + memUsageKb: 194252.8, + }, + { + cpuPercent: 0.18239999999999998, + memUsageKb: 194252.8, + }, + { + cpuPercent: 0.1946, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1946, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1946, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.20800000000000002, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.20800000000000002, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1772, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1772, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1812, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.1812, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.1499, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1499, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1981, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1981, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1999, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1999, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1916, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1916, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1971, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.1971, + memUsageKb: 193945.6, + }, + { + cpuPercent: 0.17579999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.17579999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1906, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1906, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.19440000000000002, + memUsageKb: 193536, + }, + { + cpuPercent: 0.19440000000000002, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1972, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1972, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1844, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1844, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.20370000000000002, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.20370000000000002, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.20579999999999998, + memUsageKb: 193536, + }, + { + cpuPercent: 0.20579999999999998, + memUsageKb: 193536, + }, + { + cpuPercent: 0.2163, + memUsageKb: 193228.8, + }, + { + cpuPercent: 0.2163, + memUsageKb: 193228.8, + }, + { + cpuPercent: 0.1961, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1961, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1932, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1932, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1924, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1924, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1895, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1895, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.20440000000000003, + memUsageKb: 193536, + }, + { + cpuPercent: 0.20440000000000003, + memUsageKb: 193536, + }, + { + cpuPercent: 0.191, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.191, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.191, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.19510000000000002, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.19510000000000002, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1972, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1972, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1894, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1894, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.21289999999999998, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.21289999999999998, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1883, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1883, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1889, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1889, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1779, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1779, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1818, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1818, + memUsageKb: 193536, + }, + { + cpuPercent: 0.2066, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.2066, + memUsageKb: 193126.4, + }, + { + cpuPercent: 0.1989, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1989, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.21059999999999998, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.21059999999999998, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1746, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1746, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1971, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1971, + memUsageKb: 193536, + }, + { + cpuPercent: 0.19870000000000002, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.19870000000000002, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.19940000000000002, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.19940000000000002, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1934, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1934, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1884, + memUsageKb: 194150.4, + }, + { + cpuPercent: 0.1884, + memUsageKb: 194150.4, + }, + { + cpuPercent: 0.192, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.192, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1739, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1739, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.19469999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.19469999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.19469999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1918, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1918, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.17809999999999998, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.17809999999999998, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.2107, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.2107, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.19879999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.19879999999999998, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1834, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1834, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.18960000000000002, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.18960000000000002, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.19260000000000002, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.19260000000000002, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.2163, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.2163, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1948, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1948, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.19, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.19, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1804, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1804, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1813, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.1813, + memUsageKb: 193433.6, + }, + { + cpuPercent: 0.20329999999999998, + memUsageKb: 193536, + }, + { + cpuPercent: 0.20329999999999998, + memUsageKb: 193536, + }, + { + cpuPercent: 0.187, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.187, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1912, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.1912, + memUsageKb: 193843.2, + }, + { + cpuPercent: 0.2025, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.2025, + memUsageKb: 193331.2, + }, + { + cpuPercent: 0.1979, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1979, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1979, + memUsageKb: 193536, + }, + { + cpuPercent: 0.2045, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.2045, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.183, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.183, + memUsageKb: 193638.4, + }, + { + cpuPercent: 0.1859, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1859, + memUsageKb: 193740.8, + }, + { + cpuPercent: 0.1082, + memUsageKb: 193536, + }, + { + cpuPercent: 0.1082, + memUsageKb: 193536, + }, + { + cpuPercent: 0.0075, + memUsageKb: 193536, + }, + { + cpuPercent: 0.0075, + memUsageKb: 193536, + }, + { + cpuPercent: 0.0199, + memUsageKb: 193536, + }, + { + cpuPercent: 0.0199, + memUsageKb: 193536, + }, + { + cpuPercent: 0.006999999999999999, + memUsageKb: 193536, + }, + { + cpuPercent: 0.006999999999999999, + memUsageKb: 193536, + }, + { + cpuPercent: 0.0069, + memUsageKb: 193536, + }, + { + cpuPercent: 0.0069, + memUsageKb: 193536, + }, + { + cpuPercent: 0.0072, + memUsageKb: 193536, + }, + { + cpuPercent: 0.0072, + memUsageKb: 193536, + }, + { + cpuPercent: 0.0059, + memUsageKb: 193536, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], + "supabase-imgproxy": [ + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.068, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.068, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.006, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.006, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.07139999999999999, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.07139999999999999, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0621, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0.0621, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0.0085, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0085, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0.061500000000000006, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.061500000000000006, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0641, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0641, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0063, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0.0063, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0.06309999999999999, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.06309999999999999, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.056900000000000006, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.056900000000000006, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0074, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0.0074, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0.0767, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0767, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0719, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0719, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0719, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.006, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.006, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.062, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.062, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.064, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.064, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0085, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0.0085, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87193.6, + }, + { + cpuPercent: 0, + memUsageKb: 87193.6, + }, + { + cpuPercent: 0.0638, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0638, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0.0699, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0699, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0085, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0.0085, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0.0654, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0654, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0647, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0647, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0063, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0.0063, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87193.6, + }, + { + cpuPercent: 0, + memUsageKb: 87193.6, + }, + { + cpuPercent: 0.0693, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0693, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0663, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0663, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0060999999999999995, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0.0060999999999999995, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0.0060999999999999995, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0, + memUsageKb: 87203.84, + }, + { + cpuPercent: 0.0751, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0751, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.06709999999999999, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0.06709999999999999, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0.0126, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0126, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.0712, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0712, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0756, + memUsageKb: 87265.28, + }, + { + cpuPercent: 0.0756, + memUsageKb: 87265.28, + }, + { + cpuPercent: 0.011899999999999999, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0.011899999999999999, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87224.32, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0, + memUsageKb: 87214.08, + }, + { + cpuPercent: 0.06559999999999999, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.06559999999999999, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0676, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0.0676, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0.0052, + memUsageKb: 87285.76, + }, + { + cpuPercent: 0.0052, + memUsageKb: 87285.76, + }, + { + cpuPercent: 0, + memUsageKb: 87285.76, + }, + { + cpuPercent: 0, + memUsageKb: 87285.76, + }, + { + cpuPercent: 0, + memUsageKb: 87285.76, + }, + { + cpuPercent: 0, + memUsageKb: 87285.76, + }, + { + cpuPercent: 0, + memUsageKb: 87275.52, + }, + { + cpuPercent: 0, + memUsageKb: 87275.52, + }, + { + cpuPercent: 0.0694, + memUsageKb: 87418.88, + }, + { + cpuPercent: 0.0694, + memUsageKb: 87418.88, + }, + { + cpuPercent: 0, + memUsageKb: 87306.24, + }, + { + cpuPercent: 0, + memUsageKb: 87306.24, + }, + { + cpuPercent: 0, + memUsageKb: 87296, + }, + { + cpuPercent: 0, + memUsageKb: 87296, + }, + { + cpuPercent: 0, + memUsageKb: 87296, + }, + { + cpuPercent: 0, + memUsageKb: 87296, + }, + { + cpuPercent: 0, + memUsageKb: 87296, + }, + { + cpuPercent: 0, + memUsageKb: 87296, + }, + { + cpuPercent: 0.0672, + memUsageKb: 99215.36, + }, + { + cpuPercent: 0.0672, + memUsageKb: 99215.36, + }, + { + cpuPercent: 0.0182, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0182, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0681, + memUsageKb: 87377.92, + }, + { + cpuPercent: 0.0681, + memUsageKb: 87377.92, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0886, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0886, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0, + memUsageKb: 87234.56, + }, + { + cpuPercent: 0.0742, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0.0742, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0697, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0697, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: 0.0616, + memUsageKb: 87623.68, + }, + { + cpuPercent: 0.0616, + memUsageKb: 87623.68, + }, + { + cpuPercent: 0, + memUsageKb: 87265.28, + }, + { + cpuPercent: 0, + memUsageKb: 87265.28, + }, + { + cpuPercent: 0, + memUsageKb: 87265.28, + }, + { + cpuPercent: 0, + memUsageKb: 87265.28, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0, + memUsageKb: 87255.04, + }, + { + cpuPercent: 0.054000000000000006, + memUsageKb: 87429.12, + }, + { + cpuPercent: 0.054000000000000006, + memUsageKb: 87429.12, + }, + { + cpuPercent: 0, + memUsageKb: 87244.8, + }, + { + cpuPercent: null, + memUsageKb: 0, + }, + ], +}; diff --git a/docs/src/content/docs/reference/_benchmarks/trailbase_utilization.ts b/docs/src/content/docs/reference/_benchmarks/trailbase_utilization.ts new file mode 100644 index 0000000..70380e5 --- /dev/null +++ b/docs/src/content/docs/reference/_benchmarks/trailbase_utilization.ts @@ -0,0 +1,143 @@ +type Datum = { + cpu: number; + rss: number; +}; + +export const data: Datum[] = [ + { + cpu: 0, + rss: 53640, + }, + { + cpu: 0, + rss: 53640, + }, + { + cpu: 0, + rss: 53640, + }, + { + cpu: 0, + rss: 53640, + }, + { + cpu: 0, + rss: 53640, + }, + { + cpu: 0, + rss: 53640, + }, + { + cpu: 0, + rss: 53640, + }, + { + cpu: 0, + rss: 53640, + }, + { + cpu: 1.2, + rss: 100256, + }, + { + cpu: 2.273, + rss: 70444, + }, + { + cpu: 3.1, + rss: 71984, + }, + { + cpu: 3.1, + rss: 74032, + }, + { + cpu: 3.2, + rss: 76436, + }, + { + cpu: 3.2, + rss: 79124, + }, + { + cpu: 3.2, + rss: 83760, + }, + { + cpu: 3.2, + rss: 86192, + }, + { + cpu: 3.2, + rss: 95820, + }, + { + cpu: 3.2, + rss: 103000, + }, + { + cpu: 3.2, + rss: 111724, + }, + { + cpu: 3.2, + rss: 116524, + }, + { + cpu: 3.2, + rss: 116748, + }, + { + cpu: 1.2, + rss: 110208, + }, + { + cpu: 0.7, + rss: 111360, + }, + { + cpu: 0.636, + rss: 112768, + }, + { + cpu: 0.6, + rss: 113024, + }, + { + cpu: 0.6, + rss: 113024, + }, + { + cpu: 0.5, + rss: 113024, + }, + { + cpu: 0.5, + rss: 112844, + }, + { + cpu: 0, + rss: 112844, + }, + { + cpu: 0, + rss: 112844, + }, + { + cpu: 0, + rss: 112844, + }, + { + cpu: 0, + rss: 112844, + }, + { + cpu: 0, + rss: 112844, + }, + { + cpu: 0, + rss: 112844, + }, +]; diff --git a/docs/src/content/docs/reference/_sql.mdx b/docs/src/content/docs/reference/_sql.mdx new file mode 100644 index 0000000..c763286 --- /dev/null +++ b/docs/src/content/docs/reference/_sql.mdx @@ -0,0 +1,74 @@ +--- +title: SQL +description: A short intro to SQL. +--- + +SQL is a functional general-purpose query language for relational databases. It +is as old as relational databases themselves. +It allows to define arbitrary data look-ups and computations w/o hard-coding a +specific database implementation or storage structure (presence of indexes, +storage layout, ...). +Yet many foster a love-hate relationship with it, which has given rise to an +entire cottage industry of ORMs: higher-level, often type-safe abstractions +with bindings for your favorite programming language. +They tend to work great until you need to break glass. In recent years, there +has been a push to thinner and thinner abstractions. + +Instead of hiding or working around SQL, TrailBase embraces it as an evergreen, +transferable skill. +There's no denying that SQL can get tricky but it's +also its greatest strength. SQL is a general purpose functional (sometimes +imperative) programming language that lets you solve arbitrary problems in a +high-level, portable fashion. In other words, learning SQL is a lot more useful +than learning a specific ORM or similar abstractions. + +One thing that's pretty sweet about SQL is that, almost any relational database +(Postgres, MySQL, MS SQL, sqlite, ...) supports some dialect of SQL, which +makes this a pretty transferable skill. This is only possible because SQL is +pretty abstract. Given a lookup or transformation, different databases might +execute them quite differently depending on their capabilities, how the data +structures are set up, and how the look is expressed. All of this is facilitate +through the magic of the query-planner, which takes your query and turns it +into a physical execution plan. + +## A gentle introduction + +At first glance, SQL may look just like some antiquated filter language but in +practice it's a high-level, functional programming language that is optimized +for table transformations. All that SQLs does is: + +1. inserting rows (INSERT), +2. removing rows (DELETE), +3. updating rows (UPDATE), +4. and transforming NxM tables into PxQ tables (SELECT). + +5. to 3. are pretty simple, they operate on rows. + +SELECT is by far the most complex tool, think of it as writing a function that +takes in one or more table, even combined tables, filters them, and them +transforms them into a new table. They might look overwhelming at first: + +```sql +SELECT + Output: outcol0, outcol1, .. +FROM + Input: incol0, incol1, +WHERE Filter: e.g. where incol0 > 10 +ORDER BY outcol0 ASC +GROUP BY aggregation +; +``` + +but most of it is optional. The simplest statement is `SELECT 1;`, it creates a +new table with one row and one column containing the value of `1` (a scalar) +from nothing. + +Now that we can create a new column from thin air, let's transform it: + +```sql +SELECT col*2 FROM (SELECT 1 as col); +``` + +Now we created two nested SELECTs, inner one creates the table we already know +but names the column `col` and the outer SELECT transforms that table into a +new 1x1 table with the values doubled. diff --git a/docs/src/content/docs/reference/benchmarks.mdx b/docs/src/content/docs/reference/benchmarks.mdx new file mode 100644 index 0000000..4fc1768 --- /dev/null +++ b/docs/src/content/docs/reference/benchmarks.mdx @@ -0,0 +1,207 @@ +--- +title: Benchmarks +description: Performance comparison with similar products. +--- + +import { + Duration100kInsertsChart, + PocketBaseAndTrailBaseReadLatencies, + PocketBaseAndTrailBaseInsertLatencies, + SupaBaseMemoryUsageChart, + SupaBaseCpuUsageChart, + PocketBaseAndTrailBaseUsageChart, +} from "./_benchmarks/benchmarks.tsx"; + +TrailBase is merely the sum of its parts. It's the result of marrying one of +the lowest-overhead languages, one of the fastest HTTP servers, and one of the +lightest relational SQL databases, while merely avoiding extra expenditures. +We did expect it to go fast but how fast exactly? Let's take a brief look at +how TrailBase performs compared to a few amazing, and more weathered +alternatives such as SupaBase, PocketBase, and vanilla SQLite. + +## Disclaimer + +In general, benchmarks are tricky, both to do well and to interpret. +Benchmarks never show how fast something can theoretically go but merely how +fast the author managed to make it go. +Micro-benchmarks, especially, offer a selective key-hole insights, which may be +biased and may or may not apply to your workload. + +Performance also doesn't exist in a vacuum. If something is super fast but +doesn't do what you need it to do, performance is an illusive luxury. +Doing less makes it naturally easier to go fast, which is not a bad thing, +however means that comparing a highly specialized solution to a more general +one on a specific aspect can be misleading or "unfair". +Specifically, PocketBase and SupaBase have both been around for longer offering +a different and in many cases more comprehensive features. + +We tried our hardest to give all contenders the best chance to go fast [^1]. +We were surprised by the performance gap ourselves and thus went back and +forth. We suspect that any overhead weighs so heavily because of how quick +SQLite itself is. +If you spot any issues or have ideas to make anyone go faster, +[we want to know](https://github.com/trailbaseio/trailbase-benchmark). +We hope to improve the methodology over time, make the numbers more broadly +applicable, and as fair as an apples-to-oranges comparison can be. +With that said, we hope that the results can provide at least some insights +into what to expect when taken with a grain of salt. +Ultimately, nothing beats benchmarking your own workload and setup. + +## Insertion Benchmarks + +_Total Time for 100k Insertions_ + +
+
+ +
+
+ +The graph shows the overall time it takes to insert 100k messages into a mock +"chat-room" table setup. Less time is better. + +Unsurprisingly, in-process SQLite is the quickest [^2]. +All other setups add additional table look-ups for access checking, IPC +overhead[^3], and layers of features on top. +Maybe think of this data point as an upper bound to how fast SQLite could go +and the cost a project would pay by adopting any of the systems over in-process +SQLite. + +The data suggests that depending on your setup (client, data, hardware) +TrailBase can insert 100k records 9 to 16 times faster than SupaBase[^4] and +roughly 6 to 7 times faster than PocketBase [^1]. +The fact that our TS/node.js benchmark is slower than the Dart one, suggests a +client-side bottleneck that could be overcome by tuning the setup or trying +other JS runtimes with lower overhead HTTP clients. + +Total time of inserting a large batch of data tells only part of the story, +let's have a quick look at resource consumption to get an intuition for +provisioning or footprint requirements: + +_TrailBase & PocketBase Utilization_ + +
+
+ +
+
+ +The graph shows the CPU utilization and memory consumption (RSS) of both +PocketBase and TrailBase. They look fairly similar apart from TrailBase +finishing earlier. They both load roughly 3 CPUs with PocketBase's CPU +consumption being slightly more variable [^5]. +The little bump after the TrailBase run is likely due to SQLite check-pointing. + +Both only consume about 140MB of memory at full tilt, which makes them a great +choice for running on a tiny VPS or a toaster. + +SupaBase is a bit more involved due to it's +[layered architecture](https://supabase.com/docs/guides/getting-started/architecture) +including a dozen separate services that provide a ton of extra functionality: + +_SupaBase Memory Usage_ + +
+
+ +
+
+ +Looking at SupaBase's memory usage, it increased from from roughly 6GB at rest to +7GB fully loaded. +This means that out of the box, SupaBase has roughly 50 times the memory +footprint of either PocketBase or TrailBase. +In all fairness, there's a lot of extra functionality and it might be possible +to further optimize the setup by shedding some less critical services, e.g. +removing "supabase-analytics" may safe ~40% of memory. That said, we don't know +how feasible this is in practice. + +_SupaBase CPU utilization_ + +
+
+ +
+
+ +Looking at the CPU usage You can see how the CPU usage jumps up to roughly 9 +cores (the benchmark ran on a machine with 8 physical cores and 16 threads: +7840U). Most of the CPUs seem to be consumed by "supabase-rest" with postgres +itself hovering at only ~0.7. + +## Latency and Read Performance + +In this chapter we'll take a closer look at latency distributions. To keep +things manageable we'll focus on PocketBase and TrailBase, which are +architecturally simpler and more comparable. + +Reads were on average 3.5 faster with TrailBase and insertions 6x as discussed +above. + +
+
+ +
+ +
+ +
+
+ +Looking at the latency distributions we can see that the spread is well +contained for TrailBase. For PocketBase, read latencies are also generally well +contained and predictable. +However, insert latencies show a more significant "long tail" with their p90 +being roughly 5x longer than therr p50. +Slower insertions can take north of 100ms. There may or may not be a connection +to the variability in CPU utilization we've seen above. + +## Final Words + +We're very happy to confirm that TrailBase is quick. The significant +performance gap we observed might just be a consequence of how much overhead +matters given how quick SQLite itself is. +Yet, it challenges our intuition. With the numbers fresh of the press, prudence is +of the essence. We'd like to re-emphasize how important it is to run your own +tests with your specific setup and workloads. +In any case, we hope this was interesting nonetheless and let us know if you +see anything that can or should be improved. +The benchmarks are available on [GitHub](https://github.com/trailbaseio/trailbase-benchmark). + +
+ +--- + +[^1]: + Trying to give PocketBase the best chance, the binary was built with the + latest go compiler (v1.23.1 at the time of writing), `CGO_ENABLED=1` (which + according to PB's own documentation will use a faster C-based SQLite + driver) and `GOAMD64=v4` (for less portable but more aggressive CPU + optimizations). + We found this setup to be roughly 20% faster than the static, pre-built + binary release. + +[^2]: + Our setup with drizzle and node.js is certainly not the fastest possible. + For example, we could drop down to using raw SQLite in C or another + low-level language. + That said, drizzle is a great popular choice which mostly serves as a + point-of-reference and sanity check. + +[^3]: + The actual magnitude on IPC overhead will depend on the communication cost. + For the benchmarks at hand we're using a loopback network device. + +[^4]: + The SupaBase benchmark setup skips row-level access checks. Technically, + this is in its favor from a performance standpoint, however looking at the + overall load on its constituents with PG being only a sliver, it probably + would not make much of an overall difference nor would PG17's vectorization, + which has been released since the benchmarks were run. That said, these + claims deserve re-validation. + +[^5]: + We're unsure as to what causes these 1-core swings. + Runtime-effects, such as garbage collection, may have an effect, however we + would have expected these to show on shorter time-scales. + This could also indicate a contention or thrashing issue 🤷. diff --git a/docs/src/content/docs/reference/faq.mdx b/docs/src/content/docs/reference/faq.mdx new file mode 100644 index 0000000..c5748b7 --- /dev/null +++ b/docs/src/content/docs/reference/faq.mdx @@ -0,0 +1,107 @@ +--- +title: FAQ +description: Frequently Asked Questions +--- + +## How is TrailBase different from PocketBase, SupaBase or other application bases? + +Naturally there's a lot of overlap but let's start by saying that +we're also huge fans of SupaBase and PocketBase. +The former is incredibly versatile, while the latter is incredibly easy and +cheap to use. +As far as we can tell, PocketBase pioneered the notion of a single-file, +SQLite-based, FireBase-like server. + +TrailBase is an attempt at combining the flexibility and principled +architecture of SupaBase with the ease and low-overhead of PocketBase. +We owe a great debt of gratitude to both ❤️. + +Let's address the elephant in the room: other more established solutions are +more polished, may have more extensive feature sets in many areas, and have +seen a lot more mileage. +TrailBase is committed to catch up and challenge the status quo following our +[principles](/getting-started/philosophy) and in many ways, TrailBase is +already incredibly easy to deploy and [blazingly fast](/reference/benchmarks). + +We also offer some slightly more detailed comparisons to both +[PocketBase](/comparison/pocketbase) and [SupaBase](/comparison/supabase). + +## Is TrailBase ready for production use? + +TrailBase has not seen a lot of mileage yet and there's probably plenty of +sharp edges, which will take some time to smooth over. +That said, it's also incredibly simple, easy to get on, and easy to get off. +We're welcoming any brave soul who would like to be an early adopter. +If you're curious and patient, we're ready to help you get off the ground in +return for your honest feedback 🙏. +You can take a look at the preliminary +[productionization](/documentation/production). + +## Scale, performance and reliability + +As my product grows, will TrailBase scale with me or will I hit a wall? +Firstly, congratulations! The "success"-problem is a great problem to have 🎉. + +Short, hand-wavy answer: you'll face all the same issues as with other +solutions but you probably will be fine 😶‍🌫️ . + +Long answer: TrailBase currently only scales vertically, however it's incredibly +fast. Besides, there's an inherent beauty to vertical scaling [^1] and modern +servers can get you very very far. +You can absolutely support tens of thousands or even hundreds thousands of +concurrent users with a single database. +With TrailBase simple deployment, it may also be an option to shard your users +or tenants across multiple databases. In the future, TrailBase would also like +to support multi-database setups out-of-the-box to further improve concurrency. + +Keep in mind that other databases, like MySQL or Postgres, aren't a silver bullet either. +If you're reaching massive levels of scale, more specialized solutions will +become more and more attractive such as non-relational document stores, +columnar OLAP stores for analytic workloads, ... + +TrailBase explicitly tries to avoid tight coupling locking you in. At the end +of the day, you're using very plain SQLite, letting you adopt and drop +TrailBase when it makes sense. +Similarly, the stateless auth flow makes it easy to split out your logic and +data while continuing to use TrailBase. + +Besides pure scale and performance, many more horizontal solutions provide +additional benefits such as disaster-recovery/fail-over or improved edge read +latency. +Fortunately, both can be achieved with SQLite as well using solutions like +[LiteStream](https://litestream.io/) keeping eventually consistent copies of +your data. + +## Can we add Features to TrailBase? + +Yes! First take a look at our coarse [roadmap](/reference/roadmap), maybe we're +already working on it? +Otherwise, don't hesitate, just open an issue and ask away. We love to hear +your thoughts. +Contributions are also very welcome, let's just talk upfront to avoid any +surprises. +Especially, in the early days we'll have to see how "things" fit into the +roadmap. +For example, having a dark mode for the dashboard would be nice but it's also +extra work to maintain while the dashboard is still rapidly changing, so it +becomes a question of when. + +## Data Import & Export + +Few requirements: `STRICT` table and an auto-incrementing primary key for +collections but the dashboard will work for any table, view, etc. +You can simply import and export data with standard SQLite tooling, e.g.: + +```shell +sqlite3 main.db < import.sql +``` + +Also check out the [getting started](/getting-started/first-app) guide. + +
+ +--- + +[^1]: + Adopting more complex multi-tiered database solutions comes with its own + challenges for operations, testing, and developer setups. diff --git a/docs/src/content/docs/reference/roadmap.mdx b/docs/src/content/docs/reference/roadmap.mdx new file mode 100644 index 0000000..4587f25 --- /dev/null +++ b/docs/src/content/docs/reference/roadmap.mdx @@ -0,0 +1,7 @@ +--- +title: Roadmap +--- + +import Roadmap from "../_roadmap.md"; + + diff --git a/docs/src/env.d.ts b/docs/src/env.d.ts new file mode 100644 index 0000000..acef35f --- /dev/null +++ b/docs/src/env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/docs/src/lib/darkmode.ts b/docs/src/lib/darkmode.ts new file mode 100644 index 0000000..d9bd077 --- /dev/null +++ b/docs/src/lib/darkmode.ts @@ -0,0 +1,24 @@ +import { createSignal, onCleanup, onMount } from "solid-js"; +import type { Accessor } from "solid-js"; + +export function createDarkMode(): Accessor { + const isDark = () => document.documentElement.dataset["theme"] === "dark"; + + const [darkMode, setDarkMode] = createSignal(isDark()); + + let observer: MutationObserver | undefined; + + onMount(() => { + observer = new MutationObserver((mutations) => { + mutations.forEach((mu) => { + if (mu.type === "attributes" && mu.attributeName === "data-theme") { + setDarkMode(isDark()); + } + }); + }); + observer.observe(document.documentElement, { attributes: true }); + }); + onCleanup(() => observer?.disconnect()); + + return darkMode; +} diff --git a/docs/src/tailwind.css b/docs/src/tailwind.css new file mode 100644 index 0000000..0d592b5 --- /dev/null +++ b/docs/src/tailwind.css @@ -0,0 +1,38 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --overlay-accent: #92d1fe30; +} + +:root[data-theme="dark"] { + --overlay-accent: #92d1fe70; +} + +[data-has-hero] .page { + background: + linear-gradient(215deg, var(--overlay-accent), transparent 40%), + radial-gradient(var(--overlay-accent), transparent 40%) no-repeat -60vw -40vh / + 105vw 200vh, + radial-gradient(var(--overlay-accent), transparent 65%) no-repeat 50% + calc(100% + 20rem) / 60rem 30rem; +} + +.card { + border-radius: 0.75rem; +} + +[data-has-hero] header { + border-bottom: 1px solid transparent; + background-color: #ffffffc0; + -webkit-backdrop-filter: blur(32px); + backdrop-filter: blur(32px); +} + +[data-has-hero][data-theme="dark"] header { + border-bottom: 1px solid transparent; + background-color: transparent; + -webkit-backdrop-filter: blur(32px); + backdrop-filter: blur(32px); +} diff --git a/docs/tailwind.config.mjs b/docs/tailwind.config.mjs new file mode 100644 index 0000000..e8d9b14 --- /dev/null +++ b/docs/tailwind.config.mjs @@ -0,0 +1,33 @@ +import starlightPlugin from "@astrojs/starlight-tailwind"; + +// Generated color palettes +const accent = { + 200: "#92d1fe", + 600: "#0073aa", + 900: "#003653", + 950: "#00273d", +}; +const gray = { + 100: "#f3f7f9", + 200: "#e7eff2", + 300: "#bac4c8", + 400: "#7b8f96", + 500: "#495c62", + 700: "#2a3b41", + 800: "#182a2f", + 900: "#121a1c", +}; + +/** @type {import('tailwindcss').Config} */ +export default { + content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"], + theme: { + extend: { + colors: { + accent, + gray, + }, + }, + }, + plugins: [starlightPlugin()], +}; diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 0000000..ba1912b --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "astro/tsconfigs/strict", + "compilerOptions": { + "jsx": "preserve", + "jsxImportSource": "solid-js", + "baseUrl": "./", + "paths": { + "@/*": ["./src/*"], + "@assets/*": ["../assets/*"], + "@common/*": ["../ui/common/*"] + } + }, + "exclude": [ + "dist", + "node_modules", + "public" + ] +} diff --git a/examples/blog/Caddyfile b/examples/blog/Caddyfile new file mode 100644 index 0000000..565dbf4 --- /dev/null +++ b/examples/blog/Caddyfile @@ -0,0 +1,5 @@ +# example.com + +localhost +encode gzip zstd +reverse_proxy blog:4000 diff --git a/examples/blog/Dockerfile b/examples/blog/Dockerfile new file mode 100644 index 0000000..6253df2 --- /dev/null +++ b/examples/blog/Dockerfile @@ -0,0 +1,39 @@ +# syntax = edrevo/dockerfile-plus + +# NOTE: paths are relative to build context, which is trailbase's root otherwise we +# cannot build the trailbase server as well. + +INCLUDE+ Dockerfile + +FROM chef AS webapp_builder + +COPY examples/blog/web /app +WORKDIR /app + +RUN pnpm install --no-frozen-lockfile +RUN pnpm run build + +FROM debian:bookworm-slim AS runtime +RUN apt-get update && apt-get install -y --no-install-recommends tini curl + +COPY --from=builder /app/target/x86_64-unknown-linux-gnu/release/trail /app/ +COPY --from=webapp_builder /app/dist /app/public + +# When `docker run` is executed, launch the binary as unprivileged user. +ENV USERNAME=trailbase +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "$(pwd)" \ + --no-create-home \ + ${USERNAME} +USER ${USERNAME} + +WORKDIR /app + +EXPOSE 4000 +ENTRYPOINT ["tini", "--"] + +CMD ["/app/trail", "run"] + +HEALTHCHECK CMD curl --fail http://localhost:4000/api/healthcheck || exit 1 diff --git a/examples/blog/Makefile b/examples/blog/Makefile new file mode 100644 index 0000000..de897ee --- /dev/null +++ b/examples/blog/Makefile @@ -0,0 +1,45 @@ +outputs = \ + web/types/article.ts \ + web/types/profile.ts \ + web/types/new_profile.ts \ + flutter/lib/types/article.dart \ + flutter/lib/types/profile.dart \ + flutter/lib/types/new_profile.dart + +types: $(outputs) + +schema/article.json: + cargo run -- schema articles_view --mode select > $@ +web/types/article.ts: schema/article.json + pnpm quicktype -s schema $< -o $@ +flutter/lib/types/article.dart: schema/article.json + pnpm quicktype -s schema $< -o $@ + +schema/new_article.json: + cargo run -- schema articles_view --mode insert > $@ +web/types/new_article.ts: schema/new_article.json + pnpm quicktype -s schema $< -o $@ + +schema/profile.json: + cargo run -- schema profiles_view --mode select > $@ +web/types/profile.ts: schema/profile.json + pnpm quicktype -s schema $< -o $@ +flutter/lib/types/profile.dart: schema/profile.json + pnpm quicktype -s schema $< -o $@ + +schema/new_profile.json: + cargo run -- schema profiles --mode insert > $@ +web/types/new_profile.ts: schema/new_profile.json + pnpm quicktype -s schema $< -o $@ +flutter/lib/types/new_profile.dart: schema/new_profile.json + pnpm quicktype -s schema $< -o $@ + +clean_data: + rm -f traildepot/data/* + +clean_types: + rm -f schema/* web/types/* flutter/lib/types/* + +clean: clean_data clean_types + +.PHONY: clean clean_data clean_types diff --git a/examples/blog/README.md b/examples/blog/README.md new file mode 100644 index 0000000..8958391 --- /dev/null +++ b/examples/blog/README.md @@ -0,0 +1,80 @@ +# TrailBase Example: A Blog with Web and Mobile clients + +The main goal of this example is to be easily digestible while show-casing many +of TrailBase's capabilities both for web and cross-platform Flutter: + +* Bootstrapping the database including schemas and dummy content though migration. +* End-to-end type-safety through code-generated data models for TypeScript, + Dart and many more based on JSON Schema. +* Builtin web authentication flow (including OAuth) on web and Flutter as well + as a custom password-based login in Flutter. +* API authorization: world readable, user editable, and moderator manageable articles. +* Different API types: + * Table and View-based APIs for custom user profiles associating users with a + username and keep their email addresses private as well as associating + articles with usernames. + * Virtual-table-based query API to expose "is_editor" authorization. +* The web client illustrates two different styles: a consumer SPA and an + HTML-only form-based authoring UI. + +## Directory Structure + +``` +. +├── Caddyfile # Example reverse proxy for TLS termination +├── Dockerfile # Example for bundling web app +├── docker-compose.yml # Example setup with reverse proxy +├── flutter # +│   ├── lib # Flutter app lives here +│   └── ... # Most other files a default cross-platform setup +├── Makefile # Builds JSON schemas and coge-generates type definitions +├── schema # Checked-in JSON schemas +├── traildepot # Where TrailBase keeps its runtime data +│   ├── backups # Periodic DB backups +│   ├── data # Contains SQLite's DB and WAL +│   ├── migrations # Bootstraps DB with schemas and dummy content +│   ├── secrets # Nothing to see :) +│   └── uploads # Local file uploads (will support S3 soon) +└── web + ├── dist # Built/packaged web app + ├── src # Web app lives here + └── types # Generated type definitions + └── ... +``` + +## Instructions + +Generally speaking, there are roughly 2.5 moving parts to run the example, i.e: +we have to build the web UI, start the TrailBase server, and optionally start +the Flutter app. Once you have `cargo`, `pnpm`, and `flutter` installed, you +can simply run: + +```bash +# From within the blog examples base directory +$ cd $REPO/examples/blog + +# build and bundle the web app: +$ pnpm --dir web build + +# Start TrailBase: +cargo run --bin trail -- run --public web/dist + +# Start Flutter app: +$ cd flutter +$ flutter run -d +``` + +You can also try the code generation: + +```bash +# Optionally delete the checked-in JSON schemas and code first +$ make clean_types + +# Genarate JSON Schema and codegen types from DB schema (this requires that +# you start TrailBase first to initialize the DB) +$ make --always-make types +``` + +## Reference + +* The styling is based on: https://github.com/palmiak/pacamara-astro 🙏 diff --git a/examples/blog/caddy/config/.gitignore b/examples/blog/caddy/config/.gitignore new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/examples/blog/caddy/config/.gitignore @@ -0,0 +1 @@ +* diff --git a/examples/blog/caddy/data/.gitignore b/examples/blog/caddy/data/.gitignore new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/examples/blog/caddy/data/.gitignore @@ -0,0 +1 @@ +* diff --git a/examples/blog/docker-compose.yml b/examples/blog/docker-compose.yml new file mode 100644 index 0000000..7be68a1 --- /dev/null +++ b/examples/blog/docker-compose.yml @@ -0,0 +1,33 @@ +services: + + blog: + # NOTE: We have to build relative to root to have a build context that + # includes both: the trailbase server source and the demo wepapp sources. + # build: ../.. + # TODO: Build from "." once the Dockerfile can pull a base image from + # dockerhub. We still need an example Dockerfile to build the UI. + build: + context: ../.. + dockerfile: examples/blog/Dockerfile + restart: unless-stopped + environment: + TRAIL_INITIAL_PASSWORD: secret + ADDRESS: 0.0.0.0:4000 + PUBLIC_DIR: ./public + DATA_DIR: ./traildepot + volumes: + - ./traildepot:/app/traildepot + + caddy: + image: caddy:2.8-alpine + restart: unless-stopped + cap_add: + - NET_ADMIN + ports: + - "80:80" + - "443:443" + - "443:443/udp" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile + - ./caddy/data:/data + - ./caddy/config:/config diff --git a/examples/blog/flutter/.gitignore b/examples/blog/flutter/.gitignore new file mode 100644 index 0000000..4e9b8f3 --- /dev/null +++ b/examples/blog/flutter/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release + +flutter_jank*.json diff --git a/examples/blog/flutter/.metadata b/examples/blog/flutter/.metadata new file mode 100644 index 0000000..e1116b2 --- /dev/null +++ b/examples/blog/flutter/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "2c18f27a9efabdc352cc294260a36c1335c7b98f" + channel: "[user-branch]" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + base_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + - platform: android + create_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + base_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + - platform: ios + create_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + base_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + - platform: linux + create_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + base_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + - platform: macos + create_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + base_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + - platform: web + create_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + base_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + - platform: windows + create_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + base_revision: 2c18f27a9efabdc352cc294260a36c1335c7b98f + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/examples/blog/flutter/analysis_options.yaml b/examples/blog/flutter/analysis_options.yaml new file mode 100644 index 0000000..efcadb7 --- /dev/null +++ b/examples/blog/flutter/analysis_options.yaml @@ -0,0 +1,21 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +analyzer: + exclude: + - lib/types/** + +linter: + rules: + prefer_single_quotes: true + unnecessary_brace_in_string_interps: false + unawaited_futures: true + sort_child_properties_last: false diff --git a/examples/blog/flutter/android/.gitignore b/examples/blog/flutter/android/.gitignore new file mode 100644 index 0000000..55afd91 --- /dev/null +++ b/examples/blog/flutter/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/examples/blog/flutter/android/app/build.gradle b/examples/blog/flutter/android/app/build.gradle new file mode 100644 index 0000000..d2775f4 --- /dev/null +++ b/examples/blog/flutter/android/app/build.gradle @@ -0,0 +1,44 @@ +plugins { + id "com.android.application" + id "kotlin-android" + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id "dev.flutter.flutter-gradle-plugin" +} + +android { + namespace = "com.example.trailbase_blog" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8 + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.example.trailbase_blog" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.debug + } + } +} + +flutter { + source = "../.." +} diff --git a/examples/blog/flutter/android/app/src/debug/AndroidManifest.xml b/examples/blog/flutter/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/examples/blog/flutter/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/examples/blog/flutter/android/app/src/main/AndroidManifest.xml b/examples/blog/flutter/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..406d1b8 --- /dev/null +++ b/examples/blog/flutter/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/blog/flutter/android/app/src/main/kotlin/com/example/trailbase_blog/MainActivity.kt b/examples/blog/flutter/android/app/src/main/kotlin/com/example/trailbase_blog/MainActivity.kt new file mode 100644 index 0000000..f6811cc --- /dev/null +++ b/examples/blog/flutter/android/app/src/main/kotlin/com/example/trailbase_blog/MainActivity.kt @@ -0,0 +1,5 @@ +package com.example.trailbase_blog + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() diff --git a/examples/blog/flutter/android/app/src/main/res/drawable-v21/launch_background.xml b/examples/blog/flutter/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/examples/blog/flutter/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/examples/blog/flutter/android/app/src/main/res/drawable/launch_background.xml b/examples/blog/flutter/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/examples/blog/flutter/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/examples/blog/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/blog/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/examples/blog/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/blog/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/examples/blog/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/android/app/src/main/res/values-night/styles.xml b/examples/blog/flutter/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/examples/blog/flutter/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/examples/blog/flutter/android/app/src/main/res/values/styles.xml b/examples/blog/flutter/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/examples/blog/flutter/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/examples/blog/flutter/android/app/src/profile/AndroidManifest.xml b/examples/blog/flutter/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/examples/blog/flutter/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/examples/blog/flutter/android/build.gradle b/examples/blog/flutter/android/build.gradle new file mode 100644 index 0000000..d2ffbff --- /dev/null +++ b/examples/blog/flutter/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = "../build" +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/examples/blog/flutter/android/gradle.properties b/examples/blog/flutter/android/gradle.properties new file mode 100644 index 0000000..2597170 --- /dev/null +++ b/examples/blog/flutter/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true +android.enableJetifier=true diff --git a/examples/blog/flutter/android/gradle/wrapper/gradle-wrapper.properties b/examples/blog/flutter/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7bb2df6 --- /dev/null +++ b/examples/blog/flutter/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip diff --git a/examples/blog/flutter/android/settings.gradle b/examples/blog/flutter/android/settings.gradle new file mode 100644 index 0000000..b9e43bd --- /dev/null +++ b/examples/blog/flutter/android/settings.gradle @@ -0,0 +1,25 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.1.0" apply false + id "org.jetbrains.kotlin.android" version "1.8.22" apply false +} + +include ":app" diff --git a/examples/blog/flutter/ios/.gitignore b/examples/blog/flutter/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/examples/blog/flutter/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/examples/blog/flutter/ios/Flutter/AppFrameworkInfo.plist b/examples/blog/flutter/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..7c56964 --- /dev/null +++ b/examples/blog/flutter/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/examples/blog/flutter/ios/Flutter/Debug.xcconfig b/examples/blog/flutter/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/examples/blog/flutter/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/examples/blog/flutter/ios/Flutter/Release.xcconfig b/examples/blog/flutter/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/examples/blog/flutter/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/examples/blog/flutter/ios/Runner.xcodeproj/project.pbxproj b/examples/blog/flutter/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..65e3db0 --- /dev/null +++ b/examples/blog/flutter/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,616 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/examples/blog/flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/examples/blog/flutter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/examples/blog/flutter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..8e3ca5d --- /dev/null +++ b/examples/blog/flutter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/blog/flutter/ios/Runner.xcworkspace/contents.xcworkspacedata b/examples/blog/flutter/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/examples/blog/flutter/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/examples/blog/flutter/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/examples/blog/flutter/ios/Runner/AppDelegate.swift b/examples/blog/flutter/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..6266644 --- /dev/null +++ b/examples/blog/flutter/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Flutter +import UIKit + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..797d452e458972bab9d994556c8305db4c827017 GIT binary patch literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2d933e1120817fe9182483a228007b18ab6ae GIT binary patch literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd7b0099ca80c806f8fe495613e8d6c69460d76 GIT binary patch literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe730945a01f64a61e2235dbe3f45b08f7729182 GIT binary patch literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..502f463a9bc882b461c96aadf492d1729e49e725 GIT binary patch literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec303439225b78712f49115768196d8d76f6790 GIT binary patch literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 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 literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0467bf12aa4d28f374bb26596605a46dcbb3e7c8 GIT binary patch literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..b5b843a --- /dev/null +++ b/examples/blog/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +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. diff --git a/examples/blog/flutter/ios/Runner/Base.lproj/LaunchScreen.storyboard b/examples/blog/flutter/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/examples/blog/flutter/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/blog/flutter/ios/Runner/Base.lproj/Main.storyboard b/examples/blog/flutter/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/examples/blog/flutter/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/blog/flutter/ios/Runner/Info.plist b/examples/blog/flutter/ios/Runner/Info.plist new file mode 100644 index 0000000..815168c --- /dev/null +++ b/examples/blog/flutter/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Trailbase Blog + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + trailbase_blog + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/examples/blog/flutter/ios/Runner/Runner-Bridging-Header.h b/examples/blog/flutter/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/examples/blog/flutter/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/examples/blog/flutter/ios/RunnerTests/RunnerTests.swift b/examples/blog/flutter/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/examples/blog/flutter/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/examples/blog/flutter/lib/main.dart b/examples/blog/flutter/lib/main.dart new file mode 100644 index 0000000..7333f0c --- /dev/null +++ b/examples/blog/flutter/lib/main.dart @@ -0,0 +1,237 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:logging/logging.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:trailbase/trailbase.dart'; + +import 'types/article.dart'; +import 'src/login.dart'; + +Future main() async { + Logger.root.level = Level.INFO; + Logger.root.onRecord.listen((record) { + // ignore: avoid_print + print( + '${record.level.name}: ${record.time} ${record.loggerName}: ${record.message}'); + }); + + final prefs = await SharedPreferences.getInstance(); + + final tokensJson = prefs.getString(_tokensKey); + Tokens? tokens; + try { + tokens = (tokensJson != null && tokensJson.isNotEmpty) + ? Tokens.fromJson(jsonDecode(tokensJson)) + : null; + } catch (err) { + _logger.warning(err); + } + + final user = ValueNotifier(null); + void onAuthChange(Client client, Tokens? tokens) { + user.value = client.user(); + prefs.setString(_tokensKey, tokens != null ? jsonEncode(tokens) : ''); + } + + const address = 'http://localhost:4000'; + final client = tokens != null + ? await Client.withTokens( + address, + tokens, + onAuthChange: onAuthChange, + ) + : Client(address, onAuthChange: onAuthChange); + + runApp(TrailbaseBlog(client, user)); +} + +class TrailbaseBlog extends StatelessWidget { + final ValueNotifier user; + final Client client; + + const TrailbaseBlog(this.client, this.user, {super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + title: 'TrailBase 🚀', + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal), + useMaterial3: true, + ), + home: Landing(client: client, user: user), + ); + } +} + +class Landing extends StatefulWidget { + final ValueNotifier user; + final Client client; + + const Landing({ + super.key, + required this.client, + required this.user, + }); + + @override + State createState() => _LandingState(); +} + +class _LandingState extends State { + late final _articlesApi = widget.client.records('articles_view'); + final _articlesCtrl = StreamController>(); + + @override + void initState() { + super.initState(); + + _fetchArticles(); + } + + Future _fetchArticles() async { + try { + final records = await _articlesApi.list(); + _articlesCtrl.add(records.map((r) => Article.fromJson(r)).toList()); + } catch (err) { + _articlesCtrl.addError(err); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text('TrailBase Blog 🚀'), + ValueListenableBuilder( + valueListenable: widget.user, + builder: (BuildContext context, User? user, Widget? _) { + if (user == null) { + return IconButton( + icon: const Icon(Icons.no_accounts), + onPressed: () => Scaffold.of(context).openEndDrawer(), + ); + } + + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(user.email), + const Icon(Icons.account_box), + ], + ); + }, + ), + ], + ), + ), + endDrawer: Drawer( + child: ListView( + padding: EdgeInsets.zero, + children: [ + const DrawerHeader( + decoration: BoxDecoration( + color: Colors.teal, + ), + child: Text( + '', + style: TextStyle( + color: Colors.white, + fontSize: 24, + ), + ), + ), + LoginFormWidget(client: widget.client), + ], + ), + ), + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: StreamBuilder( + stream: _articlesCtrl.stream, + builder: ( + BuildContext context, + AsyncSnapshot> articles, + ) { + final err = articles.error; + if (err != null) { + return Text( + 'Stream produced: ${err} ${widget.client.user()}'); + } + + final data = articles.data; + if (data == null) { + return const CircularProgressIndicator(); + } + + return ListView( + padding: const EdgeInsets.all(8), + children: data + .map((a) => ArticleWidget(api: _articlesApi, article: a)) + .toList(), + ); + }, + ), + ), + ], + ), + ); + } +} + +class ArticleWidget extends StatelessWidget { + final RecordApi api; + final Article article; + + const ArticleWidget({ + super.key, + required this.api, + required this.article, + }); + + @override + Widget build(BuildContext context) { + final textTheme = Theme.of(context).textTheme; + + return Card( + child: Container( + padding: const EdgeInsets.all(24), + child: Row( + children: [ + if (article.image != null) ...[ + Image.network( + api.imageUri(RecordId.uuid(article.id), 'image').toString(), + width: 100, + ), + const SizedBox(width: 16), + ], + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(article.title, style: textTheme.titleLarge), + const SizedBox(height: 8), + Text(article.intro, style: textTheme.titleMedium), + const SizedBox(height: 12), + Text(article.body), + ], + ), + ), + ], + ), + ), + ); + } +} + +final _logger = Logger('main'); +const _tokensKey = 'tokens'; diff --git a/examples/blog/flutter/lib/src/login.dart b/examples/blog/flutter/lib/src/login.dart new file mode 100644 index 0000000..30ec207 --- /dev/null +++ b/examples/blog/flutter/lib/src/login.dart @@ -0,0 +1,174 @@ +import 'dart:io' show Platform; + +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:flutter_web_auth_2/flutter_web_auth_2.dart'; +import 'package:logging/logging.dart'; +import 'package:trailbase/trailbase.dart'; + +class LoginFormWidget extends StatefulWidget { + final Client client; + + const LoginFormWidget({ + super.key, + required this.client, + }); + + @override + State createState() => _LoginFormState(); +} + +class _LoginFormState extends State { + final _usernameCtrl = TextEditingController(); + final _passwordCtrl = TextEditingController(); + + @override + void dispose() { + _usernameCtrl.dispose(); + _passwordCtrl.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), + child: TextFormField( + controller: _usernameCtrl, + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'E-mail', + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), + child: TextFormField( + controller: _passwordCtrl, + obscureText: true, + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'password', + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + FilledButton( + child: const Text('OAuth'), + onPressed: () async { + final scaffold = Scaffold.of(context); + final messenger = ScaffoldMessenger.of(context); + + final redirectUri = _redirectUri(); + final callbackUrlScheme = _callbackUrlScheme(); + final (:verifier, :challenge) = Pkce.generate(); + + _logger.info( + 'redirect: ${redirectUri}; callbackUrlScheme: ${callbackUrlScheme}'); + + // Construct the login page url + final url = Uri.parse('${widget.client.site()}/_/auth/login') + .replace(queryParameters: { + 'redirect_to': redirectUri, + 'response_type': 'code', + 'pkce_code_challenge': challenge, + }); + + // Open a browser or webview to get an authorization code. + final result = await FlutterWebAuth2.authenticate( + url: url.toString(), + callbackUrlScheme: callbackUrlScheme, + options: const FlutterWebAuth2Options( + useWebview: false, + ), + ); + + _logger.info('RESULT: ${result}'); + + final String? code = + Uri.parse(result).queryParameters['code']; + if (code == null) { + _logger.warning('Failed to get auth code: ${result}'); + return; + } + + try { + await widget.client.loginWithAuthCode( + code, + pkceCodeVerifier: verifier, + ); + scaffold.closeEndDrawer(); + } catch (err) { + messenger.showSnackBar( + SnackBar( + duration: const Duration(seconds: 5), + content: Text(err.toString()), + ), + ); + } + }, + ), + + // Password login + FilledButton( + child: const Text('Login'), + onPressed: () { + final scaffold = Scaffold.of(context); + final messenger = ScaffoldMessenger.of(context); + (() async { + final client = widget.client; + try { + await client.login( + _usernameCtrl.text, _passwordCtrl.text); + scaffold.closeEndDrawer(); + } catch (err) { + messenger.showSnackBar( + SnackBar( + duration: const Duration(seconds: 5), + content: Text(err.toString()), + ), + ); + } + })(); + }, + ), + ], + ), + ], + ), + ); + } +} + +String _callbackUrlScheme() { + if (Platform.isLinux || Platform.isWindows) { + return 'http://localhost:22342'; + } + return 'trailbase-example-blog'; +} + +// See https://pub.dev/packages/flutter_web_auth_2#setup. +String _redirectUri() { + // On web we redirect to a different page web/auth.html which + // will then communicate back to `flutter_web_auth_2` via `postMessage()` apis. + if (kIsWeb) { + return '${Uri.base}auth.html'; + } + + // `flutter_web_auth_2` will start a local http server to receive the callback on Linux and Windows. + // Ideally, we'd pick a port that is guaranteed to be available but the entire + // approach is racy anyway :shrug:. + if (Platform.isLinux || Platform.isWindows) { + return 'http://localhost:22342'; + } + + return '${_callbackUrlScheme()}://login-callback'; +} + +final _logger = Logger('login'); diff --git a/examples/blog/flutter/lib/types/article.dart b/examples/blog/flutter/lib/types/article.dart new file mode 100644 index 0000000..20e25ed --- /dev/null +++ b/examples/blog/flutter/lib/types/article.dart @@ -0,0 +1,91 @@ +// To parse this JSON data, do +// +// final article = articleFromJson(jsonString); + +import 'dart:convert'; + +Article articleFromJson(String str) => Article.fromJson(json.decode(str)); + +String articleToJson(Article data) => json.encode(data.toJson()); + +class Article { + String author; + String body; + int created; + String id; + FileUpload? image; + String intro; + String tag; + String title; + String username; + + Article({ + required this.author, + required this.body, + required this.created, + required this.id, + this.image, + required this.intro, + required this.tag, + required this.title, + required this.username, + }); + + factory Article.fromJson(Map json) => Article( + author: json["author"], + body: json["body"], + created: json["created"], + id: json["id"], + image: + json["image"] == null ? null : FileUpload.fromJson(json["image"]), + intro: json["intro"], + tag: json["tag"], + title: json["title"], + username: json["username"], + ); + + Map toJson() => { + "author": author, + "body": body, + "created": created, + "id": id, + "image": image?.toJson(), + "intro": intro, + "tag": tag, + "title": title, + "username": username, + }; +} + +class FileUpload { + ///The file's user-provided content type. + String? contentType; + + ///The file's original file name. + String? filename; + String id; + + ///The file's inferred mime type. Not user provided. + String? mimeType; + + FileUpload({ + this.contentType, + this.filename, + required this.id, + this.mimeType, + }); + + factory FileUpload.fromJson(Map json) => FileUpload( + contentType: json["content_type"], + filename: json["filename"], + id: json["id"], + mimeType: json["mime_type"], + ); + + Map toJson() => { + "content_type": contentType, + "filename": filename, + "id": id, + "mime_type": mimeType, + }; +} diff --git a/examples/blog/flutter/lib/types/new_profile.dart b/examples/blog/flutter/lib/types/new_profile.dart new file mode 100644 index 0000000..8805381 --- /dev/null +++ b/examples/blog/flutter/lib/types/new_profile.dart @@ -0,0 +1,38 @@ +// To parse this JSON data, do +// +// final newProfile = newProfileFromJson(jsonString); + +import 'dart:convert'; + +NewProfile newProfileFromJson(String str) => + NewProfile.fromJson(json.decode(str)); + +String newProfileToJson(NewProfile data) => json.encode(data.toJson()); + +class NewProfile { + int? created; + int? updated; + String user; + String username; + + NewProfile({ + this.created, + this.updated, + required this.user, + required this.username, + }); + + factory NewProfile.fromJson(Map json) => NewProfile( + created: json["created"], + updated: json["updated"], + user: json["user"], + username: json["username"], + ); + + Map toJson() => { + "created": created, + "updated": updated, + "user": user, + "username": username, + }; +} diff --git a/examples/blog/flutter/lib/types/profile.dart b/examples/blog/flutter/lib/types/profile.dart new file mode 100644 index 0000000..4efb6e3 --- /dev/null +++ b/examples/blog/flutter/lib/types/profile.dart @@ -0,0 +1,45 @@ +// To parse this JSON data, do +// +// final profile = profileFromJson(jsonString); + +import 'dart:convert'; + +Profile profileFromJson(String str) => Profile.fromJson(json.decode(str)); + +String profileToJson(Profile data) => json.encode(data.toJson()); + +class Profile { + String? avatarUrl; + int created; + bool? isEditor; + int updated; + String user; + String username; + + Profile({ + this.avatarUrl, + required this.created, + this.isEditor, + required this.updated, + required this.user, + required this.username, + }); + + factory Profile.fromJson(Map json) => Profile( + avatarUrl: json["avatar_url"], + created: json["created"], + isEditor: json["is_editor"], + updated: json["updated"], + user: json["user"], + username: json["username"], + ); + + Map toJson() => { + "avatar_url": avatarUrl, + "created": created, + "is_editor": isEditor, + "updated": updated, + "user": user, + "username": username, + }; +} diff --git a/examples/blog/flutter/linux/.gitignore b/examples/blog/flutter/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/examples/blog/flutter/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/examples/blog/flutter/linux/CMakeLists.txt b/examples/blog/flutter/linux/CMakeLists.txt new file mode 100644 index 0000000..d17ebd2 --- /dev/null +++ b/examples/blog/flutter/linux/CMakeLists.txt @@ -0,0 +1,145 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "trailbase_blog") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.trailbase_blog") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/examples/blog/flutter/linux/flutter/CMakeLists.txt b/examples/blog/flutter/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..d5bd016 --- /dev/null +++ b/examples/blog/flutter/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/examples/blog/flutter/linux/flutter/generated_plugin_registrant.cc b/examples/blog/flutter/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..9f3151b --- /dev/null +++ b/examples/blog/flutter/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,23 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) desktop_webview_window_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopWebviewWindowPlugin"); + desktop_webview_window_plugin_register_with_registrar(desktop_webview_window_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); + g_autoptr(FlPluginRegistrar) window_to_front_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "WindowToFrontPlugin"); + window_to_front_plugin_register_with_registrar(window_to_front_registrar); +} diff --git a/examples/blog/flutter/linux/flutter/generated_plugin_registrant.h b/examples/blog/flutter/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/examples/blog/flutter/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/examples/blog/flutter/linux/flutter/generated_plugins.cmake b/examples/blog/flutter/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..9bc27dc --- /dev/null +++ b/examples/blog/flutter/linux/flutter/generated_plugins.cmake @@ -0,0 +1,26 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + desktop_webview_window + url_launcher_linux + window_to_front +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/examples/blog/flutter/linux/main.cc b/examples/blog/flutter/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/examples/blog/flutter/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/examples/blog/flutter/linux/my_application.cc b/examples/blog/flutter/linux/my_application.cc new file mode 100644 index 0000000..2dde140 --- /dev/null +++ b/examples/blog/flutter/linux/my_application.cc @@ -0,0 +1,124 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "trailbase_blog"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "trailbase_blog"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GApplication::startup. +static void my_application_startup(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/examples/blog/flutter/linux/my_application.h b/examples/blog/flutter/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/examples/blog/flutter/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/examples/blog/flutter/macos/.gitignore b/examples/blog/flutter/macos/.gitignore new file mode 100644 index 0000000..746adbb --- /dev/null +++ b/examples/blog/flutter/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/examples/blog/flutter/macos/Flutter/Flutter-Debug.xcconfig b/examples/blog/flutter/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/examples/blog/flutter/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/examples/blog/flutter/macos/Flutter/Flutter-Release.xcconfig b/examples/blog/flutter/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/examples/blog/flutter/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/examples/blog/flutter/macos/Flutter/GeneratedPluginRegistrant.swift b/examples/blog/flutter/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..41a2904 --- /dev/null +++ b/examples/blog/flutter/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,22 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import desktop_webview_window +import flutter_web_auth_2 +import path_provider_foundation +import shared_preferences_foundation +import url_launcher_macos +import window_to_front + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + DesktopWebviewWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWebviewWindowPlugin")) + FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) + WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin")) +} diff --git a/examples/blog/flutter/macos/Runner.xcodeproj/project.pbxproj b/examples/blog/flutter/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..931f67f --- /dev/null +++ b/examples/blog/flutter/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,705 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* trailbase_blog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "trailbase_blog.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* trailbase_blog.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* trailbase_blog.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/trailbase_blog.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/trailbase_blog"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/trailbase_blog.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/trailbase_blog"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/trailbase_blog.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/trailbase_blog"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/examples/blog/flutter/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/blog/flutter/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/examples/blog/flutter/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/blog/flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/examples/blog/flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..47d4f74 --- /dev/null +++ b/examples/blog/flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/blog/flutter/macos/Runner.xcworkspace/contents.xcworkspacedata b/examples/blog/flutter/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/examples/blog/flutter/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/blog/flutter/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/blog/flutter/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/examples/blog/flutter/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/blog/flutter/macos/Runner/AppDelegate.swift b/examples/blog/flutter/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..8e02df2 --- /dev/null +++ b/examples/blog/flutter/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a2ec33f --- /dev/null +++ b/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..82b6f9d9a33e198f5747104729e1fcef999772a5 GIT binary patch literal 102994 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ⅅ8MglG&ER{i5lN315cO?EdHNLrg? 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 z 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 Pe7HEdAEg|=c=LY&YVNkY literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..13b35eba55c6dabc3aac36f33d859266c18fa0d0 GIT binary patch literal 5680 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 literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..0a3f5fa40fb3d1e0710331a48de5d256da3f275d GIT binary patch literal 520 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 literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/examples/blog/flutter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000000000000000000000000000000000000..2f1632cfddf3d9dade342351e627a0a75609fb46 GIT binary patch literal 2218 zcmV;b2vzrqP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuE6iGxuRCodHTWf3-RTMruyW6Fu zQYeUM04eX6D5c0FCjKKPrco1(K`<0SL=crI{PC3-^hZU0kQie$gh-5!7z6SH6Q0J% zqot*`H1q{R5fHFYS}dje@;kG=v$L0(yY0?wY2%*c?A&{2?!D*x?m71{of2gv!$5|C z3>qG_BW}7K_yUcT3A5C6QD<+{aq?x;MAUyAiJn#Jv8_zZtQ{P zTRzbL3U9!qVuZzS$xKU10KiW~Bgdcv1-!uAhQxf3a7q+dU6lj?yoO4Lq4TUN4}h{N z*fIM=SS8|C2$(T>w$`t@3Tka!(r!7W`x z-isCVgQD^mG-MJ;XtJuK3V{Vy72GQ83KRWsHU?e*wrhKk=ApIYeDqLi;JI1e zuvv}5^Dc=k7F7?nm3nIw$NVmU-+R>> zyqOR$-2SDpJ}Pt;^RkJytDVXNTsu|mI1`~G7yw`EJR?VkGfNdqK9^^8P`JdtTV&tX4CNcV4 z&N06nZa??Fw1AgQOUSE2AmPE@WO(Fvo`%m`cDgiv(fAeRA%3AGXUbsGw{7Q`cY;1BI#ac3iN$$Hw z0LT0;xc%=q)me?Y*$xI@GRAw?+}>=9D+KTk??-HJ4=A>`V&vKFS75@MKdSF1JTq{S zc1!^8?YA|t+uKigaq!sT;Z!&0F2=k7F0PIU;F$leJLaw2UI6FL^w}OG&!;+b%ya1c z1n+6-inU<0VM-Y_s5iTElq)ThyF?StVcebpGI znw#+zLx2@ah{$_2jn+@}(zJZ{+}_N9BM;z)0yr|gF-4=Iyu@hI*Lk=-A8f#bAzc9f z`Kd6K--x@t04swJVC3JK1cHY-Hq+=|PN-VO;?^_C#;coU6TDP7Bt`;{JTG;!+jj(` zw5cLQ-(Cz-Tlb`A^w7|R56Ce;Wmr0)$KWOUZ6ai0PhzPeHwdl0H(etP zUV`va_i0s-4#DkNM8lUlqI7>YQLf)(lz9Q3Uw`)nc(z3{m5ZE77Ul$V%m)E}3&8L0 z-XaU|eB~Is08eORPk;=<>!1w)Kf}FOVS2l&9~A+@R#koFJ$Czd%Y(ENTV&A~U(IPI z;UY+gf+&6ioZ=roly<0Yst8ck>(M=S?B-ys3mLdM&)ex!hbt+ol|T6CTS+Sc0jv(& z7ijdvFwBq;0a{%3GGwkDKTeG`b+lyj0jjS1OMkYnepCdoosNY`*zmBIo*981BU%%U z@~$z0V`OVtIbEx5pa|Tct|Lg#ZQf5OYMUMRD>Wdxm5SAqV2}3!ceE-M2 z@O~lQ0OiKQp}o9I;?uxCgYVV?FH|?Riri*U$Zi_`V2eiA>l zdSm6;SEm6#T+SpcE8Ro_f2AwxzI z44hfe^WE3!h@W3RDyA_H440cpmYkv*)6m1XazTqw%=E5Xv7^@^^T7Q2wxr+Z2kVYr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/blog/flutter/macos/Runner/Configs/AppInfo.xcconfig b/examples/blog/flutter/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..2230cb0 --- /dev/null +++ b/examples/blog/flutter/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = trailbase_blog + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.trailbaseBlog + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. diff --git a/examples/blog/flutter/macos/Runner/Configs/Debug.xcconfig b/examples/blog/flutter/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/examples/blog/flutter/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/examples/blog/flutter/macos/Runner/Configs/Release.xcconfig b/examples/blog/flutter/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/examples/blog/flutter/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/examples/blog/flutter/macos/Runner/Configs/Warnings.xcconfig b/examples/blog/flutter/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/examples/blog/flutter/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/examples/blog/flutter/macos/Runner/DebugProfile.entitlements b/examples/blog/flutter/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..dddb8a3 --- /dev/null +++ b/examples/blog/flutter/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/examples/blog/flutter/macos/Runner/Info.plist b/examples/blog/flutter/macos/Runner/Info.plist new file mode 100644 index 0000000..4789daa --- /dev/null +++ b/examples/blog/flutter/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/blog/flutter/macos/Runner/MainFlutterWindow.swift b/examples/blog/flutter/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..3cc05eb --- /dev/null +++ b/examples/blog/flutter/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/examples/blog/flutter/macos/Runner/Release.entitlements b/examples/blog/flutter/macos/Runner/Release.entitlements new file mode 100644 index 0000000..852fa1a --- /dev/null +++ b/examples/blog/flutter/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/examples/blog/flutter/macos/RunnerTests/RunnerTests.swift b/examples/blog/flutter/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..61f3bd1 --- /dev/null +++ b/examples/blog/flutter/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/examples/blog/flutter/pubspec.lock b/examples/blog/flutter/pubspec.lock new file mode 100644 index 0000000..0c47dc8 --- /dev/null +++ b/examples/blog/flutter/pubspec.lock @@ -0,0 +1,529 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + desktop_webview_window: + dependency: transitive + description: + name: desktop_webview_window + sha256: "57cf20d81689d5cbb1adfd0017e96b669398a669d927906073b0e42fc64111c0" + url: "https://pub.dev" + source: hosted + version: "0.2.3" + dio: + dependency: transitive + description: + name: dio + sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260" + url: "https://pub.dev" + source: hosted + version: "5.7.0" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_auth_2: + dependency: "direct main" + description: + name: flutter_web_auth_2 + sha256: "8f59c9fa71b5affb322cb7103b836cd0ced89c9c50c66f82b523b7d339018dc3" + url: "https://pub.dev" + source: hosted + version: "4.0.1" + flutter_web_auth_2_platform_interface: + dependency: transitive + description: + name: flutter_web_auth_2_platform_interface + sha256: "222264d4979e9372c90e441736a62d800481e4a9c860cc2c235d1d605a118a2b" + url: "https://pub.dev" + source: hosted + version: "4.0.1" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + jwt_decoder: + dependency: transitive + description: + name: jwt_decoder + sha256: "54774aebf83f2923b99e6416b4ea915d47af3bde56884eb622de85feabbc559f" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + logging: + dependency: "direct main" + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + url: "https://pub.dev" + source: hosted + version: "1.15.0" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a + url: "https://pub.dev" + source: hosted + version: "2.2.12" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" + source: hosted + version: "2.4.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e + url: "https://pub.dev" + source: hosted + version: "2.4.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + trailbase: + dependency: "direct main" + description: + path: "../../../client/trailbase-dart" + relative: true + source: path + version: "0.1.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + url_launcher: + dependency: transitive + description: + name: url_launcher + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "0dea215895a4d254401730ca0ba8204b29109a34a99fb06ae559a2b60988d2de" + url: "https://pub.dev" + source: hosted + version: "6.3.13" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af + url: "https://pub.dev" + source: hosted + version: "3.2.0" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4" + url: "https://pub.dev" + source: hosted + version: "3.1.3" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + url: "https://pub.dev" + source: hosted + version: "14.2.5" + web: + dependency: transitive + description: + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + url: "https://pub.dev" + source: hosted + version: "1.1.0" + window_to_front: + dependency: transitive + description: + name: window_to_front + sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee" + url: "https://pub.dev" + source: hosted + version: "0.0.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" +sdks: + dart: ">=3.5.3 <4.0.0" + flutter: ">=3.24.0" diff --git a/examples/blog/flutter/pubspec.yaml b/examples/blog/flutter/pubspec.yaml new file mode 100644 index 0000000..3b12394 --- /dev/null +++ b/examples/blog/flutter/pubspec.yaml @@ -0,0 +1,26 @@ +name: trailbase_blog +description: "TrailBase Example Blog Reader" +publish_to: 'none' # Remove this line if you wish to publish to pub.dev +version: 0.0.1+1 + +environment: + sdk: ^3.5.3 + +dependencies: + cupertino_icons: ^1.0.8 + flutter: + sdk: flutter + flutter_web_auth_2: ^4.0.0 + logging: ^1.2.0 + shared_preferences: ^2.3.2 + trailbase: + path: ../../../client/trailbase-dart + +dev_dependencies: + flutter_test: + sdk: flutter + + flutter_lints: ^4.0.0 + +flutter: + uses-material-design: true diff --git a/examples/blog/flutter/web/auth.html b/examples/blog/flutter/web/auth.html new file mode 100644 index 0000000..60a6a45 --- /dev/null +++ b/examples/blog/flutter/web/auth.html @@ -0,0 +1,26 @@ + + + +Authentication complete + +

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

+ + diff --git a/examples/blog/flutter/web/favicon.png b/examples/blog/flutter/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/web/icons/Icon-192.png b/examples/blog/flutter/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/web/icons/Icon-512.png b/examples/blog/flutter/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/web/icons/Icon-maskable-192.png b/examples/blog/flutter/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 zcmdT|`#%%j|KDb2V@0DPm$^(Lx5}lO%Yv(=e*7hl@QqKS50#~#^IQPxBmuh|i9sXnt4ch@VT0F7% zMtrs@KWIOo+QV@lSs66A>2pz6-`9Jk=0vv&u?)^F@HZ)-6HT=B7LF;rdj zskUyBfbojcX#CS>WrIWo9D=DIwcXM8=I5D{SGf$~=gh-$LwY?*)cD%38%sCc?5OsX z-XfkyL-1`VavZ?>(pI-xp-kYq=1hsnyP^TLb%0vKRSo^~r{x?ISLY1i7KjSp z*0h&jG(Rkkq2+G_6eS>n&6>&Xk+ngOMcYrk<8KrukQHzfx675^^s$~<@d$9X{VBbg z2Fd4Z%g`!-P}d#`?B4#S-9x*eNlOVRnDrn#jY@~$jfQ-~3Od;A;x-BI1BEDdvr`pI z#D)d)!2_`GiZOUu1crb!hqH=ezs0qk<_xDm_Kkw?r*?0C3|Io6>$!kyDl;eH=aqg$B zsH_|ZD?jP2dc=)|L>DZmGyYKa06~5?C2Lc0#D%62p(YS;%_DRCB1k(+eLGXVMe+=4 zkKiJ%!N6^mxqM=wq`0+yoE#VHF%R<{mMamR9o_1JH8jfnJ?NPLs$9U!9!dq8 z0B{dI2!M|sYGH&9TAY34OlpIsQ4i5bnbG>?cWwat1I13|r|_inLE?FS@Hxdxn_YZN z3jfUO*X9Q@?HZ>Q{W0z60!bbGh557XIKu1?)u|cf%go`pwo}CD=0tau-}t@R2OrSH zQzZr%JfYa`>2!g??76=GJ$%ECbQh7Q2wLRp9QoyiRHP7VE^>JHm>9EqR3<$Y=Z1K^SHuwxCy-5@z3 zVM{XNNm}yM*pRdLKp??+_2&!bp#`=(Lh1vR{~j%n;cJv~9lXeMv)@}Odta)RnK|6* zC+IVSWumLo%{6bLDpn)Gz>6r&;Qs0^+Sz_yx_KNz9Dlt^ax`4>;EWrIT#(lJ_40<= z750fHZ7hI{}%%5`;lwkI4<_FJw@!U^vW;igL0k+mK)-j zYuCK#mCDK3F|SC}tC2>m$ZCqNB7ac-0UFBJ|8RxmG@4a4qdjvMzzS&h9pQmu^x&*= zGvapd1#K%Da&)8f?<9WN`2H^qpd@{7In6DNM&916TRqtF4;3`R|Nhwbw=(4|^Io@T zIjoR?tB8d*sO>PX4vaIHF|W;WVl6L1JvSmStgnRQq zTX4(>1f^5QOAH{=18Q2Vc1JI{V=yOr7yZJf4Vpfo zeHXdhBe{PyY;)yF;=ycMW@Kb>t;yE>;f79~AlJ8k`xWucCxJfsXf2P72bAavWL1G#W z;o%kdH(mYCM{$~yw4({KatNGim49O2HY6O07$B`*K7}MvgI=4x=SKdKVb8C$eJseA$tmSFOztFd*3W`J`yIB_~}k%Sd_bPBK8LxH)?8#jM{^%J_0|L z!gFI|68)G}ex5`Xh{5pB%GtlJ{Z5em*e0sH+sU1UVl7<5%Bq+YrHWL7?X?3LBi1R@_)F-_OqI1Zv`L zb6^Lq#H^2@d_(Z4E6xA9Z4o3kvf78ZDz!5W1#Mp|E;rvJz&4qj2pXVxKB8Vg0}ek%4erou@QM&2t7Cn5GwYqy%{>jI z)4;3SAgqVi#b{kqX#$Mt6L8NhZYgonb7>+r#BHje)bvaZ2c0nAvrN3gez+dNXaV;A zmyR0z@9h4@6~rJik-=2M-T+d`t&@YWhsoP_XP-NsVO}wmo!nR~QVWU?nVlQjNfgcTzE-PkfIX5G z1?&MwaeuzhF=u)X%Vpg_e@>d2yZwxl6-r3OMqDn8_6m^4z3zG##cK0Fsgq8fcvmhu z{73jseR%X%$85H^jRAcrhd&k!i^xL9FrS7qw2$&gwAS8AfAk#g_E_tP;x66fS`Mn@SNVrcn_N;EQm z`Mt3Z%rw%hDqTH-s~6SrIL$hIPKL5^7ejkLTBr46;pHTQDdoErS(B>``t;+1+M zvU&Se9@T_BeK;A^p|n^krIR+6rH~BjvRIugf`&EuX9u69`9C?9ANVL8l(rY6#mu^i z=*5Q)-%o*tWl`#b8p*ZH0I}hn#gV%|jt6V_JanDGuekR*-wF`u;amTCpGG|1;4A5$ zYbHF{?G1vv5;8Ph5%kEW)t|am2_4ik!`7q{ymfHoe^Z99c|$;FAL+NbxE-_zheYbV z3hb0`uZGTsgA5TG(X|GVDSJyJxsyR7V5PS_WSnYgwc_D60m7u*x4b2D79r5UgtL18 zcCHWk+K6N1Pg2c;0#r-)XpwGX?|Iv)^CLWqwF=a}fXUSM?n6E;cCeW5ER^om#{)Jr zJR81pkK?VoFm@N-s%hd7@hBS0xuCD0-UDVLDDkl7Ck=BAj*^ps`393}AJ+Ruq@fl9 z%R(&?5Nc3lnEKGaYMLmRzKXow1+Gh|O-LG7XiNxkG^uyv zpAtLINwMK}IWK65hOw&O>~EJ}x@lDBtB`yKeV1%GtY4PzT%@~wa1VgZn7QRwc7C)_ zpEF~upeDRg_<#w=dLQ)E?AzXUQpbKXYxkp>;c@aOr6A|dHA?KaZkL0svwB^U#zmx0 zzW4^&G!w7YeRxt<9;d@8H=u(j{6+Uj5AuTluvZZD4b+#+6Rp?(yJ`BC9EW9!b&KdPvzJYe5l7 zMJ9aC@S;sA0{F0XyVY{}FzW0Vh)0mPf_BX82E+CD&)wf2!x@{RO~XBYu80TONl3e+ zA7W$ra6LcDW_j4s-`3tI^VhG*sa5lLc+V6ONf=hO@q4|p`CinYqk1Ko*MbZ6_M05k zSwSwkvu;`|I*_Vl=zPd|dVD0lh&Ha)CSJJvV{AEdF{^Kn
_Yfsd!{Pc1GNgw}(^~%)jk5~0L~ms|Rez1fiK~s5t(p1ci5Gq$JC#^JrXf?8 z-Y-Zi_Hvi>oBzV8DSRG!7dm|%IlZg3^0{5~;>)8-+Nk&EhAd(}s^7%MuU}lphNW9Q zT)DPo(ob{tB7_?u;4-qGDo!sh&7gHaJfkh43QwL|bbFVi@+oy;i;M zM&CP^v~lx1U`pi9PmSr&Mc<%HAq0DGH?Ft95)WY`P?~7O z`O^Nr{Py9M#Ls4Y7OM?e%Y*Mvrme%=DwQaye^Qut_1pOMrg^!5u(f9p(D%MR%1K>% zRGw%=dYvw@)o}Fw@tOtPjz`45mfpn;OT&V(;z75J*<$52{sB65$gDjwX3Xa!x_wE- z!#RpwHM#WrO*|~f7z}(}o7US(+0FYLM}6de>gQdtPazXz?OcNv4R^oYLJ_BQOd_l172oSK$6!1r@g+B@0ofJ4*{>_AIxfe-#xp>(1 z@Y3Nfd>fmqvjL;?+DmZk*KsfXJf<%~(gcLwEez%>1c6XSboURUh&k=B)MS>6kw9bY z{7vdev7;A}5fy*ZE23DS{J?8at~xwVk`pEwP5^k?XMQ7u64;KmFJ#POzdG#np~F&H ze-BUh@g54)dsS%nkBb}+GuUEKU~pHcYIg4vSo$J(J|U36bs0Use+3A&IMcR%6@jv$ z=+QI+@wW@?iu}Hpyzlvj-EYeop{f65GX0O%>w#0t|V z1-svWk`hU~m`|O$kw5?Yn5UhI%9P-<45A(v0ld1n+%Ziq&TVpBcV9n}L9Tus-TI)f zd_(g+nYCDR@+wYNQm1GwxhUN4tGMLCzDzPqY$~`l<47{+l<{FZ$L6(>J)|}!bi<)| zE35dl{a2)&leQ@LlDxLQOfUDS`;+ZQ4ozrleQwaR-K|@9T{#hB5Z^t#8 zC-d_G;B4;F#8A2EBL58s$zF-=SCr`P#z zNCTnHF&|X@q>SkAoYu>&s9v@zCpv9lLSH-UZzfhJh`EZA{X#%nqw@@aW^vPcfQrlPs(qQxmC|4tp^&sHy!H!2FH5eC{M@g;ElWNzlb-+ zxpfc0m4<}L){4|RZ>KReag2j%Ot_UKkgpJN!7Y_y3;Ssz{9 z!K3isRtaFtQII5^6}cm9RZd5nTp9psk&u1C(BY`(_tolBwzV_@0F*m%3G%Y?2utyS zY`xM0iDRT)yTyYukFeGQ&W@ReM+ADG1xu@ruq&^GK35`+2r}b^V!m1(VgH|QhIPDE X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/web/icons/Icon-maskable-512.png b/examples/blog/flutter/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 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 MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/web/index.html b/examples/blog/flutter/web/index.html new file mode 100644 index 0000000..f010497 --- /dev/null +++ b/examples/blog/flutter/web/index.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + trailbase_blog + + + + + + diff --git a/examples/blog/flutter/web/manifest.json b/examples/blog/flutter/web/manifest.json new file mode 100644 index 0000000..0b44b18 --- /dev/null +++ b/examples/blog/flutter/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "trailbase_blog", + "short_name": "trailbase_blog", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/examples/blog/flutter/windows/.gitignore b/examples/blog/flutter/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/examples/blog/flutter/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/examples/blog/flutter/windows/CMakeLists.txt b/examples/blog/flutter/windows/CMakeLists.txt new file mode 100644 index 0000000..4377368 --- /dev/null +++ b/examples/blog/flutter/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(trailbase_blog LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "trailbase_blog") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/examples/blog/flutter/windows/flutter/CMakeLists.txt b/examples/blog/flutter/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..903f489 --- /dev/null +++ b/examples/blog/flutter/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/examples/blog/flutter/windows/flutter/generated_plugin_registrant.cc b/examples/blog/flutter/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..3a6d25f --- /dev/null +++ b/examples/blog/flutter/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,20 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + DesktopWebviewWindowPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); + WindowToFrontPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("WindowToFrontPlugin")); +} diff --git a/examples/blog/flutter/windows/flutter/generated_plugin_registrant.h b/examples/blog/flutter/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/examples/blog/flutter/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/examples/blog/flutter/windows/flutter/generated_plugins.cmake b/examples/blog/flutter/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..cf17c65 --- /dev/null +++ b/examples/blog/flutter/windows/flutter/generated_plugins.cmake @@ -0,0 +1,26 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + desktop_webview_window + url_launcher_windows + window_to_front +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/examples/blog/flutter/windows/runner/CMakeLists.txt b/examples/blog/flutter/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..394917c --- /dev/null +++ b/examples/blog/flutter/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/examples/blog/flutter/windows/runner/Runner.rc b/examples/blog/flutter/windows/runner/Runner.rc new file mode 100644 index 0000000..ef4eb90 --- /dev/null +++ b/examples/blog/flutter/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "trailbase_blog" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "trailbase_blog" "\0" + VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "trailbase_blog.exe" "\0" + VALUE "ProductName", "trailbase_blog" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/examples/blog/flutter/windows/runner/flutter_window.cpp b/examples/blog/flutter/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..955ee30 --- /dev/null +++ b/examples/blog/flutter/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/examples/blog/flutter/windows/runner/flutter_window.h b/examples/blog/flutter/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/examples/blog/flutter/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/examples/blog/flutter/windows/runner/main.cpp b/examples/blog/flutter/windows/runner/main.cpp new file mode 100644 index 0000000..bb94690 --- /dev/null +++ b/examples/blog/flutter/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"trailbase_blog", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/examples/blog/flutter/windows/runner/resource.h b/examples/blog/flutter/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/examples/blog/flutter/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/examples/blog/flutter/windows/runner/resources/app_icon.ico b/examples/blog/flutter/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 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 literal 0 HcmV?d00001 diff --git a/examples/blog/flutter/windows/runner/runner.exe.manifest b/examples/blog/flutter/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..153653e --- /dev/null +++ b/examples/blog/flutter/windows/runner/runner.exe.manifest @@ -0,0 +1,14 @@ + + + + + PerMonitorV2 + + + + + + + + + diff --git a/examples/blog/flutter/windows/runner/utils.cpp b/examples/blog/flutter/windows/runner/utils.cpp new file mode 100644 index 0000000..3a0b465 --- /dev/null +++ b/examples/blog/flutter/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/examples/blog/flutter/windows/runner/utils.h b/examples/blog/flutter/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/examples/blog/flutter/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/examples/blog/flutter/windows/runner/win32_window.cpp b/examples/blog/flutter/windows/runner/win32_window.cpp new file mode 100644 index 0000000..60608d0 --- /dev/null +++ b/examples/blog/flutter/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/examples/blog/flutter/windows/runner/win32_window.h b/examples/blog/flutter/windows/runner/win32_window.h new file mode 100644 index 0000000..e901dde --- /dev/null +++ b/examples/blog/flutter/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/examples/blog/package.json b/examples/blog/package.json new file mode 100644 index 0000000..0fda473 --- /dev/null +++ b/examples/blog/package.json @@ -0,0 +1,11 @@ +{ + "name": "trailbase-example-blog-typegen", + "type": "module", + "version": "0.0.1", + "scripts": { + "types": "make --always-make types" + }, + "devDependencies": { + "quicktype": "^23.0.170" + } +} diff --git a/examples/blog/schema/article.json b/examples/blog/schema/article.json new file mode 100644 index 0000000..fbf519f --- /dev/null +++ b/examples/blog/schema/article.json @@ -0,0 +1,80 @@ +{ + "$defs": { + "image": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "content_type": { + "description": "The file's user-provided content type.", + "type": [ + "string", + "null" + ] + }, + "filename": { + "description": "The file's original file name.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string" + }, + "mime_type": { + "description": "The file's inferred mime type. Not user provided.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "title": "FileUpload", + "type": "object" + } + }, + "properties": { + "author": { + "type": "string" + }, + "body": { + "type": "string" + }, + "created": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "image": { + "$ref": "#/$defs/image" + }, + "intro": { + "type": "string" + }, + "tag": { + "type": "string" + }, + "title": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "author", + "title", + "intro", + "tag", + "body", + "created", + "username" + ], + "title": "articles_view", + "type": "object" +} diff --git a/examples/blog/schema/new_profile.json b/examples/blog/schema/new_profile.json new file mode 100644 index 0000000..82da3dd --- /dev/null +++ b/examples/blog/schema/new_profile.json @@ -0,0 +1,23 @@ +{ + "$defs": {}, + "properties": { + "created": { + "type": "integer" + }, + "updated": { + "type": "integer" + }, + "user": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "user", + "username" + ], + "title": "profiles", + "type": "object" +} diff --git a/examples/blog/schema/profile.json b/examples/blog/schema/profile.json new file mode 100644 index 0000000..83c3f97 --- /dev/null +++ b/examples/blog/schema/profile.json @@ -0,0 +1,31 @@ +{ + "$defs": {}, + "properties": { + "avatar_url": { + "type": "string" + }, + "created": { + "type": "integer" + }, + "is_editor": { + "type": "boolean" + }, + "updated": { + "type": "integer" + }, + "user": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "user", + "username", + "created", + "updated" + ], + "title": "profiles_view", + "type": "object" +} diff --git a/examples/blog/traildepot/.gitignore b/examples/blog/traildepot/.gitignore new file mode 100644 index 0000000..c30536f --- /dev/null +++ b/examples/blog/traildepot/.gitignore @@ -0,0 +1,7 @@ + +backups/ +data/ +secrets/ +uploads/ + +!migrations/ diff --git a/examples/blog/traildepot/config.textproto b/examples/blog/traildepot/config.textproto new file mode 100644 index 0000000..7d3af29 --- /dev/null +++ b/examples/blog/traildepot/config.textproto @@ -0,0 +1,60 @@ +# Auto-generated config.Config textproto +email {} +server { + application_name: "TrailBase" + site_url: "http://localhost:4000" +} +auth {} +record_apis: [ + { + name: "_user_avatar" + table_name: "_user_avatar" + conflict_resolution: REPLACE + autofill_missing_user_id_columns: true + acl_world: [READ] + acl_authenticated: [CREATE, READ, UPDATE, DELETE] + create_access_rule: "_REQ_.user IS NULL OR _REQ_.user = _USER_.id" + update_access_rule: "_ROW_.user = _USER_.id" + delete_access_rule: "_ROW_.user = _USER_.id" + }, + { + name: "profiles" + table_name: "profiles" + conflict_resolution: REPLACE + acl_authenticated: [CREATE] + create_access_rule: "_REQ_.user = _USER_.id" + }, + { + name: "profiles_view" + table_name: "profiles_view" + acl_authenticated: [READ] + read_access_rule: "_ROW_.user = _USER_.id" + }, + { + name: "articles" + table_name: "articles" + autofill_missing_user_id_columns: true + acl_authenticated: [CREATE, READ, UPDATE, DELETE] + create_access_rule: "(_REQ_.author IS NULL OR _REQ_.author = _USER_.id) AND EXISTS(SELECT * FROM editors WHERE user = _USER_.id)" + update_access_rule: "_ROW_.author = _USER_.id AND EXISTS(SELECT * FROM editors WHERE user = _USER_.id)" + delete_access_rule: "_ROW_.author = _USER_.id AND EXISTS(SELECT * FROM editors WHERE user = _USER_.id)" + }, + { + name: "articles_view" + table_name: "articles_view" + acl_world: [READ] + } +] +query_apis: [ + { + name: "is_editor" + virtual_table_name: "_is_editor" + params: [ + { + name: "user" + type: BLOB + } + ] + acl: WORLD + } +] diff --git a/examples/blog/traildepot/migrations/U1725019361__create_profiles.sql b/examples/blog/traildepot/migrations/U1725019361__create_profiles.sql new file mode 100644 index 0000000..3ef7ab5 --- /dev/null +++ b/examples/blog/traildepot/migrations/U1725019361__create_profiles.sql @@ -0,0 +1,37 @@ +-- Table with custom profile information. +-- +-- One could add more user information here, customize validation, etc. +CREATE TABLE profiles ( + user BLOB PRIMARY KEY NOT NULL REFERENCES _user(id) ON DELETE CASCADE, + + -- Make sure that usernames are at least 3 alphanumeric characters. + username TEXT NOT NULL CHECK(username REGEXP '^[\w]{3,}$'), + + created INTEGER DEFAULT (UNIXEPOCH()) NOT NULL, + updated INTEGER DEFAULT (UNIXEPOCH()) NOT NULL +) STRICT; + +-- Ensure usernames are unique. +CREATE UNIQUE INDEX _profiles__username_index ON profiles (username); + +-- Use trigger to manage the `updated` timestamp. +CREATE TRIGGER _profiles__updated_trigger AFTER UPDATE ON profiles FOR EACH ROW + BEGIN + UPDATE profiles SET updated = UNIXEPOCH() WHERE user = OLD.user; + END; + +-- Compile username, avatar_url, and editor_priviledges into a single read-only +-- API for convenience. +CREATE VIEW profiles_view AS + SELECT + p.*, + -- TrailBase requires top-level cast to determine result type and generate JSON schemas. + CAST(CASE + WHEN avatar.file IS NOT NULL THEN CONCAT('/api/records/v1/_user_avatar/', uuid_url_safe_b64(p.user), '/file/file') + ELSE NULL + END AS TEXT) AS avatar_url, + -- TrailBase requires top-level cast to determine result type and generate JSON schemas. + CAST(IIF(editors.user IS NULL, FALSE, TRUE) AS BOOLEAN) AS is_editor + FROM profiles AS p + LEFT JOIN _user_avatar AS avatar ON p.user = avatar.user + LEFT JOIN editors ON p.user = editors.user; diff --git a/examples/blog/traildepot/migrations/U1725019362__create_articles.sql b/examples/blog/traildepot/migrations/U1725019362__create_articles.sql new file mode 100644 index 0000000..032b466 --- /dev/null +++ b/examples/blog/traildepot/migrations/U1725019362__create_articles.sql @@ -0,0 +1,16 @@ +CREATE TABLE articles ( + id BLOB PRIMARY KEY NOT NULL CHECK(is_uuid_v7(id)) DEFAULT (uuid_v7()), + author BLOB NOT NULL REFERENCES _user(id) ON DELETE CASCADE, + + title TEXT NOT NULL, + intro TEXT NOT NULL, + tag TEXT NOT NULL, + body TEXT NOT NULL, + + image TEXT CHECK(jsonschema('std.FileUpload', image, 'image/png, image/jpeg')), + + created INTEGER DEFAULT (UNIXEPOCH()) NOT NULL +) STRICT; + +-- Join articles with user profiles to get the username. +CREATE VIEW articles_view AS SELECT a.*, p.username FROM articles AS a LEFT JOIN profiles AS p ON p.user = a.author; diff --git a/examples/blog/traildepot/migrations/U1725019363__create_editor_group.sql b/examples/blog/traildepot/migrations/U1725019363__create_editor_group.sql new file mode 100644 index 0000000..90f481d --- /dev/null +++ b/examples/blog/traildepot/migrations/U1725019363__create_editor_group.sql @@ -0,0 +1,10 @@ +-- Create a group that is used to gate write access to articles. Members of +-- this group can author articles. +CREATE TABLE editors ( + user BLOB NOT NULL, + + FOREIGN KEY(user) REFERENCES _user(id) ON DELETE CASCADE +) STRICT; + +-- Create an "is_editor" query api. +CREATE VIRTUAL TABLE _is_editor USING define((SELECT EXISTS (SELECT * FROM editors WHERE user = $1) AS is_editor)); diff --git a/examples/blog/traildepot/migrations/U1725019371__add_admin_user.sql b/examples/blog/traildepot/migrations/U1725019371__add_admin_user.sql new file mode 100644 index 0000000..e6bbf5c --- /dev/null +++ b/examples/blog/traildepot/migrations/U1725019371__add_admin_user.sql @@ -0,0 +1,10 @@ +-- Create admin user with "secret" password. +INSERT INTO _user + (email, password_hash, verified, admin) +VALUES + ('admin@localhost', (hash_password('secret')), TRUE, TRUE); + +-- Set a username for the admin user. +INSERT INTO profiles (user, username) + SELECT user.id, 'Admin' + FROM _user AS user WHERE email = 'admin@localhost'; diff --git a/examples/blog/traildepot/migrations/U1725019372__add_users.sql b/examples/blog/traildepot/migrations/U1725019372__add_users.sql new file mode 100644 index 0000000..be24b75 --- /dev/null +++ b/examples/blog/traildepot/migrations/U1725019372__add_users.sql @@ -0,0 +1,20 @@ +-- Add an editor +INSERT INTO _user (email, password_hash, verified) VALUES ('editor@localhost', (hash_password('secret')), TRUE); + +-- Set a username for the editor user. +INSERT INTO profiles (user, username) + SELECT user.id, 'Eddy Editor' + FROM _user AS user WHERE email = 'editor@localhost'; + +-- Add an avatar image for the editor user. +INSERT INTO _user_avatar (user, file) + SELECT user.id, '{"id":"0328bc95-9622-42e7-a609-625769a797c2","filename":"admin.png","content_type":"image/png","mime_type":"image/png"}' + FROM _user AS user WHERE email = 'editor@localhost'; + +-- Add the editor user to the editors group +INSERT INTO editors (user) + SELECT user.id FROM _user AS user WHERE email = 'editor@localhost'; + + +-- Add another user: non-admin, non-editor and w/o profile. +INSERT INTO _user (email, password_hash, verified) VALUES ('other@localhost', (hash_password('secret')), TRUE); diff --git a/examples/blog/traildepot/migrations/U1725019381__add_article.sql b/examples/blog/traildepot/migrations/U1725019381__add_article.sql new file mode 100644 index 0000000..1750a99 --- /dev/null +++ b/examples/blog/traildepot/migrations/U1725019381__add_article.sql @@ -0,0 +1,18 @@ +-- Bootstrap articles by inserting a dummy article for the admin user. +INSERT INTO articles ( + title, + intro, + tag, + author, + body, + image +) +SELECT + 'TrailBase is Here 🎉', + 'A rigorously simple and blazingly fast application base 😉', + 'important,example', + id, + 'TrailBase provides core functionality such restful APIs, file upload, auth, access control and a convenient admin dashboard out of the box.', + '{"id":"40e8d2a2-b025-435e-9aa0-4cb6b895ab2a","filename":"image.png","content_type":"image/png","mime_type":"image/png"}' +FROM _user +WHERE email = 'editor@localhost'; diff --git a/examples/blog/traildepot/uploads/0328bc95-9622-42e7-a609-625769a797c2 b/examples/blog/traildepot/uploads/0328bc95-9622-42e7-a609-625769a797c2 new file mode 100644 index 0000000000000000000000000000000000000000..037dc996e25f7473fa62b85ad17bdaeb63b55886 GIT binary patch literal 28861 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 literal 0 HcmV?d00001 diff --git a/examples/blog/traildepot/uploads/40e8d2a2-b025-435e-9aa0-4cb6b895ab2a b/examples/blog/traildepot/uploads/40e8d2a2-b025-435e-9aa0-4cb6b895ab2a new file mode 100644 index 0000000000000000000000000000000000000000..95c574a7a0cbeffb4a74ef8abe409aba4da2fa5d GIT binary patch literal 23528 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

nCzXzu zj4LB#5zQ4Yjfxg1zS_i?wICoM0GI(Kb)TG^92z>h>HJ>maVMrttf9)z+eaX&o+5o&)XAeQPIGuzfQK*p>1%u%rU&&3#&l8wqE%tB}$>jka*A@ z@WdC0h)d0iIhgrn?$KeS5|Jx4X|-FZk`5rV-j~vbjil}}8fA%OVZp&k*3CO^>mFgH zInx@FA3p|IT9umNLD@AcA))*7Hx$YOVWoPx_SM_(g266?^?OnaROUEk4D~8kY$GRb#QC=shcm|- zt!xURB?m*&A?u4O*%Hfs2FyHf0d!_?w5f^3L=G)4Z(2>qUm1O~2_Yz8)F|bAwKTww z8lL0L3bc>szQ=6Pyd8)oG`==V%*c>2G^8k1gk~mQTwG8H39U;dmsjFgZqLJ)#B=QN zkUzf{h~Gxe`M@kEFHcKB;or#V;TIS5@)ebkP|kjiSM@)KX*%{}caHW;4udT(Exq5K z3qX=1kqz<;LDiVZ5rhI`g9aeDp`cEm}=7w(>(jwg%n zXRVr)zSvuytp36UD5w8;oYo5Yyd6tTog)yxT=I!O=S}C>L>zh>4<9%?*b^Rl5Al_>8&Mj@s$S3Z}cv2PLYw<`^X0t#Uqg6VyL)=7`tpbk)U9p zibVyThdh)(9yN_SloApBjV$B0%(^mZWwc(meZx(A{E@hA(5NDWW~pwfWfs6GDwV6& zr~U#^af*(P9Eix6NiJ(+&ucwSNe0D!2)vLv(`iDxb<*chrKj$-R<}asa#OZMg5>N6 z%GP+(mPf<`D41PI+4Gau`$4p(G_Qo=hA$pyYFKd^!P5MSmy z`!*Ev`j1fKA4K9s7fg^JpPr5ZB#iKw7_Q{vlp!FaSxyyz^Yin~(8Q}pNBi~oe;Aou z;-rjciWi1XlS-PK(*cN=Mw=D&`8{R@1%=>{5P*pqT2oV#zsiRzUA>lWRWem0lSC;p zw;7luvCLe*QzD;Tdoo{hQ+>aM=7b8!*Z$V;b60hGIw3){>pclA!{kii<2tC znOk|xtVJzk8&pByR#aECZss@pr)GNLm4o;INT8ghaMF`g&=6d^|Wb6o-HyG*KmgXm2+iy^pRsQIPatv6^e^DbfCXTHm1Le}`O7 z*%8hnGH2WbZm04r<_a|00$vbw=Eb|JMJd;><3*|bOAf2Bw@y28I<)#5Ka~*SbTIa5 zXfK2JLYB13+j{(W-WvKLXnW!)`Dreiij;l6Mxs_$6$h)o8btnbvNqhDZy1pBIrf!R z1BKt8r)BvbpUDmJ(p2y0s^hNr##%j++fPBvh1LqWLM)*eL{zXRo0T8uQ&HZ|en(#c`-*b=JIS8u>o z#QNGw&*2R{CjGxF2liK6Tx5}ukWe5Hh}K<|L1zcBpYVVE`qdLG9D*GniUMJBACDB| zjN%cgqx${>n@R>Hff{4dMaIhu=IAn#MOt{&_w;G7A9%%#a1zUhWQ~nw@`RugQ;G#* z7v$gzX!OgCZom3mC1y<>yhtM_B`b^jDGW3DQER(qV75H*#1k2l zlp&T}P}?+FG+aUbf)t-=fO#F%KVljbj7=Yms`KOP>+d?vDQiZ8f`a`3*5~FX3*x5W z?%^?9JvcTd4-9|3Q427OI?A64d;y+*nfL$3&5;=tKQP%Gf&ffQ^t*agi_7uIQ5z;E zCKUsN6p$`Zk&%(L7Wg5MD4;e?$j)Yw`}tTKgQZ* z1OH3(%+IUeX0}zCo0w30dwcg4%ccgSK8S|Lg<#89Z9Xv2_5OF%HhRI>t-+{am}EFU zuv;##{qw29uzTQyBWFiX{v$sMUjVCr#E8Jo-x#0Ujr z_o3mxk7g{PP + + +No Image diff --git a/examples/blog/web/public/image.png b/examples/blog/web/public/image.png new file mode 100644 index 0000000000000000000000000000000000000000..95c574a7a0cbeffb4a74ef8abe409aba4da2fa5d GIT binary patch literal 23528 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

nCzXzu zj4LB#5zQ4Yjfxg1zS_i?wICoM0GI(Kb)TG^92z>h>HJ>maVMrttf9)z+eaX&o+5o&)XAeQPIGuzfQK*p>1%u%rU&&3#&l8wqE%tB}$>jka*A@ z@WdC0h)d0iIhgrn?$KeS5|Jx4X|-FZk`5rV-j~vbjil}}8fA%OVZp&k*3CO^>mFgH zInx@FA3p|IT9umNLD@AcA))*7Hx$YOVWoPx_SM_(g266?^?OnaROUEk4D~8kY$GRb#QC=shcm|- zt!xURB?m*&A?u4O*%Hfs2FyHf0d!_?w5f^3L=G)4Z(2>qUm1O~2_Yz8)F|bAwKTww z8lL0L3bc>szQ=6Pyd8)oG`==V%*c>2G^8k1gk~mQTwG8H39U;dmsjFgZqLJ)#B=QN zkUzf{h~Gxe`M@kEFHcKB;or#V;TIS5@)ebkP|kjiSM@)KX*%{}caHW;4udT(Exq5K z3qX=1kqz<;LDiVZ5rhI`g9aeDp`cEm}=7w(>(jwg%n zXRVr)zSvuytp36UD5w8;oYo5Yyd6tTog)yxT=I!O=S}C>L>zh>4<9%?*b^Rl5Al_>8&Mj@s$S3Z}cv2PLYw<`^X0t#Uqg6VyL)=7`tpbk)U9p zibVyThdh)(9yN_SloApBjV$B0%(^mZWwc(meZx(A{E@hA(5NDWW~pwfWfs6GDwV6& zr~U#^af*(P9Eix6NiJ(+&ucwSNe0D!2)vLv(`iDxb<*chrKj$-R<}asa#OZMg5>N6 z%GP+(mPf<`D41PI+4Gau`$4p(G_Qo=hA$pyYFKd^!P5MSmy z`!*Ev`j1fKA4K9s7fg^JpPr5ZB#iKw7_Q{vlp!FaSxyyz^Yin~(8Q}pNBi~oe;Aou z;-rjciWi1XlS-PK(*cN=Mw=D&`8{R@1%=>{5P*pqT2oV#zsiRzUA>lWRWem0lSC;p zw;7luvCLe*QzD;Tdoo{hQ+>aM=7b8!*Z$V;b60hGIw3){>pclA!{kii<2tC znOk|xtVJzk8&pByR#aECZss@pr)GNLm4o;INT8ghaMF`g&=6d^|Wb6o-HyG*KmgXm2+iy^pRsQIPatv6^e^DbfCXTHm1Le}`O7 z*%8hnGH2WbZm04r<_a|00$vbw=Eb|JMJd;><3*|bOAf2Bw@y28I<)#5Ka~*SbTIa5 zXfK2JLYB13+j{(W-WvKLXnW!)`Dreiij;l6Mxs_$6$h)o8btnbvNqhDZy1pBIrf!R z1BKt8r)BvbpUDmJ(p2y0s^hNr##%j++fPBvh1LqWLM)*eL{zXRo0T8uQ&HZ|en(#c`-*b=JIS8u>o z#QNGw&*2R{CjGxF2liK6Tx5}ukWe5Hh}K<|L1zcBpYVVE`qdLG9D*GniUMJBACDB| zjN%cgqx${>n@R>Hff{4dMaIhu=IAn#MOt{&_w;G7A9%%#a1zUhWQ~nw@`RugQ;G#* z7v$gzX!OgCZom3mC1y<>yhtM_B`b^jDGW3DQER(qV75H*#1k2l zlp&T}P}?+FG+aUbf)t-=fO#F%KVljbj7=Yms`KOP>+d?vDQiZ8f`a`3*5~FX3*x5W z?%^?9JvcTd4-9|3Q427OI?A64d;y+*nfL$3&5;=tKQP%Gf&ffQ^t*agi_7uIQ5z;E zCKUsN6p$`Zk&%(L7Wg5MD4;e?$j)Yw`}tTKgQZ* z1OH3(%+IUeX0}zCo0w30dwcg4%ccgSK8S|Lg<#89Z9Xv2_5OF%HhRI>t-+{am}EFU zuv;##{qw29uzTQyBWFiX{v$sMUjVCr#E8Jo-x#0Ujr z_o3mxk7g{PP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/blog/web/src/assets/default.jpg b/examples/blog/web/src/assets/default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b2d20430ac883c8301204d0936df1608c8f6c478 GIT binary patch literal 664742 zcmbrl2UJtf_V{~JfDl@M0HKH8g-}D25_<1N5$Q;4ZzaRdt0|+fOO*H@n0s$J=7w~tJ z)It-7yK7*iucoP^daVEeQVks!PcJY606aYXeT~$W(H54s&_oje7$61+0So}x+WUFy z8mpNA*FjSihxWTR`iK7$zRv^KIRU_|kcI&o{U7=NE26ab_VotHhW}G% zAlkA2$o`Y|KQgaU0KlGK`zGZ-GP_&=Xo&&<)Y5-soW%e@5eWdzlmGQRwEwi1d;b33 zGQz@vfq^$%9PMxX*#rXE3@lX=HlsmUEQ7zF8(fFo@f`(|6L9L ze@ymYW%vjG)vm9By8I7-yn6#cOd|EO#(oyo?dG}|E@P3Vl&{Mo@dUw_pf$; z&DZ+>iT`gAIQjY~*w4io{f`)DWP-L2@V);JU-yZBA_4#oPyk4P9$*1D0A4@{5Cx7N8U81_ppp zU<#N6mVtF(2RH&wfbYPs>w%02L2~q{=fQ&$vARCY~$P*L* zdI)+9N&uyS@<1h^YS2qi8>kyJ44MWlf;K=0pfk`V7y>2*Bf-pIZm=*I3swSagH6D9 zz|LSFa0oaOoCMARmxAlS&ERhED0mLM4n6{(LjVW~gciaE5rSYLIEX&v7Q_kS3kie7 zL$V;Hka|cvWDqh7S%-XrTtEq-)KD~32r3KJfSN+>p+3+sXd*NZS_N%}_CaT%8_*Nz z9|AH0CISHh83IiL3j$|?K!Rw3EP@Jx*983pa|AmC-w6o`X$g4=@Z!!`4dGG?G18h9oW|c#<5F7bHU@8zdK`RHXc*I8rOp0MaDVO42UUMbfWiWMtfA zie$IQ{K=BYs>yoE*2sR6Q7-b_A2eoR43!9}4&VNDT2kwwu&F-h?W zL5$!=;1ITmFhoA04Y7bYr=+IDQ0h~9P$p8=P!3b>QxQ>dQ>jupP(@OeQT0-7QA4OX zsBzTx)Q_plsr#vSkc3Dcq$bi8nSgwboIsw?P|=9fn9&5$m9GZ-=i zGCXDIXZXa3WRzvJXN+fTWL#nbGx0MSF+E@^V;W;RXJ%nmXZB{!W$tDE#6ruW$l}V9 z!Sa^nfR&o{CaVi;2J1W4Lo^Lq3GI%~LHD6g*qGQf*aFx}*e2M1vGcH-vPZBtu&;8! zIj|f~92p!v94DNtoVuJ3IcqtWxQMy1T=%%Lxdyp@aPx4RbH{MEaPRY=crP|RN+D4KOzz$?jq$P%NQz*7A6AIjyV(M7qu77 z7kw{ACZ;C#NUT-tR9ryZQT(a+2MKBkU5OZp9*N(QQj)%s^^yltoKiMY1yT!GB-Q|% zh#it9kXDv{B;6@}AtNc{FViUVMOH}GO}0jMUyeu4QLbEWOP*ccR=z}j{U-XR&CTMQ z>k4cNwhE;Rn~EHY4vH0udrEvtu1a-E$I2qgzRItaf8bE&Oyvl?sm8z*~ zp6Z$!yPC6Ft=fsYg!%*ZE)4<=ZH-io1x;p6d(CRi6D=vNP^~^~Qf*`HJnc;#ejQ(( zc3rTpmTtQ4iXNAqr(TObps%T)uD@!)W8h=ZVMu6bV3=>XYlJa+Xf$X{ZG6|b#`wF5 zvPrVZvMH}=fN75zg_)IEwb>7I74tOnbqisOP>WGZ21^&q)>}lk%x+cOI=`)YJM;FA zm4sEa)%+cvJ3)7btr@J{t>4_GxNCd2$%eqj+@{9n%2waD)b`v?)2_ho#2#m#ZGYsT z=#b%X;3)5y=D6o1@08}W?=0_}?tE}h;a=9gPcAr@JeN~f4c8*qA8z_?m2Q9C&D|S3 zU>-IeZJtz~Zk~N!EM7rg)7}E!(cbGmGCr9;C%)Rg6@DPUJASSH$m_+_SO9N8RKUjl zoA>kY{|qz>Yzm?b@(daa<`0ew-V0F+dG-MM!2UtcL$-(E4>v-ULQBFxVRm6Xk2oGh zKH9;nj?j>Jc9MX5*CMw3VTMlZz3#uUXuV_jk=;>6-| z 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 z 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

+ + {/* + {paginationEnabled && ( + + )} + */} + + ); +} + +function PaginationControl(props: { + table: TableType; + rowCount?: number; +}) { + const table = () => props.table; + + const PerPage = () => ( +
+ + per page +
+ ); + + const PaginationInfoText = () => { + const width = createWindowWidth(); + + const pageIndex = () => table().getState().pagination.pageIndex; + const pageCount = () => table().getPageCount(); + const rowCount = () => props.rowCount; + + return ( + <> + {rowCount() && width() > 578 + ? `page ${pageIndex() + 1} of ${pageCount()} (${rowCount()} rows total)` + : `page ${pageIndex() + 1} of ${pageCount()}`} + + ); + }; + + return ( +
+
+
+ + + + +
+ +
+ +
+
+ + +
+ ); +} diff --git a/ui/admin/src/components/auth/AccountsPage.tsx b/ui/admin/src/components/auth/AccountsPage.tsx new file mode 100644 index 0000000..3a24e4e --- /dev/null +++ b/ui/admin/src/components/auth/AccountsPage.tsx @@ -0,0 +1,17 @@ +import { Separator } from "@/components/ui/separator"; + +import { UserTable } from "./UserTable"; + +export function AccountsPage() { + return ( + <> +

Users

+ + + +
+ +
+ + ); +} diff --git a/ui/admin/src/components/auth/AddUser.tsx b/ui/admin/src/components/auth/AddUser.tsx new file mode 100644 index 0000000..f82a79a --- /dev/null +++ b/ui/admin/src/components/auth/AddUser.tsx @@ -0,0 +1,109 @@ +import type { JSXElement } from "solid-js"; +import { createForm } from "@tanstack/solid-form"; + +import { Button } from "@/components/ui/button"; +import { SheetHeader, SheetTitle, SheetFooter } from "@/components/ui/sheet"; + +import { + buildBoolFormField, + buildTextFormField, + notEmptyValidator, +} from "@/components/FormFields"; +import type { CreateUserRequest } from "@/lib/bindings"; +import { createUser } from "@/lib/user"; + +export function AddUser(props: { + close: () => void; + markDirty: () => void; + userRefetch: () => void; +}) { + const form = createForm(() => ({ + defaultValues: { + email: "", + password: "", + verified: true, + admin: false, + }, + onSubmit: async ({ value }) => { + createUser(value) + .then(() => { + props.userRefetch(); + props.close(); + }) + .catch(console.error); + }, + })); + + return ( +
+ + {"Add new user"} + + +
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ + {buildTextFormField({ label: () => E-mail, type: "email" })} + + + + {buildTextFormField({ + label: () => Password, + type: "password", + })} + + + + {buildBoolFormField({ + label: () => ( + +
Admin
+
+ ), + })} +
+ + + {buildBoolFormField({ + label: () => ( + +
Verified
+
+ ), + })} +
+
+ + + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + children={(state) => { + return ( + + ); + }} + /> + +
+
+ ); +} + +function L(props: { children: JSXElement }) { + return
{props.children}
; +} diff --git a/ui/admin/src/components/auth/AuthButton.tsx b/ui/admin/src/components/auth/AuthButton.tsx new file mode 100644 index 0000000..aba0f13 --- /dev/null +++ b/ui/admin/src/components/auth/AuthButton.tsx @@ -0,0 +1,74 @@ +import { createEffect, createSignal, Show } from "solid-js"; +import { useStore } from "@nanostores/solid"; +import { TbUser } from "solid-icons/tb"; +import { type User } from "trailbase"; + +import { urlSafeBase64ToUuid } from "@/lib/utils"; +import { client, $user } from "@/lib/fetch"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; + +const navBarIconSize = 22; +const style = + "rounded-full hover:bg-accent-600 hover:text-white transition-all p-[10px]"; + +function Profile(props: { user: User }) { + const profile = props.user; + + // TODO: Bring back avater. + return ( +
+
E-mail: {profile.email}
+ +
id: {urlSafeBase64ToUuid(profile.id)}
+ + {import.meta.env.DEV &&
id b64: {profile.id}
} +
+ ); +} + +export function AuthButton() { + const [open, setOpen] = createSignal(false); + const user = useStore($user); + + createEffect(() => { + console.log("user", user()); + }); + + return ( + + + + + + Current User + + + + + + + + + + + + + ); +} diff --git a/ui/admin/src/components/auth/LoginPage.tsx b/ui/admin/src/components/auth/LoginPage.tsx new file mode 100644 index 0000000..74a3d7c --- /dev/null +++ b/ui/admin/src/components/auth/LoginPage.tsx @@ -0,0 +1,76 @@ +import { createSignal } from "solid-js"; +import { client } from "@/lib/fetch"; + +import { showToast } from "@/components/ui/toast"; +import { Button } from "@/components/ui/button"; +import { Card } from "@/components/ui/card"; +import { + TextField, + TextFieldLabel, + TextFieldInput, +} from "@/components/ui/text-field"; + +export function LoginPage() { + const [username, setUsername] = createSignal(""); + const [password, setPassword] = createSignal(""); + + const onSubmit = async () => { + try { + await client.login(username(), password()); + } catch (err) { + showToast({ + title: "Uncaught Error", + description: `${err}`, + variant: "error", + }); + } + // Don't reload. + return false; + }; + + return ( +
+ +
+

Login

+ + + E-mail + + { + const target = e.currentTarget as HTMLInputElement; + setUsername(target.value); + }} + /> + + + + Password + + { + const target = e.currentTarget as HTMLInputElement; + setPassword(target.value); + }} + /> + + +
+ +
+
+
+
+ ); +} diff --git a/ui/admin/src/components/auth/UserTable.tsx b/ui/admin/src/components/auth/UserTable.tsx new file mode 100644 index 0000000..3a505c4 --- /dev/null +++ b/ui/admin/src/components/auth/UserTable.tsx @@ -0,0 +1,363 @@ +import { + createResource, + createSignal, + Match, + Show, + Switch, + Suspense, +} from "solid-js"; +import type { Setter, JSXElement } from "solid-js"; +import { createForm } from "@tanstack/solid-form"; +import { TbCrown } from "solid-icons/tb"; +import type { DialogTriggerProps } from "@kobalte/core/dialog"; + +import { + type ColumnDef, + createColumnHelper, + PaginationState, +} from "@tanstack/solid-table"; +import { Button } from "@/components/ui/button"; +import { FilterBar } from "@/components/FilterBar"; +import { + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/sheet"; + +import { Checkbox } from "@/components/ui/checkbox"; +import { DataTable } from "@/components/Table"; +import { Label } from "@/components/ui/label"; +import { AddUser } from "@/components/auth/AddUser"; +import { deleteUser, updateUser } from "@/lib/user"; +import type { + UpdateUserRequest, + UserJson, + ListUsersResponse, +} from "@/lib/bindings"; +import { + buildTextFormField, + buildOptionalTextFormField, +} from "@/components/FormFields"; +import { SafeSheet, SheetContainer } from "@/components/SafeSheet"; +import { adminFetch } from "@/lib/fetch"; + +type FetchArgs = { + filter: string | undefined; + pageSize: number; + pageIndex: number; + cursors: string[]; +}; + +export async function fetchUsers( + source: FetchArgs, + { value }: { value: ListUsersResponse | undefined }, +): Promise { + const pageIndex = source.pageIndex; + const limit = source.pageSize; + const cursors = source.cursors; + + const filter = source.filter ?? ""; + const filterQuery = filter + .split("AND") + .map((frag) => frag.trim().replaceAll(" ", "")) + .join("&"); + + console.log("QUERY: ", filterQuery); + + const params = new URLSearchParams(filterQuery); + params.set("limit", limit.toString()); + + // Build the next UUIDv7 "cursor" from previous response and update local + // cursor stack. If we're paging forward we add new cursors, otherwise we're + // re-using previously seen cursors for consistency. We reset if we go back + // to the start. + if (pageIndex === 0) { + cursors.length = 0; + } else { + const index = pageIndex - 1; + if (index < cursors.length) { + // Already known page + params.set("cursor", cursors[index]); + } else { + // New page case: use cursor from previous response or fall back to more + // expensive and inconsistent offset-based pagination. + const cursor = value?.cursor; + if (cursor) { + cursors.push(cursor); + params.set("cursor", cursor); + } else { + params.set("offset", `${pageIndex * source.pageSize}`); + } + } + } + + try { + const response = await adminFetch(`/user?${params}`); + return await response.json(); + } catch (err) { + if (value) { + return value; + } + throw err; + } +} + +const columnHelper = createColumnHelper(); + +function buildColumns( + setEditUser: Setter, + userRefetch: () => void, +): ColumnDef[] { + return [ + { + header: "id", + accessorFn: ({ id }) => id, + }, + columnHelper.accessor("email", { header: "email" }) as ColumnDef, + { + header: "verified", + accessorFn: ({ verified }) => Boolean(verified), + }, + columnHelper.accessor("id", { + header: "Admin", + cell: (ctx) => ( +
+ {ctx.row.original.admin ? : null} +
+ ), + }) as ColumnDef, + columnHelper.display({ + header: "Actions", + cell: (ctx) => { + const userId = ctx.row.original.id; + return ( +
+ + + +
+ ); + }, + }), + ]; +} + +function EditSheetContent(props: { + user: UserJson; + close: () => void; + markDirty: () => void; + refetch: () => void; +}) { + const form = createForm(() => ({ + defaultValues: { + id: props.user.id, + email: props.user.email, + password: null, + verified: props.user.verified, + }, + onSubmit: async ({ value }) => { + updateUser(value) + .then(() => props.close()) + .catch(console.error); + + props.refetch(); + }, + })); + + return ( + + + Edit User + + Change a user's properties. Be careful + + +
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ + {buildTextFormField({ + label: () => E-mail, + type: "email", + })} + + + + {buildOptionalTextFormField({ + label: () => Password, + type: "password", + })} + + + + {(field) => ( +
+ + +
+ )} +
+
+ + + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + children={(state) => { + return ( + + ); + }} + /> + +
+
+ ); +} + +export function UserTable() { + const [filter, setFilter] = createSignal(); + const [pagination, setPagination] = createSignal({ + pageSize: 20, + pageIndex: 0, + }); + const cursors: string[] = []; + + const buildFetchArgs = (): FetchArgs => ({ + pageSize: pagination().pageSize, + pageIndex: pagination().pageIndex, + cursors: cursors, + filter: filter(), + }); + + const [users, { refetch }] = createResource(buildFetchArgs, fetchUsers); + const [editUser, setEditUser] = createSignal(); + + const columns = () => buildColumns(setEditUser, refetch); + + return ( + Loading...
}> + + + Error: {users.error} + + + +
+ { + if (value === filter()) { + refetch(); + } else { + setFilter(value); + } + }} + example='e.g. "email[like]=%@foo.com"' + /> + +
+ users()?.users} + rowCount={Number(users()?.total_row_count)} + initialPagination={pagination()} + onPaginationChange={setPagination} + /> +
+ + { + return ( + <> + + + + + ( + + )} + /> + + ); + }} + /> + + {/* WARN: This might open multiple sheets or at least scrims for each row */} + editUser() !== undefined, + (isOpen: boolean | ((value: boolean) => boolean)) => { + if (!isOpen) { + setEditUser(undefined); + } + }, + ]} + children={(sheet) => { + return ( + + + + + + ); + }} + /> +
+
+
+ + ); +} + +function L(props: { children: JSXElement }) { + return
{props.children}
; +} + +const sheetMaxWidth = "sm:max-w-[520px]"; diff --git a/ui/admin/src/components/editor/EditorPage.tsx b/ui/admin/src/components/editor/EditorPage.tsx new file mode 100644 index 0000000..287e2d9 --- /dev/null +++ b/ui/admin/src/components/editor/EditorPage.tsx @@ -0,0 +1,443 @@ +import { + For, + Match, + Show, + Switch, + createEffect, + createResource, + createSignal, + onCleanup, + onMount, +} from "solid-js"; +import { createWritableMemo } from "@solid-primitives/memo"; +import type { Accessor, Signal } from "solid-js"; +import type { ColumnDef } from "@tanstack/solid-table"; +import { persistentAtom } from "@nanostores/persistent"; +import { useStore } from "@nanostores/solid"; +import { TbTrash, TbEdit, TbDeviceFloppy, TbHelp } from "solid-icons/tb"; + +import { Separator } from "@/components/ui/separator"; +import { EditorView, keymap, lineNumbers, gutter } from "@codemirror/view"; +import { EditorState } from "@codemirror/state"; +import { defaultKeymap } from "@codemirror/commands"; +import { + syntaxHighlighting, + defaultHighlightStyle, +} from "@codemirror/language"; +import { sql } from "@codemirror/lang-sql"; + +import { SplitView } from "@/components/SplitView"; +import { + Resizable, + ResizablePanel, + ResizableHandle, +} from "@/components/ui/resizable"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, + DialogFooter, +} from "@/components/ui/dialog"; +import { TextField, TextFieldInput } from "@/components/ui/text-field"; + +import { DataTable } from "@/components/Table"; +import type { QueryRequest, QueryResponse } from "@/lib/bindings"; +import { adminFetch } from "@/lib/fetch"; +import { isNotNull } from "@/lib/schema"; + +async function executeSql( + sql: string | undefined, +): Promise { + if (sql === undefined) { + return undefined; + } + + const response = await adminFetch("/query", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: sql, + } as QueryRequest), + }); + + return await response.json(); +} + +type RowData = Array; + +function View(props: { response: Accessor }) { + const response = () => props.response(); + + const columnDefs = (): ColumnDef[] => { + return (response()?.columns ?? []).map((col, idx) => { + const notNull = isNotNull(col.options); + + const header = `${col.name} [${col.data_type}${notNull ? "" : "?"}]`; + return { + accessorFn: (row) => row[idx], + header, + }; + }); + }; + + return ( + No Data}> + + 0}> + response()!.rows as RowData[]} + /> + + + + No data returned by query + + + + ); +} + +function SideBar(props: { + selectedSignal: Signal; + horizontal: boolean; +}) { + const [selected, setSelected] = props.selectedSignal; + const scripts = useStore($scripts); + + function addNewScript() { + const s = [ + ...$scripts.get(), + { + name: "New Script", + contents: "SELECT COUNT(*) FROM _user;", + }, + ]; + $scripts.set(s); + + setSelected(s.length - 1); + } + + const flexStyle = () => (props.horizontal ? "flex flex-col h-dvh" : "flex"); + return ( +
+ + {(_script: Script, index: Accessor) => { + const scriptName = () => scripts()[index()].name; + return ( + + ); + }} + + + +
+ ); +} + +function HelpDialog() { + return ( + + + + + + + + Editor Help + + +

+ The editor lets you execute arbitrary SQL statements, so be careful + with what you wish for. If you just want to experiment, consider + working on a non-prod data set or a copy. +

+ +

+ Further note that there's no pagination, so whatever you query will be + returned. Working on large data sets, you might want to{" "} + LIMIT your result size. +

+ +

+ Also note that scripts are currently stored in your browser's local + storage. This means, switching devices, browsers, or the origin of + your website, you won't have access to your scripts. This is something + we'd like to lower into the database layer in the future. +

+
+
+ ); +} + +function RenameDialog(props: { selected: number; script: Script }) { + const [open, setOpen] = createSignal(false); + const [name, setName] = createWritableMemo(() => props.script.name); + + const onSubmit = () => { + updateExistingScript(props.selected, { + ...props.script, + name: name(), + }); + setOpen(false); + }; + + return ( + + + + + + + + Rename + + +
+ + { + setName((e.target as HTMLInputElement).value); + }} + /> + + + + + +
+
+
+ ); +} + +function EditorPanel(props: { selectedSignal: Signal }) { + const [selected, setSelected] = props.selectedSignal; + + const scripts = useStore($scripts); + const script = (): Script => { + const s = scripts(); + if (selected() < s.length) { + return s[selected()]; + } + if (s.length === 0) { + return defaultScript; + } + return s[s.length - 1]; + }; + + const [queryString, setQueryString] = createSignal(); + const [executionResult, { mutate, refetch }] = createResource( + queryString, + executeSql, + ); + + createEffect(() => { + // Subscribe to selected script changes and reset the query results. + selected(); + const r = executionResult(); + if (r && editor?.state.doc.toString() !== queryString()) { + mutate(undefined); + } + }); + + const execute = () => { + const text = editor?.state.doc.toString(); + if (text) { + // We need to distinguish to work-around createResources caching. + if (queryString() === text) { + refetch(); + } else { + setQueryString(text); + } + } + }; + + let ref: HTMLDivElement | undefined; + let editor: EditorView | undefined; + + const newEditorState = (contents: string) => + EditorState.create({ + doc: contents, + extensions: [ + myTheme, + keymap.of([ + { + key: "Ctrl-Enter", + run: () => { + execute(); + return true; + }, + }, + ...defaultKeymap, + ]), + lineNumbers(), + gutter({ class: "cm-mygutter" }), + sql(), + syntaxHighlighting(defaultHighlightStyle), + ], + }); + + onCleanup(() => { + console.debug("editor cleanup"); + editor?.destroy(); + }); + onMount(() => { + editor?.destroy(); + editor = new EditorView({ + state: newEditorState(script().contents), + parent: ref!, + }); + editor.focus(); + }); + + createEffect(() => { + console.debug("setting editor state"); + const s = script(); + editor?.setState(newEditorState(s.contents)); + }); + + return ( + <> + + +

+
+ Editor + > + {script().name} + + + + { + const e = editor; + if (e) { + updateExistingScript(selected(), { + ...script(), + contents: e.state.doc.toString(), + }); + } + }} + /> +
+ +
+ + { + $scripts.set($scripts.get().toSpliced(selected(), 1)); + setSelected(Math.max(0, selected() - 1)); + }} + /> +
+

+ + + +
+ {/* Editor */} +
+
+
+ +
+ +
+
+ + + + + + + + + + ); +} + +export function EditorPage() { + const selectedSignal = createSignal(0); + + return ( + { + return ( + + ); + }} + second={() => { + return ; + }} + /> + ); +} + +export default EditorPage; + +const myTheme = EditorView.theme( + { + ".cm-gutters": { + backgroundColor: "#eeeeee", + color: "#000", + border: "none", + }, + }, + { dark: false }, +); + +type Script = { + name: string; + contents: string; +}; + +const defaultScript: Script = { + name: "Select", + contents: "SELECT\n *\nFROM\n _user;", +}; + +// NOTE: It seems like "nanostores" diffs array contents. It re-renders, if the array +// object is different and at least one of the contained objects has a different id. +// In other words just copying the array and setting a new Script.name, doesn't trigger, +// we have to replace the entire script. +// If this behavior is documented somewhere, I couldn't find it. I wish it would be less +// smart :/. +function updateExistingScript(index: number, script: Script) { + const s = [...$scripts.get()]; + s[index] = { + ...script, + }; + $scripts.set(s); +} + +const $scripts = persistentAtom("scripts", [defaultScript], { + encode: JSON.stringify, + decode: JSON.parse, +}); diff --git a/ui/admin/src/components/logs/LogsPage.tsx b/ui/admin/src/components/logs/LogsPage.tsx new file mode 100644 index 0000000..0d4c307 --- /dev/null +++ b/ui/admin/src/components/logs/LogsPage.tsx @@ -0,0 +1,337 @@ +import { + Match, + Switch, + createEffect, + createResource, + createSignal, + onCleanup, +} from "solid-js"; +import { useSearchParams } from "@solidjs/router"; +import { + type ColumnDef, + createColumnHelper, + type PaginationState, +} from "@tanstack/solid-table"; +import { Chart } from "chart.js/auto"; +import type { + ChartData, + ScriptableLineSegmentContext, + TooltipItem, +} from "chart.js/auto"; +import { TbRefresh } from "solid-icons/tb"; + +import { Separator } from "@/components/ui/separator"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; + +import { DataTable, defaultPaginationState } from "@/components/Table"; +import { FilterBar } from "@/components/FilterBar"; +import type { LogJson, ListLogsResponse, Stats } from "@/lib/bindings"; +import { adminFetch } from "@/lib/fetch"; + +const columnHelper = createColumnHelper(); + +const columns: ColumnDef[] = [ + columnHelper.display({ + header: "Created", + cell: (ctx) => { + const timestamp = new Date(ctx.row.original.created * 1000); + return ( + + {timestamp.toUTCString()} + + + {timestamp.toLocaleString()} (Local) + + + ); + }, + }), + { + accessorKey: "type", + cell: (ctx) => { + const type = ctx.row.original.type; + if (type === 2) { + return "HTTP"; + } else if (type === 1) { + return "Admin API"; + } else if (type === 3) { + return "Record API"; + } + return type; + }, + }, + columnHelper.display({ + header: "Level", + cell: (ctx) => <>{levelToName.get(ctx.row.original.level)}, + }), + { accessorKey: "status" }, + { accessorKey: "method" }, + { accessorKey: "url" }, + { + accessorKey: "latency_ms", + header: "Latency (ms)", + }, + { accessorKey: "client_ip" }, + { accessorKey: "referer" }, + { + accessorKey: "user_agent", + cell: (ctx) => { + return ( + + +
+ {ctx.row.original.user_agent} +
+
+ + {ctx.row.original.user_agent} +
+ ); + }, + }, + { accessorKey: "data" }, +]; + +type GetLogsProps = { + pagination: PaginationState; + // Filter where clause to pass to the fetch. + filter?: string; + // Keep track of the timestamp cursor to have consistency for forwards and backwards pagination. + cursors: string[]; +}; + +// Value is the previous value in case this isn't the first fetch. +async function getLogs( + source: GetLogsProps, + { value }: { value: ListLogsResponse | undefined }, +): Promise { + const pageIndex = source.pagination.pageIndex; + const limit = source.pagination.pageSize; + const filter = source.filter ?? ""; + + // Here we're setting the timestamp "cursor". If we're paging forward we add new cursors. + // otherwise we're re-using previously seen cursors for consistency. We reset if we go back + // to the start. + const cursor = (() => { + if (pageIndex === 0) { + source.cursors.length = 0; + return undefined; + } + + const cursors = source.cursors; + const index = pageIndex - 1; + if (index < cursors.length) { + return cursors[index]; + } + + // New page case. + const cursor = value!.cursor; + if (cursor) { + cursors.push(cursor); + return cursor; + } + })(); + + const filterQuery = filter + .split("AND") + .map((frag) => frag.trim().replaceAll(" ", "")) + .join("&"); + + const params = new URLSearchParams(filterQuery); + params.set("limit", limit.toString()); + if (cursor) { + params.set("cursor", cursor); + } + + console.debug("Fetching logs for ", params); + const response = await adminFetch(`/logs?${params}`); + return await response.json(); +} + +export function LogsPage() { + const [searchParams, setSearchParams] = useSearchParams<{ + filter: string; + }>(); + const [filter, setFilter] = createSignal( + searchParams.filter, + ); + createEffect(() => { + setSearchParams({ filter: filter() }); + }); + + const [pagination, setPagination] = createSignal( + defaultPaginationState(), + ); + const cursors: string[] = []; + const getLogsProps = (): GetLogsProps => { + return { + pagination: pagination(), + filter: filter(), + cursors, + }; + }; + const [logsFetch, { refetch }] = createResource(getLogsProps, getLogs); + + return ( + <> +
+

Logs

+ + +
+ + + +
+ { + if (value === filter()) { + refetch(); + } else { + setFilter(value); + } + }} + example='e.g. "latency[lt]=2 AND status=200"' + /> + + + +

Loading...

+
+ + Error {`${logsFetch.error}`} + + + {pagination().pageIndex === 0 && ( + + )} + + columns} + data={() => logsFetch()?.entries} + rowCount={Number(logsFetch()?.total_row_count ?? -1)} + onPaginationChange={setPagination} + initialPagination={pagination()} + /> + +
+
+ + ); +} + +function changeDistantPointLineColorToTransparent( + ctx: ScriptableLineSegmentContext, +) { + const secondsApart = Math.abs(ctx.p0.parsed.x - ctx.p1.parsed.x) / 1000; + if (secondsApart > 1200) { + return "transparent"; + } + return undefined; +} + +function LogsChart(props: { stats?: Stats }) { + const stats = props.stats; + if (!stats) { + return null; + } + + const data = (): ChartData | undefined => { + const s = stats; + if (!s) return; + + const labels = s.rate.map(([ts, _v]) => Number(ts) * 1000); + const data = s.rate.map(([_ts, v]) => v); + + return { + labels, + datasets: [ + { + data, + label: "Rate", + showLine: true, + fill: false, + segment: { + borderColor: changeDistantPointLineColorToTransparent, + }, + spanGaps: true, + }, + ], + }; + }; + + let ref: HTMLCanvasElement | undefined; + let chart: Chart | undefined; + + onCleanup(() => chart?.destroy()); + createEffect(() => { + if (chart) { + chart.destroy(); + } + + const d = data(); + if (d) { + chart = new Chart(ref!, { + type: "scatter", + data: d, + options: { + // animation: false, + maintainAspectRatio: false, + scales: { + x: { + ticks: { + callback: (value: number | string) => { + return new Date(value).toLocaleTimeString(); + }, + }, + }, + }, + plugins: { + legend: { + display: false, // This hides all text in the legend and also the labels. + }, + // https://www.chartjs.org/docs/latest/configuration/tooltip.html + tooltip: { + enabled: true, + callbacks: { + title: (items: TooltipItem<"scatter">[]) => { + return items.map((item) => { + const ts = new Date(item.parsed.x); + return ts.toUTCString(); + }); + }, + label: (item: TooltipItem<"scatter">) => { + return `rate: ${item.parsed.y.toPrecision(2)}/s`; + }, + }, + }, + }, + }, + }); + } + }); + + return ( +
+ +
+ ); +} + +const logLevels: Array<[number, string]> = [ + [4, "TRACE"], + [3, "DEBUG"], + [2, "INFO"], + [1, "WARN"], + [0, "ERROR"], +] as const; + +const levelToName: Map = new Map(logLevels); + +export default LogsPage; diff --git a/ui/admin/src/components/settings/AuthSettings.tsx b/ui/admin/src/components/settings/AuthSettings.tsx new file mode 100644 index 0000000..788009f --- /dev/null +++ b/ui/admin/src/components/settings/AuthSettings.tsx @@ -0,0 +1,475 @@ +import { + createResource, + For, + Suspense, + Switch, + Match, + createSignal, + createMemo, +} from "solid-js"; +import { createForm } from "@tanstack/solid-form"; + +import { + buildTextFormField, + buildNumberFormField, + buildSecretFormField, +} from "@/components/FormFields"; +import type { FormType } from "@/components/FormFields"; +import { + TbCircleCheck, + TbCircle, + TbCirclePlus, + TbArrowBackUp, + TbTrash, +} from "solid-icons/tb"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader } from "@/components/ui/card"; + +import type { OAuthProviderResponse, OAuthProviderEntry } from "@/lib/bindings"; +import { AuthConfig, Config, OAuthProviderConfig } from "@proto/config"; +import { createConfigQuery, setConfig } from "@/lib/config"; +import { adminFetch } from "@/lib/fetch"; +import { showSaveFileDialog } from "@/lib/utils"; + +// Using a proxy struct since tanstack only deals with arrays and not maps. +// And rather than trying to hack it an converting on the fly, we're converting +// once upfront from config to proxy and back on submission. +type State = { + clientId?: string; + clientSecret?: string; +}; +type NamedOAuthProvider = { + provider: OAuthProviderEntry; + state?: State; +}; +type AuthConfigProxy = Omit & { + namedOauthProviders: NamedOAuthProvider[]; +}; + +function nonEmpty(v: string | undefined): string | undefined { + return v && v !== "" ? v : undefined; +} + +export async function adminListOAuthProviders(): Promise { + const response = await adminFetch("/oauth_providers", { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + return await response.json(); +} + +function createSetOnce(initial: T): [ + () => T, + (v: T) => void, + { + reset: (v: T) => void; + }, +] { + let called = false; + const [v, setV] = createSignal(initial); + + const setter = (v: T) => { + if (!called) { + called = true; + setV(() => v); + } + }; + + return [v, setter, { reset: setV }]; +} + +function configToProxy( + providers: Array, + config: AuthConfig, +): AuthConfigProxy { + const idToConfig = new Map( + Object.values(config.oauthProviders).map((c) => { + const providerId = c.providerId; + if (!providerId) { + console.warn("missing provider id:", c); + return [-1, c]; + } + + return [providerId, c]; + }), + ); + + return { + ...config, + namedOauthProviders: providers.map((p): NamedOAuthProvider => { + const config = idToConfig.get(p.id); + const clientId = config?.clientId; + + return { + provider: p, + state: clientId + ? { + clientId: clientId, + // NOTE: This is basically undefined since the config doesn't contain the striped secret. + clientSecret: config?.clientSecret, + } + : undefined, + }; + }), + }; +} + +function proxyToConfig(proxy: AuthConfigProxy): AuthConfig { + const config = AuthConfig.fromPartial({ + ...(proxy as Omit), + }); + config.oauthProviders = {}; + + for (const entry of proxy.namedOauthProviders) { + const p = entry.provider; + const clientId = entry.state?.clientId; + const clientSecret = entry.state?.clientSecret; + + if (clientId && clientSecret) { + config.oauthProviders[p.name] = { + providerId: p.id, + displayName: p.display_name, + clientId, + clientSecret, + }; + } else { + console.debug("Skipping: ", entry); + } + } + return config; +} + +function ProviderSettingsSubForm(props: { + form: FormType; + index: number; + provider: OAuthProviderEntry; +}) { + const [original, setOnce, { reset }] = createSetOnce( + undefined, + ); + + const current = props.form.useStore((state) => { + if (state.isSubmitted) { + reset(state.values.namedOauthProviders[props.index].state); + } + + const s = state.values.namedOauthProviders[props.index].state; + setOnce({ ...s }); + return s; + }); + + const dirty = () => { + const id = nonEmpty(current()?.clientId) !== nonEmpty(original()?.clientId); + const secret = + nonEmpty(current()?.clientSecret) !== nonEmpty(original()?.clientSecret); + return id || secret; + }; + + const icon = () => { + if (dirty()) { + return ; + } + + if (current()?.clientId !== undefined) { + return ; + } + + return ; + }; + + return ( + + +
+ {icon()} + {props.provider.display_name} +
+
+ + +
+ { + if (value === "") return "Must not be empty"; + }, + }} + > + {buildTextFormField({ label: () => "Client Id", required: false })} + + + { + if (value === "") return "Must not be empty"; + }, + }} + > + {buildSecretFormField({ + label: () => "Client Secret", + required: false, + })} + +
+ +
+ + + +
+
+
+ ); +} +function AuthSettingsForm(props: { + config: Config; + providers: OAuthProviderResponse; + markDirty: () => void; + postSubmit: () => void; +}) { + const values = createMemo(() => + configToProxy( + props.providers.providers, + props.config.auth ?? AuthConfig.create(), + ), + ); + + const form = createForm(() => ({ + defaultValues: values(), + onSubmit: async ({ value }) => { + const newConfig = Config.decode(Config.encode(props.config).finish()); + newConfig.auth = proxyToConfig(value); + + console.debug("Submitting provider config:", value); + await setConfig(newConfig); + + props.postSubmit(); + }, + })); + + form.useStore((state) => { + if (state.isDirty && !state.isSubmitted) { + props.markDirty(); + } + }); + + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ + +

Token Settings

+
+ + +
+ + {buildNumberFormField({ + integer: true, + label: () =>
Auth TTL [sec]
, + info: ( +

+ AuthToken TTL. Older tokens are invalid. A new AuthToken + can be minted given a valid refresh Token. +

+ ), + })} +
+ + + {buildNumberFormField({ + integer: true, + label: () =>
Refresh TTL [sec]
, + info: ( +

+ RefreshToken TTL. Older tokens are invalid. A refresh + token can only be renewed by users logging in anew. +

+ ), + })} +
+
+
+
+ + + +

Public Key

+
+ + +

+ TrailBase uses short-lived, stateless JWT Auth tokens and + asymmetric public/private key cryptography (Ed25519 elliptic + curves) in combination with longer-lived, stateful refresh tokens. + Refresh tokens can be trivially exchanged for a fresh short-lived + auth token for as long as the refresh token has neither expired + nor been revoked. The main benefit of self-contained, stateless + auth is that other backend services you may run can simply + authenticate users by validating a given auth token against the + public key below w/o having to talk to TrailBase. It's important + that you keep the corresponding private key secret at all times. +

+ +

+ A common concern with stateless auth, as opposed to stateful + session-based auth, is the inability to revoke access in case an + auth token ever leaks. This is why, Auth tokens are short-lived to + reduce the impact of any such leak. +

+ + +
+
+ + + +

OAuth Providers

+
+ + + + {(_field) => { + return ( + + + {(provider, index) => { + const idx: number = index(); + + return ( + + ); + }} + + + ); + }} + + +
+ +
+ ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + > + {(state) => { + return ( + + ); + }} + +
+
+ + ); +} + +export function AuthSettings(props: { + markDirty: () => void; + postSubmit: () => void; +}) { + const [providers] = createResource(adminListOAuthProviders); + const config = createConfigQuery(); + + const protoConfig = () => { + const c = config.data?.config; + if (c) { + // "deep-copy" + return Config.decode(Config.encode(c).finish()); + } + // Fallback + return Config.create(); + }; + + return ( + Loading...
}> + + + Error: {providers.error?.toString()} + + + + Error: {config.error?.toString()} + + + + + + + + ); +} + +const labelWidth = "w-40"; diff --git a/ui/admin/src/components/settings/EmailSettings.tsx b/ui/admin/src/components/settings/EmailSettings.tsx new file mode 100644 index 0000000..d7f8e3d --- /dev/null +++ b/ui/admin/src/components/settings/EmailSettings.tsx @@ -0,0 +1,255 @@ +import type { JSXElement } from "solid-js"; +import { createForm } from "@tanstack/solid-form"; + +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader } from "@/components/ui/card"; + +import { + notEmptyValidator, + buildTextFormField, + buildTextAreaFormField, + buildNumberFormField, + largerThanZero, + buildSecretFormField, +} from "@/components/FormFields"; +import type { FormType } from "@/components/FormFields"; +import { Config, EmailConfig } from "@proto/config"; +import { createConfigQuery, setConfig } from "@/lib/config"; + +function EmailTemplate(props: { + form: FormType; + fieldName: string; +}) { + const form = props.form; + + return ( +
+ + {buildTextFormField({ + label: () => Subject, + info: ( +

+ Email's subject line. Valid template parameters:{" "} + + {"{{APP_NAME}}"} + + . +

+ ), + })} +
+ + + {buildTextAreaFormField( + { + label: () => Body, + info: ( +

+ Email's body. Valid template parameters:{" "} + + {"{{ APP_NAME }}"} + + ,{" "} + + {"{{ SITE_URL }}"} + + , and{" "} + + {"{{ CODE }}"} + + . +

+ ), + }, + 10, + )} +
+
+ ); +} + +export function EmailSettings(props: { + markDirty: () => void; + postSubmit: () => void; +}) { + const config = createConfigQuery(); + + const Form = (p: { config: EmailConfig }) => { + const form = createForm(() => ({ + defaultValues: p.config, + onSubmit: async ({ value }) => { + const c = config.data?.config; + if (!c) { + console.warn("Missing base config."); + return; + } + + const newConfig = Config.fromPartial(c); + newConfig.email = value; + await setConfig(newConfig); + + props.postSubmit(); + }, + })); + + form.useStore((state) => { + if (state.isDirty && !state.isSubmitted) { + props.markDirty(); + } + }); + + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ + +

SMTP Settings

+
+ + +

+ TrailBase try to use the local sendmail command if no SMTP + server is configured. This may be fine for development but will + likely result in your Emails getting classified as Spam. Please + add a valid SMTP server before going to production. There are + many specialized providers with generous free tiers such as{" "} + Brevo, ... +

+ + + {buildTextFormField({ label: () => Host })} + + + + {buildNumberFormField({ + integer: true, + label: () => Port, + })} + + + + {buildTextFormField({ label: () => Username })} + + + + {buildSecretFormField({ + label: () => Password, + })} + + + + + + +

Sender Settings

+
+ + + + {buildTextFormField({ + label: () => Sender Address, + type: "email", + })} + + + + {buildTextFormField({ label: () => Sender Name })} + + +
+ + + +

Email Templates

+
+ + + + + + Email Verification Template + + + + + + + + + Password Reset Template + + + + + + + +
+ +
+ ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + > + {(state) => { + return ( + + ); + }} + +
+
+
+ ); + }; + + const emailConfig = () => { + const c = config.data?.config?.email; + if (c) { + // "deep-copy" + return EmailConfig.decode(EmailConfig.encode(c).finish()); + } + // Fallback + return EmailConfig.create(); + }; + + return
; +} + +function L(props: { children: JSXElement }) { + return
{props.children}
; +} + +const flexColStyle = "flex flex-col gap-2"; diff --git a/ui/admin/src/components/settings/SchemaSettings.tsx b/ui/admin/src/components/settings/SchemaSettings.tsx new file mode 100644 index 0000000..337e298 --- /dev/null +++ b/ui/admin/src/components/settings/SchemaSettings.tsx @@ -0,0 +1,152 @@ +import { createResource, Suspense, Switch, Match, Index } from "solid-js"; +import { createForm } from "@tanstack/solid-form"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import { Card, CardContent, CardHeader } from "@/components/ui/card"; + +import { adminFetch } from "@/lib/fetch"; +import type { + UpdateJsonSchemaRequest, + ListJsonSchemasResponse, + JsonSchema, +} from "@/lib/bindings"; + +async function listSchemas(): Promise { + const response = await adminFetch("/schema", { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + return await response.json(); +} + +async function _updateSchema(request: UpdateJsonSchemaRequest): Promise { + await adminFetch("/schema", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); +} + +function SchemaSettingsForm(props: { + markDirty: () => void; + postSubmit: () => void; + schemas: JsonSchema[]; +}) { + const form = createForm(() => ({ + defaultValues: { + entries: props.schemas, + }, + onSubmit: async ({ value }) => { + throw `NOT IMPLEMENTED: ${value}`; + + props.postSubmit(); + }, + })); + + form.useStore((state) => { + if (state.isDirty && !state.isSubmitted) { + props.markDirty(); + } + }); + + return ( + { + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > + + {(field) => { + return ( + + + {(_, i) => { + const schema = field().state.value[i]; + return ( + + + {schema.name} {schema.builtin ? "" : null} + + + + + {(subField) => ( +
+                              {JSON.stringify(
+                                JSON.parse(subField().state.value),
+                                null,
+                                2,
+                              )}
+                            
+ )} +
+
+
+ ); + }} +
+
+ ); + }} +
+ + ); +} + +export function SchemaSettings(props: { + markDirty: () => void; + postSubmit: () => void; +}) { + const [schemas] = createResource(listSchemas); + return ( + Loading...}> + + + Error: {`${schemas.error}`} + + + + + +

Schemas

+
+ + +

+ Registering custom JSON schemas is not yet available in the UI. + However, you can register your own schemas in the{" "} + `config.textproto`. JSON schemas + can be used to enforce constraints on TEXT/JSON columns, e.g.: +

+ +
+                CREATE TABLE table (
+    json      TEXT + CHECK(jsonschema('mySchema', json)) +
+ ) strict; +
+
+ + +
+
+
+
+
+ ); +} diff --git a/ui/admin/src/components/settings/SettingsPage.tsx b/ui/admin/src/components/settings/SettingsPage.tsx new file mode 100644 index 0000000..ee6f665 --- /dev/null +++ b/ui/admin/src/components/settings/SettingsPage.tsx @@ -0,0 +1,463 @@ +import { createSignal, For, Show } from "solid-js"; +import type { Component, JSXElement } from "solid-js"; +import { Route, useNavigate, type RouteSectionProps } from "@solidjs/router"; +import { createForm } from "@tanstack/solid-form"; + +import { showToast } from "@/components/ui/toast"; +import { Button } from "@/components/ui/button"; +import { Dialog } from "@/components/ui/dialog"; +import { Separator } from "@/components/ui/separator"; +import { Card, CardContent, CardHeader } from "@/components/ui/card"; +import { Label } from "@/components/ui/label"; + +import { Config, ServerConfig } from "@proto/config"; +import { + notEmptyValidator, + buildNumberFormField, + buildTextFormField, +} from "@/components/FormFields"; +import { ConfirmCloseDialog } from "@/components/SafeSheet"; +import { AuthSettings } from "@/components/settings/AuthSettings"; +import { SchemaSettings } from "@/components/settings/SchemaSettings"; +import { EmailSettings } from "@/components/settings/EmailSettings"; +import { SplitView } from "@/components/SplitView"; + +import { createConfigQuery, setConfig } from "@/lib/config"; + +function ServerSettings(props: CommonProps) { + const config = createConfigQuery(); + + const Form = (p: { config: ServerConfig }) => { + const form = createForm(() => ({ + defaultValues: p.config, + onSubmit: async ({ value }: { value: ServerConfig }) => { + const c = config.data?.config; + if (!c) { + console.warn("Missing base config:"); + return; + } + + const newConfig = Config.fromPartial(c); + newConfig.server = value; + await setConfig(newConfig); + + props.postSubmit?.(); + }, + })); + + form.useStore((state) => { + if (state.isDirty && !state.isSubmitted) { + props.markDirty(); + } + }); + + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > + + +

Server Settings

+
+ + +
+ + {buildTextFormField({ + label: () =>
App Name
, + info: ( +

+ The name of your application. Used e.g. in emails sent to + users. +

+ ), + })} +
+
+ +
+ + {buildTextFormField({ + label: () =>
Site URL
, + info: ( +

+ The public address under which the server is reachable. + Used e.g. for auth, e.g. verification links sent via + Email. +

+ ), + })} +
+
+ +
+ + {buildNumberFormField({ + integer: true, + label: () => ( +
Log Retention (sec)
+ ), + info: ( +

+ A background ask periodically cleans up logs older than + above retention period. Setting the retention to zero turn + off the cleanup and logs will be retained indefinitely. +

+ ), + })} +
+
+
+
+ +
+ ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + > + {(state) => { + return ( + + ); + }} + +
+
+ ); + }; + + const serverConfig = () => { + const c = config.data?.config?.server; + if (c) { + // "deep-copy" + return ServerConfig.decode(ServerConfig.encode(c).finish()); + } + // Fallback + return ServerConfig.create(); + }; + + return ( +
+ Failed to fetch config + + Loading + + +
+ + + {import.meta.env.DEV && ( +
+ +
+ )} +
+ ); +} + +function BackupImportSettings(props: CommonProps) { + const config = createConfigQuery(); + + const Form = (p: { config: ServerConfig }) => { + const form = createForm(() => ({ + defaultValues: p.config, + onSubmit: async ({ value }: { value: ServerConfig }) => { + const c = config.data?.config; + if (!c) { + console.warn("Missing base config:"); + return; + } + + const newConfig = Config.fromPartial(c); + newConfig.server = value; + await setConfig(newConfig); + }, + })); + + form.useStore((state) => { + if (state.isDirty) { + props.markDirty(); + } + }); + + return ( + { + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ + +

Backup Settings

+
+ + + + {buildNumberFormField({ + integer: true, + label: () => ( +
+ +
+ ), + info: backupInfo, + })} +
+
+
+ + + +

Data Import {"&"} Export

+
+ + +

+ Data import and export from and to Sql via the UI is not yet + supported, however with TrailBase not relying on specific + metadata you can use all the usual suspects around sqlite and + the data will show up in the table editor. If you import your + data into a table with strict typing and an UUIDv7 primary + column you'll also be able to expose the data via restful APIs. +

+ +

Import, e.g.:

+
+                $ cat dump.sql | sqlite3 main.db
+              
+ +

Output, e.g.:

+ +
+                $ sqlite3 main.db
+                
+ sqlite> .output dump.db +
+ sqlite> .dump +
+
+
+
+ +
+ ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + > + {(state) => { + return ( + + ); + }} + +
+
+ + ); + }; + + const serverConfig = () => { + const c = config.data?.config?.server; + if (c) { + // "deep-copy" + return ServerConfig.decode(ServerConfig.encode(c).finish()); + } + // Fallback + return ServerConfig.create(); + }; + + return ( + <> + Failed to fetch config + + Loading + + +
+ + + ); +} + +function WrapSidebar( + base: string, + route: string, + site: Site, +): Component> { + const [dirty, setDirty] = createSignal(false); + + return (_props: RouteSectionProps) => { + function First(props: { horizontal: boolean }) { + const navigate = useNavigate(); + + const flexStyle = props.horizontal ? "flex flex-col" : "flex"; + + return ( +
+ + {([r, s]) => { + const [dialogOpen, setDialogOpen] = createSignal(false); + + return ( + + setDialogOpen(false)} + confirm={() => { + setDialogOpen(false); + navigate(base + r); + }} + /> + + + + ); + }} + +
+ ); + } + + function Second() { + return ( +
+

+ Settings + > + {site.label} +

+ + + +
+ setDirty(true)} + postSubmit={() => { + setDirty(false); + showToast({ + title: "submitted", + variant: "success", + }); + }} + /> +
+
+ ); + } + + return ; + }; +} + +interface CommonProps { + markDirty: () => void; + postSubmit: () => void; +} + +interface Site { + label: string; + child: Component; +} + +const sites: { [k: string]: Site } = { + "/": { + label: "Host", + child: ServerSettings, + }, + "/email": { + label: "E-mail", + child: EmailSettings, + }, + "/auth": { + label: "Auth", + child: AuthSettings, + }, + "/schema": { + label: "Schemas", + child: SchemaSettings, + }, + "/backup": { + label: "Backup", + child: BackupImportSettings, + }, +} as const; + +export function SettingsPages() { + return ( + <> + + {([route, site]) => ( + + )} + + + ); +} + +const backupInfo: JSXElement = ( +

+ Setting the backup interval to zero will disable periodic backups on next + server start. Backups will lock the database for the duration of the backup, + which is typically fine for small data sets. However, we recommend a more + continuous disaster recovery solution such as{" "} + Litestream to avoid locking and avoid + losing changes made between backups. +

+); + +const labelWidth = "w-40"; diff --git a/ui/admin/src/components/tables/CreateAlterIndex.tsx b/ui/admin/src/components/tables/CreateAlterIndex.tsx new file mode 100644 index 0000000..22b8731 --- /dev/null +++ b/ui/admin/src/components/tables/CreateAlterIndex.tsx @@ -0,0 +1,253 @@ +import { createSignal, Index } from "solid-js"; +import type { Accessor } from "solid-js"; +import { createForm } from "@tanstack/solid-form"; + +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader } from "@/components/ui/card"; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { SheetHeader, SheetTitle, SheetFooter } from "@/components/ui/sheet"; +import { showToast } from "@/components/ui/toast"; + +import { alterIndex, createIndex } from "@/lib/table"; +import type { ColumnOrder, Table, TableIndex } from "@/lib/bindings"; +import { + buildTextFormField, + buildBoolFormField, + buildSelectField, +} from "@/components/FormFields"; +import { SheetContainer } from "@/components/SafeSheet"; +import { randomName } from "@/lib/name"; + +export function CreateAlterIndexForm(props: { + close: () => void; + markDirty: () => void; + schemaRefetch: () => void; + table: Table; + schema?: TableIndex; +}) { + const [sql, setSql] = createSignal(); + + const original = props.schema + ? JSON.parse(JSON.stringify(props.schema)) + : undefined; + const newDefaultColumn = (index: number): ColumnOrder => { + return { + column_name: props.table.columns[index].name, + // Ascending is sqlite's default. + ascending: false, + // Sqlite doesn't support nulls_first, i.e. this parameter must be "null". + nulls_first: null, + }; + }; + + const onSubmit = async (value: TableIndex, dryRun: boolean) => { + console.debug("Index schema:", value); + + try { + if (original) { + const response = await alterIndex({ + source_schema: original, + target_schema: value, + }); + console.debug("AlterIndexResponse:", response); + } else { + const response = await createIndex({ schema: value, dry_run: dryRun }); + console.debug(`CreateIndexResponse [dry: ${dryRun}]:`, response); + + if (dryRun) { + setSql(response.sql); + } + } + + if (!dryRun) { + props.schemaRefetch(); + props.close(); + } + } catch (err) { + showToast({ + title: "Uncaught Error", + description: `${err}`, + variant: "error", + }); + } + }; + + const form = createForm(() => ({ + defaultValues: props.schema ?? { + name: `_${props.table.name}__${randomName()}_index`, + table_name: props.table.name, + columns: [newDefaultColumn(0)] as ColumnOrder[], + unique: false, + predicate: null, + }, + onSubmit: async ({ value }) => await onSubmit(value, false), + })); + + form.useStore((state) => { + if (state.isDirty && !state.isSubmitted) { + props.markDirty(); + } + }); + + return ( + + + + {original ? "Alter Index" : "Create New Index"} for " + {props.table.name}" Table + + + + { + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ { + return value ? undefined : "Table name missing"; + }, + }} + > + {buildTextFormField({ label: () => "Index name" })} + + + {/* columns */} + + {(field) => ( +
+
+ + {(_c: Accessor, i) => ( + + Index Column {i} + + +
+ + {buildSelectField( + [...props.table.columns.map((c) => c.name)], + { + label: () => ( +
Column Name
+ ), + }, + )} +
+ + + {buildBoolFormField({ + label: () =>
Ascending
, + })} +
+ + + {buildBoolFormField({ + label: () =>
Nulls first
, + })} +
+
+
+
+ )} +
+
+ + +
+ )} +
+
+ + + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + > + {(state) => { + return ( +
+ {original === undefined && ( + { + if (!open) { + setSql(undefined); + } + }} + > + +
+ +
+
+ + + + SQL + + +
+
{sql()}
+
+ + +
+
+ )} + +
+ +
+
+ ); + }} +
+
+ +
+ ); +} + +const labelWidth = "w-[112px]"; diff --git a/ui/admin/src/components/tables/CreateAlterTable.tsx b/ui/admin/src/components/tables/CreateAlterTable.tsx new file mode 100644 index 0000000..2fac6a4 --- /dev/null +++ b/ui/admin/src/components/tables/CreateAlterTable.tsx @@ -0,0 +1,876 @@ +import { createEffect, createSignal, Index, For } from "solid-js"; +import type { Accessor, JSX, JSXElement, Setter } from "solid-js"; +import { createForm } from "@tanstack/solid-form"; +import { Collapsible } from "@kobalte/core/collapsible"; +import { TbChevronDown, TbTrash, TbInfoCircle } from "solid-icons/tb"; + +import { showToast } from "@/components/ui/toast"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader } from "@/components/ui/card"; +import { Checkbox } from "@/components/ui/checkbox"; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + HoverCard, + HoverCardContent, + HoverCardTrigger, +} from "@/components/ui/hover-card"; +import { Label } from "@/components/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { SheetHeader, SheetTitle, SheetFooter } from "@/components/ui/sheet"; +import { + TextField, + TextFieldLabel, + TextFieldInput, +} from "@/components/ui/text-field"; + +import { + isNotNull, + setNotNull, + getCheckValue, + setCheckValue, + getDefaultValue, + setDefaultValue, + getUnique, + setUnique, + getForeignKey, + setForeignKey, +} from "@/lib/schema"; +import { createTable, alterTable } from "@/lib/table"; +import { cn } from "@/lib/utils"; +import { randomName } from "@/lib/name"; +import type { + Column, + ColumnDataType, + ColumnOption, + Table, +} from "@/lib/bindings"; +import { + buildBoolFormField, + gapStyle, + buildSelectField, + buildTextFormField, +} from "@/components/FormFields"; +import type { FormType, AnyFieldApi } from "@/components/FormFields"; +import { SheetContainer } from "@/components/SafeSheet"; + +export function CreateAlterTableForm(props: { + close: () => void; + markDirty: () => void; + schemaRefetch: () => Promise; + allTables: Table[]; + setSelected: (tableName: string) => void; + schema?: Table; +}) { + const [sql, setSql] = createSignal(); + + const original = props.schema + ? JSON.parse(JSON.stringify(props.schema)) + : undefined; + const newDefaultColumn = (index: number): Column => { + return { + name: `new_${index}`, + data_type: "Text", + options: [{ Default: "''" }], + }; + }; + + const onSubmit = async (value: Table, dryRun: boolean) => { + console.debug("Table schema:", value); + + try { + if (original) { + const response = await alterTable({ + source_schema: original, + target_schema: value, + }); + console.debug("AlterTableResponse:", response); + } else { + const response = await createTable({ schema: value, dry_run: dryRun }); + console.debug(`CreateTableResponse [dry: ${dryRun}]:`, response); + + if (dryRun) { + setSql(response.sql); + } + } + + if (!dryRun) { + props.schemaRefetch().then(() => { + props.setSelected(value.name); + }); + props.close(); + } + } catch (err) { + showToast({ + title: "Uncaught Error", + description: `${err}`, + variant: "error", + }); + } + }; + + const form = createForm(() => ({ + defaultValues: props.schema ?? { + name: randomName(), + strict: true, + indexes: [], + columns: [ + { + name: "id", + data_type: "Blob", + // Column constraints: https://www.sqlite.org/syntax/column-constraint.html + options: [ + { Unique: { is_primary: true } }, + { Check: "is_uuid_v7(id)" }, + { Default: "(uuid_v7())" }, + "NotNull", + ], + }, + newDefaultColumn(1), + ] satisfies Column[], + // Table constraints: https://www.sqlite.org/syntax/table-constraint.html + unique: [], + foreign_keys: [], + virtual_table: false, + temporary: false, + }, + onSubmit: async ({ value }) => await onSubmit(value, false), + })); + + form.useStore((state) => { + if (state.isDirty && !state.isSubmitted) { + props.markDirty(); + } + }); + + return ( + + + {original ? "Alter Table" : "Create New Table"} + + +
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ { + return value ? undefined : "Table name missing"; + }, + }} + > + {buildTextFormField({ label: () => Table name })} + + + "STRICT Typing" })} + /> + + {/* columns */} +

Columns

+ + + {(field) => ( +
+
+ + {(c: Accessor, i) => ( + + )} + +
+ + +
+ )} +
+
+ + + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + > + {(state) => { + return ( +
+ {original === undefined && ( + { + if (!open) { + setSql(undefined); + } + }} + > + + + + + + + SQL + + +
+
{sql()}
+
+ + +
+
+ )} + +
+ +
+
+ ); + }} +
+
+ +
+ ); +} + +function columnTypeField( + disabled: boolean, + fk: Accessor, + allTables: Table[], +) { + // WARNING: these needs to be kept in sync with ColumnDataType. TS cannot go + // from type union to array. + const columnDataTypes: ColumnDataType[] = [ + "Blob", + "Text", + "Integer", + "Real", + "Null", + ] as const; + + return (field: () => AnyFieldApi) => { + const [isDisabled, setDisabled] = createSignal(disabled); + + createEffect(() => { + const foreignKey = fk(); + if (foreignKey) { + for (const table of allTables) { + if (table.name == foreignKey) { + const type = table.columns[0].data_type; + console.debug(type, field().state.value); + if (field().state.value === type) { + break; + } + + field().setValue(type); + break; + } + } + } + + setDisabled(foreignKey !== undefined ? true : disabled); + }); + + return buildSelectField([...columnDataTypes], { + label: () => Type, + disabled: isDisabled, + })(field); + }; +} + +function ColumnOptionCheckField(props: { + column: Column; + value: ColumnOption[]; + onChange: (v: ColumnOption[]) => void; + disabled: boolean; +}) { + const disabled = () => + props.disabled || getCheckValue(props.value) === undefined; + + const HCard = () => ( + + } + variant="link" + > + + + + +
+
+

Column Constraint

+ +

+ Can be any boolean expression constant like{" "} + {`${props.column.name} < 42 `} + including SQL function calls like{" "} + + is_email({props.column.name}) + + . +

+
+
+
+
+ ); + + // TODO: Factor out inner component from buildTextFormField and use it here. + // return ( + // (Check)} + // initial={getCheckValue(props.value) ?? ""} + // handleChange={(value) => props.onChange(setCheckValue(props.value, value))} + // disabled={disabled()} + // /> + // ); + return ( + +
+ + + + Check + + + +
+ { + const value: string | undefined = ( + e.currentTarget as HTMLInputElement + ).value; + props.onChange(setCheckValue(props.value, value)); + }} + /> + + { + const newOpts = setCheckValue( + props.value, + value ? "" : undefined, + ); + props.onChange(newOpts); + }} + /> +
+
+
+ ); +} + +function ColumnOptionDefaultField(props: { + column: Column; + value: ColumnOption[]; + onChange: (v: ColumnOption[]) => void; + disabled: boolean; +}) { + const disabled = () => + props.disabled || getDefaultValue(props.value) === undefined; + + const HCard = () => ( + + } + variant="link" + > + + + + +
+
+

Column Default Value

+ +

+ Can either be a constant like{" "} + 'foo' + and 42, or a scalar + function like + + (jsonschema('std.FileUpload', {props.column.name})) + + . +

+
+
+
+
+ ); + + // TODO: Factor out inner component from buildTextFormField and use it here. + return ( + +
+ + + + Default + + + +
+ { + const value: string | undefined = ( + e.currentTarget as HTMLInputElement + ).value; + props.onChange(setDefaultValue(props.value, value)); + }} + /> + + { + // TODO: Make default dependent on column type. + const newOpts = setDefaultValue( + props.value, + value ? "''" : undefined, + ); + props.onChange(newOpts); + }} + /> +
+
+
+ ); +} + +function ColumnOptionFkSelect(props: { + value: ColumnOption[]; + onChange: (v: ColumnOption[]) => void; + allTables: Table[]; + disabled: boolean; + setFk: Setter; +}) { + const fkTableOptions: string[] = [ + "None", + ...props.allTables.map((schema) => schema.name), + ]; + const fkValue = (): string => + getForeignKey(props.value)?.foreign_table ?? "None"; + + return ( +
+ + + +
+ ); +} + +function ColumnOptionsFields(props: { + column: Column; + value: ColumnOption[]; + onChange: (v: ColumnOption[]) => void; + allTables: Table[]; + disabled: boolean; + setFk: Setter; +}) { + // Column options: (not|null), (default), (unique), (fk), (check), (comment), (onupdate). + + return ( + <> + + + + + + +
+
+ + +
+ + props.onChange(setNotNull(props.value, value)) + } + /> +
+
+ +
+ + +
+ { + props.onChange( + setUnique( + props.value, + value ? { is_primary: false } : undefined, + ), + ); + }} + /> +
+
+
+ + ); +} + +function ColumnSubForm(props: { + form: FormType
; + colIndex: number; + column: Column; + allTables: Table[]; + disabled: boolean; +}): JSX.Element { + const disabled = props.disabled; + const [name, setName] = createSignal(props.column.name); + const [expanded, setExpanded] = createSignal(props.column.name !== "id"); + + const [fk, setFk] = createSignal(); + + const Header = () => ( +
+

{name()}

+ +
+ {!disabled && ( +
+ +
+ )} + +
+
+ ); + + return ( + + + + +
+ + + + + +
+ {/* Column presets */} +
+ + +
+ + {([name, preset]) => ( + { + const columns = [...props.form.state.values.columns]; + const column = columns[props.colIndex]; + + const v = preset(column.name); + + column.data_type = v.data_type; + column.options = v.options; + + props.form.setFieldValue("columns", columns); + }} + > + {name} + + )} + +
+
+ + {/* Column name field */} + { + return value ? undefined : "Column name missing"; + }, + }} + > + {buildTextFormField({ + label: () => Name, + disabled, + onKeyUp: setName, + })} + + + {/* Column type field */} + + + {/* Column options: pk, not null, ... */} + { + return ( + + ); + }} + /> +
+
+
+ + + ); +} + +function L(props: { children: JSXElement }) { + return
{props.children}
; +} + +const transitionTimingFunc = "cubic-bezier(.87,0,.13,1)"; + +type Preset = { + data_type: ColumnDataType; + options: ColumnOption[]; +}; + +const presets: [string, (colName: string) => Preset][] = [ + [ + "Default", + (_colName: string) => { + return { + data_type: "Text", + options: [{ Default: "''" }, "NotNull"], + }; + }, + ], + [ + "UUIDv7", + (colName: string) => { + return { + data_type: "Blob", + options: [ + { Check: `is_uuid_v7(${colName})` }, + { Default: "(uuid_v7())" }, + "NotNull", + ], + }; + }, + ], + [ + "JSON", + (colName: string) => { + return { + data_type: "Text", + options: [ + { Check: `is_json(${colName})` }, + { Default: "{}" }, + "NotNull", + ], + }; + }, + ], + [ + "File", + (colName: string) => { + return { + data_type: "Text", + options: [ + { + Check: `jsonschema('std.FileUpload', ${colName})`, + }, + ], + }; + }, + ], + [ + "Files", + (colName: string) => { + return { + data_type: "Text", + options: [ + { + Check: `jsonschema('std.FileUploads', ${colName})`, + }, + { Default: "[]" }, + "NotNull", + ], + }; + }, + ], +]; diff --git a/ui/admin/src/components/tables/InsertAlterRow.tsx b/ui/admin/src/components/tables/InsertAlterRow.tsx new file mode 100644 index 0000000..27a21e2 --- /dev/null +++ b/ui/admin/src/components/tables/InsertAlterRow.tsx @@ -0,0 +1,221 @@ +import { For } from "solid-js"; +import { createForm } from "@tanstack/solid-form"; + +import { SheetHeader, SheetTitle, SheetFooter } from "@/components/ui/sheet"; +import { Button } from "@/components/ui/button"; + +import type { Column, Table, UpdateRowRequest } from "@/lib/bindings"; +import { formFieldBuilder } from "@/components/FormFields"; +import { + findPrimaryKeyColumnIndex, + getDefaultValue, + isNotNull, + isOptional, +} from "@/lib/schema"; +import { adminFetch } from "@/lib/fetch"; +import { SheetContainer } from "@/components/SafeSheet"; +import { showToast } from "@/components/ui/toast"; + +// NOTE: We use `unknown` here over `Object` to prevent forms from doing infinite-recursion type gymnastics. +type Row = { [key: string]: unknown }; + +export function copyAndConvert(row: Row): { + // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types + [key: string]: Object | undefined; +} { + return Object.fromEntries( + // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types + Object.entries(row).map(([k, v]) => [k, v as Object | undefined]), + ); +} + +async function insertRow(tableName: string, row: Row) { + const response = await adminFetch(`/table/${tableName}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(row), + }); + + return await response.text(); +} + +async function updateRow(table: Table, row: Row) { + const tableName = table.name; + const primaryKeyColumIndex = findPrimaryKeyColumnIndex(table.columns); + if (primaryKeyColumIndex < 0) { + throw Error("No primary key column found."); + } + const pkColName = table.columns[primaryKeyColumIndex].name; + + const pkValue = row[pkColName]; + if (pkValue === undefined) { + throw Error("Row is missing primary key."); + } + const copy = { + ...row, + }; + copy[pkColName] = undefined; + + const request: UpdateRowRequest = { + primary_key_column: pkColName, + // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types + primary_key_value: pkValue as Object, + row: copyAndConvert(copy), + }; + + const response = await adminFetch(`/table/${tableName}`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); + + return await response.text(); +} + +function buildDefault(schema: Table): Row { + const obj: Row = {}; + for (const col of schema.columns) { + const optional = isOptional(col.options); + if (optional) { + // obj[col.name] = undefined; + continue; + } + + switch (col.data_type) { + case "Blob": + obj[col.name] = []; + break; + case "Text": + obj[col.name] = ""; + break; + case "Real": + obj[col.name] = 0.0; + break; + case "Integer": + obj[col.name] = 0; + break; + case "Null": + break; + } + } + return obj; +} + +export function InsertAlterRowForm(props: { + close: () => void; + markDirty: () => void; + rowsRefetch: () => void; + schema: Table; + row?: Row; +}) { + const original = props.row + ? JSON.parse(JSON.stringify(props.row)) + : undefined; + + const form = createForm(() => ({ + defaultValues: props.row ?? buildDefault(props.schema), + onSubmit: async ({ value }) => { + console.debug("Submitting:", value); + try { + if (original) { + const response = await updateRow(props.schema, value); + console.debug("UpdateRowResponse:", response); + } else { + const response = await insertRow(props.schema.name, value); + console.debug("InsertRowResponse:", response); + } + + props.rowsRefetch(); + props.close(); + } catch (err) { + showToast({ + title: "Uncaught Error", + description: `${err}`, + variant: "error", + }); + } + }, + })); + + form.useStore((state) => { + if (state.isDirty && !state.isSubmitted) { + props.markDirty(); + } + }); + + return ( + + + {original ? "Edit Row" : "Insert New Row"} + + +
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ + {(col: Column) => { + const notNull = isNotNull(col.options); + const label = `${col.name} [${col.data_type}${notNull ? "" : "?"}]`; + const optional = isOptional(col.options); + const defaultValue = getDefaultValue(col.options); + + return ( + { + const defaultValue = getDefaultValue(col.options); + if (defaultValue !== undefined) { + return undefined; + } + return value !== undefined ? undefined : "Missing value"; + }, + }} + children={formFieldBuilder( + col.data_type, + label, + optional, + defaultValue, + )} + /> + ); + }} + +
+ + + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + children={(state) => { + return ( + + ); + }} + /> + + +
+ ); +} diff --git a/ui/admin/src/components/tables/RecordApiSettings.tsx b/ui/admin/src/components/tables/RecordApiSettings.tsx new file mode 100644 index 0000000..411cb4c --- /dev/null +++ b/ui/admin/src/components/tables/RecordApiSettings.tsx @@ -0,0 +1,545 @@ +import { For, createSignal } from "solid-js"; +import { createForm } from "@tanstack/solid-form"; +import { TbInfoCircle } from "solid-icons/tb"; + +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardTitle, CardHeader } from "@/components/ui/card"; +import { Checkbox } from "@/components/ui/checkbox"; +import { Label } from "@/components/ui/label"; +import { + HoverCard, + HoverCardContent, + HoverCardTrigger, +} from "@/components/ui/hover-card"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { SheetFooter } from "@/components/ui/sheet"; +import { showToast } from "@/components/ui/toast"; + +import { + Config, + ConflictResolutionStrategy, + PermissionFlag, + RecordApiConfig, +} from "@proto/config"; +import { SheetContainer } from "@/components/SafeSheet"; +import type { Table, View } from "@/lib/bindings"; +import { + buildTextFormField, + buildOptionalTextFormField, +} from "@/components/FormFields"; +import { createConfigQuery, setConfig } from "@/lib/config"; +import { parseSql } from "@/lib/parse"; +import { tableType } from "@/lib/schema"; + +const tablePermissions = { + Create: PermissionFlag.CREATE, + Read: PermissionFlag.READ, + Update: PermissionFlag.UPDATE, + Delete: PermissionFlag.DELETE, + Schema: PermissionFlag.SCHEMA, +} as const; + +const viewPermissions = { + Read: PermissionFlag.READ, + Schema: PermissionFlag.SCHEMA, +} as const; + +function AclForm(props: { + entity: string; + initial?: PermissionFlag[]; + showHeader: boolean; + onChange: (v: PermissionFlag[]) => void; + view: boolean; +}) { + const [acl, setAcl] = createSignal(new Set(props.initial ?? [])); + + return ( +
+
+ {props.showHeader && ( + + {(key, index) => ( +
+ {key} +
+ )} +
+ )} + +
+ +
+ + + {(perm) => ( +
+ { + const set = acl(); + if (v) { + set.add(perm); + } else { + set.delete(perm); + } + + setAcl(new Set(set)); + props.onChange([...set]); + }} + /> +
+ )} +
+
+
+ ); +} + +type Field = keyof RecordApiConfig; +interface AccessRule { + field: Field; + label: string; + description: string; +} + +const tableAccessRules: AccessRule[] = [ + { + field: "readAccessRule", + label: "Read access:", + description: + 'Row- and request-level read access (_user_, _row_, _req_): If the table has an "owner"\'s column containing binary user ids, access could be rstricted to the owner by setting \'_row_.owner = _user_\' here. Or if the table as a foreign key to a "group" and a relationship defined in a "membership" table: \'(SELECT 1 FROM membership WHERE group = _row_.group AND user = _user_)\'', + }, + { + field: "createAccessRule", + label: "Create access:", + description: + "Request-level create access validation base on _USER_, _REQ_:", + }, + { + field: "updateAccessRule", + label: "Update access", + description: + "Row- and request level update access based on _USER_, _ROW_, _REQ_:", + }, + { + field: "deleteAccessRule", + label: "Delete Access", + description: + "Row- and request level delete access based on _USRE_, _ROW_, _REQ_:", + }, + { + field: "schemaAccessRule", + label: "Schema Access", + description: "Schema access based on _USER_:", + }, +] as const; + +const viewAccessRules: AccessRule[] = [ + { + field: "readAccessRule", + label: "Read access:", + description: + 'Row- and request-level read access (_user_, _row_, _req_): If the table has an "owner"\'s column containing binary user ids, access could be rstricted to the owner by setting \'_row_.owner = _user_\' here. Or if the table as a foreign key to a "group" and a relationship defined in a "membership" table: \'(SELECT 1 FROM membership WHERE group = _row_.group AND user = _user_)\'', + }, + { + field: "schemaAccessRule", + label: "Schema Access", + description: "Schema access based on _USER_:", + }, +] as const; + +function updateRecordApiConfig( + config: Config, + recordApiConfig: RecordApiConfig, +): Config { + const newConfig = Config.fromPartial(config); + + for (const i in newConfig.recordApis) { + const api = newConfig.recordApis[i]; + if (api.name == recordApiConfig.name) { + newConfig.recordApis[i] = recordApiConfig; + return newConfig; + } + } + + newConfig.recordApis.push(recordApiConfig); + return newConfig; +} + +function removeRecordApiConfig(config: Config, tableName: string): Config { + const newConfig = Config.fromPartial(config); + + while (true) { + const index = newConfig.recordApis.findIndex( + (api) => api.tableName === tableName, + ); + if (index < 0) { + break; + } + + newConfig.recordApis.splice(index, 1); + } + + return newConfig; +} + +function ConflictResolutionSrategyToString( + value: ConflictResolutionStrategy | null, +): string { + switch (value) { + case ConflictResolutionStrategy.ABORT: + return "Abort"; + case ConflictResolutionStrategy.ROLLBACK: + return "Rollback"; + case ConflictResolutionStrategy.FAIL: + return "Fail"; + case ConflictResolutionStrategy.IGNORE: + return "Ignore"; + case ConflictResolutionStrategy.REPLACE: + return "Replace"; + default: + return "Undefined"; + } +} + +function findRecordApi( + config: Config | undefined, + tableName: string, +): RecordApiConfig | undefined { + if (!config) { + return undefined; + } + + for (const api of config.recordApis) { + if (api.tableName == tableName) { + return api; + } + } + + return undefined; +} + +export function RecordApiSettingsForm(props: { + close: () => void; + markDirty: () => void; + schema: Table | View; +}) { + const config = createConfigQuery(); + + const type = () => tableType(props.schema); + + // FIXME: We don't currently handle the "multiple APIs for a single table" case. + const currentApi = () => + findRecordApi(config.data!.config!, props.schema.name); + + const form = createForm(() => { + const tableName = props.schema.name; + return { + defaultValues: currentApi() ?? { + name: tableName, + tableName: tableName, + aclWorld: [], + aclAuthenticated: [], + }, + onSubmit: async ({ value }: { value: RecordApiConfig }) => { + console.debug("Add record api config:", value); + + const c = config.data?.config; + if (!c) { + console.error("missing base configuration"); + return; + } + + const newConfig = updateRecordApiConfig(c, value); + try { + await setConfig(newConfig); + props.close(); + } catch (err) { + showToast({ + title: "Uncaught Error", + description: `${err}`, + variant: "error", + }); + } + }, + }; + }); + + form.useStore((state) => { + if (state.isDirty && !state.isSubmitted) { + props.markDirty(); + } + }); + + return ( + +
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ + + Record API Settings + + + + { + return value ? undefined : "Api name missing"; + }, + }} + > + {buildTextFormField({ + label: () =>
API name
, + })} +
+ + {type() === "table" && ( + <> + + {(field) => ( +
+ + + + multiple={false} + placeholder="Select group..." + defaultValue={field().state.value} + options={[ + ConflictResolutionStrategy.ABORT, + ConflictResolutionStrategy.ROLLBACK, + ConflictResolutionStrategy.FAIL, + ConflictResolutionStrategy.IGNORE, + ConflictResolutionStrategy.REPLACE, + ]} + optionValue={ConflictResolutionSrategyToString} + onChange={( + strategy: ConflictResolutionStrategy | null, + ) => { + field().handleChange(strategy ?? undefined); + }} + itemComponent={(props) => ( + + {ConflictResolutionSrategyToString( + props.item.rawValue, + )} + + )} + > + + > + {(state) => + ConflictResolutionSrategyToString( + state.selectedOption(), + ) + } + + + + + +
+ )} +
+ + { + const HCard = () => ( + + } + variant="link" + > + + + + +
+
+

+ User Id Auto-Fill +

+ +

+ When enabled, user id columns that are not + provided as part of a CREATE request will be + auto-filled with the id of the calling user + when authenticated. +

+ +

+ For most use-cases this setting should stay + turned-off and user ids should be provided + explicitly by the client. This setting can be + useful in case the client cannot run any logic + like JS-less HTML forms. +

+
+
+
+
+ ); + // TODO: Should be buildBoolFormField? + const v = () => field().state.value; + return ( +
+ + + + + field().handleChange(v)} + /> +
+ ); + }} + /> + + )} +
+
+ + + + Access + + + + + {(field) => { + const v = field().state.value; + return ( +
+ +
+ ); + }} +
+ + + {(field) => { + const v = field().state.value; + return ( +
+ +
+ ); + }} +
+ + + {(item) => { + async function onChangeAsync(props: { + value: string | undefined; + }) { + const value = props.value; + if (value) { + console.debug("Query", value); + return parseSql(value); + } + } + + return ( + + {buildOptionalTextFormField({ + label: () =>
{item.label}
, + })} +
+ ); + }} +
+
+
+
+ + + + + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + > + {(state) => ( + + )} + + + +
+ ); +} + +const labelWidth = "w-[112px]"; diff --git a/ui/admin/src/components/tables/TablesPage.tsx b/ui/admin/src/components/tables/TablesPage.tsx new file mode 100644 index 0000000..d82cf85 --- /dev/null +++ b/ui/admin/src/components/tables/TablesPage.tsx @@ -0,0 +1,1326 @@ +import { + type Signal, + type ResourceFetcherInfo, + For, + Match, + Show, + Switch, + createMemo, + createEffect, + createResource, + createSignal, +} from "solid-js"; +import { createStore, type Store, type SetStoreFunction } from "solid-js/store"; +import { useSearchParams } from "@solidjs/router"; +import { persistentAtom } from "@nanostores/persistent"; +import { useStore } from "@nanostores/solid"; +import type { + ColumnDef, + PaginationState, + CellContext, +} from "@tanstack/solid-table"; +import { createColumnHelper } from "@tanstack/solid-table"; +import type { DialogTriggerProps } from "@kobalte/core/dialog"; +import { asyncBase64Encode } from "trailbase"; + +import { Button } from "@/components/ui/button"; +import { Checkbox } from "@/components/ui/checkbox"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Separator } from "@/components/ui/separator"; +import { SheetContent, SheetTrigger } from "@/components/ui/sheet"; +import { + Switch as SwitchUi, + SwitchControl, + SwitchLabel, + SwitchThumb, +} from "@/components/ui/switch"; +import { + TbColumns, + TbDownload, + TbRefresh, + TbTable, + TbTrash, + TbLock, + TbEye, + TbWand, +} from "solid-icons/tb"; + +import { CreateAlterTableForm } from "@/components/tables/CreateAlterTable"; +import { CreateAlterIndexForm } from "@/components/tables/CreateAlterIndex"; +import { + DataTable, + defaultPaginationState, + safeParseInt, +} from "@/components/Table"; +import { FilterBar } from "@/components/FilterBar"; +import { DestructiveActionButton } from "@/components/DestructiveActionButton"; +import { InsertAlterRowForm } from "@/components/tables/InsertAlterRow"; +import { RecordApiSettingsForm } from "@/components/tables/RecordApiSettings"; +import { SplitView } from "@/components/SplitView"; +import { SafeSheet } from "@/components/SafeSheet"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; + +import { createConfigQuery } from "@/lib/config"; +import { adminFetch } from "@/lib/fetch"; +import { urlSafeBase64ToUuid, showSaveFileDialog } from "@/lib/utils"; +import { RecordApiConfig } from "@proto/config"; +import { getAllTableSchemas, dropTable, dropIndex } from "@/lib/table"; + +import type { + Column, + DeleteRowsRequest, + FileUpload, + FileUploads, + ListRowsResponse, + ListSchemasResponse, + Table, + TableIndex, + TableTrigger, + View, +} from "@/lib/bindings"; +import { + findPrimaryKeyColumnIndex, + isFileUploadColumn, + isFileUploadsColumn, + isJSONColumn, + isNotNull, + isUUIDv7Column, + hiddenTable, + tableType, + type TableType, + tableSatisfiesRecordApiRequirements, + viewSatisfiesRecordApiRequirements, +} from "@/lib/schema"; + +// We deliberately want to use `Object` over `object` which includes primitive types such as string. +// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types +type RowData = (Object | undefined)[]; +// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types +type Row = { [key: string]: Object | undefined }; + +function rowDataToRow(columns: Column[], row: RowData): Row { + const result: Row = {}; + for (let i = 0; i < row.length; ++i) { + result[columns[i].name] = row[i]; + } + return result; +} + +function renderCell( + context: CellContext, + tableName: string, + columns: Column[], + pkIndex: number, + cell: { + col: Column; + isUUIDv7: boolean; + isJSON: boolean; + isFile: boolean; + isFiles: boolean; + }, +): unknown { + const value = context.getValue(); + if (value === null) { + return "NULL"; + } + + if (typeof value === "string") { + if (cell.isUUIDv7) { + return urlSafeBase64ToUuid(value); + } + + const imageMime = (f: FileUpload) => { + const mime = f.mime_type; + return mime === "image/jpeg" || mime === "image/png"; + }; + + if (cell.isFile) { + const fileUpload = JSON.parse(value) as FileUpload; + if (imageMime(fileUpload)) { + const pkCol = columns[pkIndex].name; + const pkVal = context.row.original[pkIndex] as string; + const url = imageUrl({ + tableName, + pkCol, + pkVal, + fileColName: cell.col.name, + }); + + return ; + } + } else if (cell.isFiles) { + const fileUploads = JSON.parse(value) as FileUploads; + + const indexes: number[] = []; + for (let i = 0; i < fileUploads.length; ++i) { + const file = fileUploads[i]; + if (imageMime(file)) { + indexes.push(i); + } + + if (indexes.length >= 3) break; + } + + if (indexes.length > 0) { + const pkCol = columns[pkIndex].name; + const pkVal = context.row.original[pkIndex] as string; + return ( +
+ + {(index: number) => { + const fileUpload = fileUploads[index]; + const url = imageUrl({ + tableName, + pkCol, + pkVal, + fileColName: cell.col.name, + index, + }); + + return ; + }} + +
+ ); + } + } + } + + return value; +} + +async function deleteRows(tableName: string, request: DeleteRowsRequest) { + const response = await adminFetch(`/table/${tableName}/rows`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); + return await response.text(); +} + +function Image(props: { url: string; mime: string }) { + const [imageData] = createResource(async () => { + const response = await adminFetch(props.url); + return await asyncBase64Encode(await response.blob()); + }); + + return ( + + {imageData.error} + + Loading + + + + + + ); +} + +function imageUrl(opts: { + tableName: string; + pkCol: string; + pkVal: string; + fileColName: string; + index?: number; +}): string { + const uri = `/table/${opts.tableName}/files?pk_column=${opts.pkCol}&pk_value=${opts.pkVal}&file_column_name=${opts.fileColName}`; + const index = opts.index; + if (index) { + return `${uri}&file_index=${index}`; + } + return uri; +} + +function SchemaDialogButton(props: { + table: Table; + indexes: TableIndex[]; + triggers: TableTrigger[]; +}) { + const columns = () => props.table.columns; + const indexes = () => props.indexes; + const triggers = () => props.triggers; + const fks = () => props.table.foreign_keys; + + return ( +
+ + + + + + + + Schema + + +
+
+

Columns

+
+                {JSON.stringify(columns(), null, 2)}
+              
+ +

Foreign Keys

+
+                {JSON.stringify(fks(), null, 2)}
+              
+ +

Indexes

+
+                {JSON.stringify(indexes(), null, 2)}
+              
+ +

Triggers

+
+                {JSON.stringify(triggers(), null, 2)}
+              
+
+
+
+
+
+ ); +} + +function TableHeaderRightHandButtons(props: { + table: Table | View; + allTables: Table[]; + schemaRefetch: () => Promise; +}) { + const table = () => props.table; + const hidden = () => hiddenTable(table()); + const type = () => tableType(table()); + + const satisfiesRecordApi = createMemo(() => { + const t = type(); + if (t === "table") { + return tableSatisfiesRecordApiRequirements( + props.table as Table, + props.allTables, + ); + } else if (t === "view") { + return viewSatisfiesRecordApiRequirements( + props.table as View, + props.allTables, + ); + } + + return false; + }); + + const config = createConfigQuery(); + const recordApi = (): RecordApiConfig | undefined => { + for (const c of config.data?.config?.recordApis ?? []) { + if (c.tableName === table().name) { + return c; + } + } + }; + + return ( +
+ {/* Delete table button */} + {!hidden() && ( + { + await dropTable({ + name: table().name, + }); + props.schemaRefetch(); + }} + msg="Deleting a table will irreversibly delete all the data contained. Are you sure you'd like to continue?" + > +
+ Delete +
+
+ )} + + {/* Record API settings*/} + {(type() === "table" || type() === "view") && !hidden() && ( + { + return ( + <> + + + + + ( + + + + + + + {satisfiesRecordApi() ? ( +

Create a Record API endpoint for this table.

+ ) : ( +

+ This table does not satisfy the requirements for + exposing a Record API: strictly typed {"&"} UUIDv7 + primary key column. +

+ )} +
+
+ )} + /> + + ); + }} + /> + )} + + {type() === "table" && !hidden() && ( + { + return ( + <> + + { + /* No selection change needed for AlterTable */ + }} + schema={props.table as Table} + {...sheet} + /> + + + ( + + )} + /> + + ); + }} + /> + )} +
+ ); +} + +function TableHeader(props: { + table: Table | View; + indexes: TableIndex[]; + triggers: TableTrigger[]; + allTables: Table[]; + schemaRefetch: () => Promise; + rowsRefetch: () => Promise; +}) { + const table = () => props.table; + const name = () => props.table.name; + + const type = () => tableType(table()); + const hasSchema = () => type() === "table"; + const header = () => { + switch (type()) { + case "view": + return "View"; + case "virtualTable": + return "Virtual Table"; + default: + return "Table"; + } + }; + + return ( +
+ + +
+ +
+
+ ); +} + +type TableStore = { + selected: Table | View; + schemas: ListSchemasResponse; + + // Filter & pagination + filter: string | undefined; + pagination: PaginationState; +}; + +type FetchArgs = { + tableName: string; + filter: string | undefined; + pageSize: number; + pageIndex: number; + cursors: string[]; +}; + +type TableState = { + store: Store; + setStore: SetStoreFunction; + + response: ListRowsResponse; + + // Derived + pkColumnIndex: number; + columnDefs: ColumnDef[]; +}; + +async function buildTableState( + source: FetchArgs, + store: Store, + setStore: SetStoreFunction, + info: ResourceFetcherInfo, +): Promise { + const response = await fetchRows(source, { value: info.value?.response }); + + const pkColumnIndex = findPrimaryKeyColumnIndex(response.columns); + const columnDefs = buildColumnDefs( + store.selected.name, + tableType(store.selected), + pkColumnIndex, + response.columns, + ); + + return { + store, + setStore, + response, + pkColumnIndex, + columnDefs, + }; +} + +function buildColumnDefs( + tableName: string, + tableType: TableType, + pkColumn: number, + columns: Column[], +): ColumnDef[] { + return columns.map((col, idx) => { + const notNull = isNotNull(col.options); + const isJSON = isJSONColumn(col); + const isUUIDv7 = isUUIDv7Column(col); + const isFile = isFileUploadColumn(col); + const isFiles = isFileUploadsColumn(col); + + // TODO: Add support for custom json schemas or generally JSON types. + const type = (() => { + if (isUUIDv7) return "UUIDv7"; + if (isJSON) return "JSON"; + if (isFile) return "File"; + if (isFiles) return "File[]"; + return col.data_type; + })(); + + return { + header: `${col.name} [${type}${notNull ? "" : "?"}]`, + cell: (context) => + renderCell(context, tableName, columns, pkColumn, { + col: col, + isUUIDv7, + isJSON, + // FIXME: Whether or not an image can be rendered depends on whether + // Record API read-access is configured and not the tableType. We + // could also consider to decouple by providing a dedicated admin + // file-access endpoint. + isFile: isFile && tableType !== "view", + isFiles: isFiles && tableType !== "view", + }), + accessorFn: (row: RowData) => row[idx], + }; + }); +} + +async function fetchRows( + source: FetchArgs, + { value }: { value: ListRowsResponse | undefined }, +): Promise { + const pageIndex = source.pageIndex; + const limit = source.pageSize; + const cursors = source.cursors; + + const filter = source.filter ?? ""; + const filterQuery = filter + .split("AND") + .map((frag) => frag.trim().replaceAll(" ", "")) + .join("&"); + + const params = new URLSearchParams(filterQuery); + params.set("limit", limit.toString()); + + // Build the next UUIDv7 "cursor" from previous response and update local + // cursor stack. If we're paging forward we add new cursors, otherwise we're + // re-using previously seen cursors for consistency. We reset if we go back + // to the start. + if (pageIndex === 0) { + cursors.length = 0; + } else { + const index = pageIndex - 1; + if (index < cursors.length) { + // Already known page + params.set("cursor", cursors[index]); + } else { + // New page case: use cursor from previous response or fall back to more + // expensive and inconsistent offset-based pagination. + const cursor = value?.cursor; + if (cursor) { + cursors.push(cursor); + params.set("cursor", cursor); + } else { + params.set("offset", `${pageIndex * source.pageSize}`); + } + } + } + + try { + const response = await adminFetch( + `/table/${source.tableName}/rows?${params}`, + ); + return (await response.json()) as ListRowsResponse; + } catch (err) { + if (value) { + return value; + } + throw err; + } +} + +function RowDataTable(props: { + state: TableState; + rowsRefetch: () => Promise; +}) { + const [editRow, setEditRow] = createSignal(); + const [selectedRows, setSelectedRows] = createSignal(new Set()); + + const table = () => props.state.store.selected; + const mutable = () => tableType(table()) === "table" && !hiddenTable(table()); + + const refetch = async () => await props.rowsRefetch(); + const columns = (): Column[] => props.state.response.columns; + const totalRowCount = () => Number(props.state.response.total_row_count); + const pkColumnIndex = () => props.state.pkColumnIndex; + + return ( + <> + editRow() !== undefined, + (isOpen: boolean | ((value: boolean) => boolean)) => { + if (!isOpen) { + setEditRow(undefined); + } + }, + ]} + children={(sheet) => { + return ( + <> + + + + + { + if (value === props.state.store.filter) { + refetch(); + } else { + props.state.setStore("filter", (_prev) => value); + } + }} + example='e.g. "latency[lt]=2 AND status=200"' + /> + +
+ props.state.columnDefs} + data={() => props.state.response.rows} + rowCount={totalRowCount()} + initialPagination={props.state.store.pagination} + onPaginationChange={( + p: + | PaginationState + | ((old: PaginationState) => PaginationState), + ) => { + props.state.setStore("pagination", p); + }} + onRowClick={ + mutable() + ? (_idx: number, row: RowData) => { + setEditRow(rowDataToRow(columns(), row)); + } + : undefined + } + onRowSelection={ + mutable() + ? (_idx: number, row: RowData, value: boolean) => { + const rows = new Set(selectedRows()); + const rowId = row[pkColumnIndex()] as string; + if (value) { + rows.add(rowId); + } else { + rows.delete(rowId); + } + setSelectedRows(rows); + } + : undefined + } + /> +
+ + ); + }} + /> + + {mutable() && ( +
+ {/* Insert Rows */} + { + return ( + <> + + + + + ( + + )} + /> + + ); + }} + /> + + {/* Delete rows */} + +
+ )} + + ); +} + +function TablePane(props: { + selectedTable: Table | View; + schemas: ListSchemasResponse; + schemaRefetch: () => Promise; +}) { + const [editIndex, setEditIndex] = createSignal(); + const [selectedIndexes, setSelectedIndexes] = createSignal(new Set()); + + const table = () => props.selectedTable; + const indexes = () => + props.schemas.indexes.filter((idx) => idx.table_name === table().name); + const triggers = () => + props.schemas.triggers.filter((trig) => trig.table_name === table().name); + + // Derived table() props. + const type = () => tableType(table()); + const hidden = () => hiddenTable(table()); + + const [searchParams, setSearchParams] = useSearchParams<{ + filter?: string; + pageSize?: string; + }>(); + + function newStore(): TableStore { + return { + selected: props.selectedTable, + schemas: props.schemas, + filter: searchParams.filter ?? "", + pagination: defaultPaginationState({ + // NOTE: We index has to start at 0 since we're building the list of + // stable cursors as we incrementally page. + index: 0, + size: safeParseInt(searchParams.pageSize) ?? 20, + }), + }; + } + + // Cursors are deliberately kept out of the store to avoid tracking. + let cursors: string[] = []; + const [store, setStore] = createStore(newStore()); + createEffect(() => { + if (store.selected.name !== props.selectedTable.name) { + // Recreate the state/store when we switch tables. + cursors = []; + setStore(newStore()); + } + + setSearchParams({ + filter: store.filter, + }); + }); + + const buildFetchArgs = (): FetchArgs => ({ + // We need to access store properties here to react to them changing. It's + // fine grained, so accessing a nested object like store.pagination isn't + // enough. + tableName: store.selected.name, + filter: store.filter, + pageSize: store.pagination.pageSize, + pageIndex: store.pagination.pageIndex, + cursors: cursors, + }); + const [state, { refetch: rowsRefetch }] = createResource( + buildFetchArgs, + async (source: FetchArgs, info: ResourceFetcherInfo) => { + try { + return await buildTableState(source, store, setStore, info); + } catch (err) { + setSearchParams({ + filter: undefined, + pageIndex: undefined, + pageSize: undefined, + }); + + throw err; + } + }, + ); + + return ( + <> + { + await rowsRefetch(); + }} + /> + + + +
+ Loading...}> + +
+ Failed to fetch rows: {`${state.error}`} +
+ +
+
+
+ + + { + await rowsRefetch(); + }} + /> + +
+ + {type() === "table" && ( +
+

Indexes

+ + editIndex() !== undefined, + (isOpen: boolean | ((value: boolean) => boolean)) => { + if (!isOpen) { + setEditIndex(undefined); + } + }, + ]} + children={(sheet) => { + return ( + <> + + + + +
+ indexColumns} + data={indexes} + onRowClick={ + hidden() + ? undefined + : (_idx: number, index: TableIndex) => { + setEditIndex(index); + } + } + onRowSelection={ + hidden() + ? undefined + : ( + _idx: number, + index: TableIndex, + value: boolean, + ) => { + const rows = new Set(selectedIndexes()); + if (value) { + rows.add(index.name); + } else { + rows.delete(index.name); + } + setSelectedIndexes(rows); + } + } + /> +
+ + ); + }} + /> + + {!hidden() && ( +
+ { + return ( + <> + + + + + ( + + )} + /> + + ); + }} + /> + + +
+ )} +
+ )} + + {type() === "table" && ( +
+

Triggers

+ +

+ The admin dashboard currently does not support modifying triggers. + Please use the editor to{" "} + + create + {" "} + new triggers or{" "} + drop{" "} + existing ones. +

+ +
+ triggerColumns} data={triggers} /> +
+
+ )} +
+ + ); +} + +function pickInitiallySelectedTable( + tables: (Table | View)[], + tableName: string | undefined, +): Table | View | undefined { + if (tables.length === 0) { + return undefined; + } + + for (const table of tables) { + if (tableName == table.name) { + return table; + } + } + return tables[0]; +} + +function TablePickerPane(props: { + horizontal: boolean; + tablesAndViews: (Table | View)[]; + selectedTableName: Signal; + schemaRefetch: () => Promise; +}) { + const tablesAndViews = createMemo(() => + props.tablesAndViews.toSorted((a, b) => { + const aHidden = a.name.startsWith("_"); + const bHidden = b.name.startsWith("_"); + + if (aHidden == bHidden) { + return a.name.localeCompare(b.name); + } + // Sort hidden tables to the back. + return aHidden ? 1 : -1; + }), + ); + const tables = () => + tablesAndViews().filter( + (either) => (either as Table) !== undefined, + ) as Table[]; + + const showHidden = useStore($showHiddenTables); + + const [selectedTableName, setSelectedTableName] = props.selectedTableName; + + createEffect(() => { + // Update search params. + const tableName = selectedTableName(); + + const [searchParams, setSearchParams] = useSearchParams<{ + table: string; + }>(); + const index = tableName + ? tablesAndViews().findIndex((t) => t.name === tableName) + : -1; + if (index < 0) { + console.debug("Did not find table:", tableName); + setSelectedTableName( + pickInitiallySelectedTable(tablesAndViews(), searchParams.table)?.name, + ); + } + + if (tableName !== searchParams.table) { + setSearchParams({ table: tableName }); + } + }); + + const flexStyle = () => (props.horizontal ? "flex flex-col h-dvh" : "flex"); + + return ( +
+ {/* TODO: Maybe add a thin bottom scrollbar to make overflow more apparent */} +
+ + {(item: Table | View) => { + const hidden = hiddenTable(item); + const type = tableType(item); + const selected = () => item.name === selectedTableName(); + + return ( + + ); + }} + + + { + return ( + <> + + + + + ( + + )} + /> + + ); + }} + /> +
+ + { + if (!show && selectedTableName()?.startsWith("_")) { + setSelectedTableName(undefined); + } + console.debug("Show hidden tables:", show); + $showHiddenTables.set(show); + }} + > + + + + Hidden Tables + +
+ ); +} + +function TableSplitView(props: { + schemas: ListSchemasResponse; + schemaRefetch: () => Promise; +}) { + const showHidden = useStore($showHiddenTables); + function filterHidden( + schemas: (Table | View)[], + showHidden: boolean, + ): (Table | View)[] { + return schemas.filter((s) => showHidden || !s.name.startsWith("_")); + } + const tablesAndViews = () => + filterHidden( + [...props.schemas.tables, ...props.schemas.views], + showHidden(), + ); + + const [searchParams] = useSearchParams<{ table: string }>(); + const selectedTableNameSignal = createSignal( + pickInitiallySelectedTable(tablesAndViews(), searchParams.table)?.name, + ); + + const selectedTable = (): Table | View | undefined => { + const [selectedTableName] = selectedTableNameSignal; + const table = props.schemas.tables.find( + (t) => t.name == selectedTableName(), + ); + if (table) { + return table; + } + return props.schemas.views.find((t) => t.name == selectedTableName()); + }; + + const First = (p: { horizontal: boolean }) => ( + + ); + const Second = () => ( + No table selected} + > + + + ); + + return ; +} + +export function TablesPage() { + const [schemaFetch, { refetch }] = createResource(getAllTableSchemas); + + return ( + + + Schema fetch error: {JSON.stringify(schemaFetch.latest)} + + + + { + const schemas = await refetch(); + console.debug("All table schemas re-fetched:", schemas); + }} + /> + + + ); +} + +const sheetMaxWidth = "sm:max-w-[520px]"; +const $showHiddenTables = persistentAtom("show_hidden_tables", false, { + encode: JSON.stringify, + decode: JSON.parse, +}); + +const indexColumns = [ + { + header: "name", + accessorKey: "name", + }, + { + header: "columns", + accessorFn: (index: TableIndex) => { + return index.columns.map((c) => c.column_name).join(", "); + }, + }, + { + header: "unique", + accessorKey: "unique", + }, + { + header: "predicate", + accessorFn: (index: TableIndex) => { + return index.predicate?.replaceAll("<>", "!="); + }, + }, +] as ColumnDef[]; + +const triggerColumnHelper = createColumnHelper(); +const triggerColumns = [ + triggerColumnHelper.accessor("name", {}), + triggerColumnHelper.accessor("sql", { + header: "statement", + cell: (props) =>
{props.getValue()}
, + }), +] as ColumnDef[]; diff --git a/ui/admin/src/components/ui/accordion.tsx b/ui/admin/src/components/ui/accordion.tsx new file mode 100644 index 0000000..ec86dcf --- /dev/null +++ b/ui/admin/src/components/ui/accordion.tsx @@ -0,0 +1,82 @@ +import { type JSX, splitProps, type ValidComponent } from "solid-js" + +import * as AccordionPrimitive from "@kobalte/core/accordion" +import type { PolymorphicProps } from "@kobalte/core/polymorphic" + +import { cn } from "@/lib/utils" + +const Accordion = AccordionPrimitive.Root + +type AccordionItemProps = + AccordionPrimitive.AccordionItemProps & { + class?: string | undefined + } + +const AccordionItem = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as AccordionItemProps, ["class"]) + return +} + +type AccordionTriggerProps = + AccordionPrimitive.AccordionTriggerProps & { + class?: string | undefined + children?: JSX.Element + } + +const AccordionTrigger = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as AccordionTriggerProps, ["class", "children"]) + return ( + + svg]:rotate-180", + local.class + )} + {...others} + > + {local.children} + + + + + + ) +} + +type AccordionContentProps = + AccordionPrimitive.AccordionContentProps & { + class?: string | undefined + children?: JSX.Element + } + +const AccordionContent = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as AccordionContentProps, ["class", "children"]) + return ( + +
{local.children}
+
+ ) +} + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/ui/admin/src/components/ui/badge.tsx b/ui/admin/src/components/ui/badge.tsx new file mode 100644 index 0000000..6407e17 --- /dev/null +++ b/ui/admin/src/components/ui/badge.tsx @@ -0,0 +1,48 @@ +import type { Component, ComponentProps } from "solid-js" +import { splitProps } from "solid-js" + +import type { VariantProps } from "class-variance-authority" +import { cva } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground" + } + }, + defaultVariants: { + variant: "default" + } + } +) + +type BadgeProps = ComponentProps<"div"> & + VariantProps & { + round?: boolean + } + +const Badge: Component = (props) => { + const [local, others] = splitProps(props, ["class", "variant", "round"]) + return ( +
+ ) +} + +export type { BadgeProps } +export { Badge, badgeVariants } diff --git a/ui/admin/src/components/ui/button.tsx b/ui/admin/src/components/ui/button.tsx new file mode 100644 index 0000000..6282259 --- /dev/null +++ b/ui/admin/src/components/ui/button.tsx @@ -0,0 +1,52 @@ +import { type JSX, splitProps, type ValidComponent } from "solid-js" + +import * as ButtonPrimitive from "@kobalte/core/button" +import { type PolymorphicProps } from "@kobalte/core/polymorphic" +import type { VariantProps } from "class-variance-authority" +import { cva } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: "border border-input hover:bg-accent hover:text-accent-foreground", + secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline" + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "size-10" + } + }, + defaultVariants: { + variant: "default", + size: "default" + } + } +) + +type ButtonProps = ButtonPrimitive.ButtonRootProps & + VariantProps & { class?: string | undefined; children?: JSX.Element } + +const Button = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as ButtonProps, ["variant", "size", "class"]) + return ( + + ) +} + +export type { ButtonProps } +export { Button, buttonVariants } diff --git a/ui/admin/src/components/ui/card.tsx b/ui/admin/src/components/ui/card.tsx new file mode 100644 index 0000000..6cfc008 --- /dev/null +++ b/ui/admin/src/components/ui/card.tsx @@ -0,0 +1,43 @@ +import type { Component, ComponentProps } from "solid-js" +import { splitProps } from "solid-js" + +import { cn } from "@/lib/utils" + +const Card: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( +
+ ) +} + +const CardHeader: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return
+} + +const CardTitle: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( +

+ ) +} + +const CardDescription: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return

+} + +const CardContent: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return

+} + +const CardFooter: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return
+} + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/ui/admin/src/components/ui/checkbox.tsx b/ui/admin/src/components/ui/checkbox.tsx new file mode 100644 index 0000000..1295351 --- /dev/null +++ b/ui/admin/src/components/ui/checkbox.tsx @@ -0,0 +1,38 @@ +import { splitProps, type ValidComponent } from "solid-js" + +import * as CheckboxPrimitive from "@kobalte/core/checkbox" +import type { PolymorphicProps } from "@kobalte/core/polymorphic" + +import { cn } from "@/lib/utils" + +type CheckboxRootProps = + CheckboxPrimitive.CheckboxRootProps & { class?: string | undefined } + +const Checkbox = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as CheckboxRootProps, ["class"]) + return ( + + + + + + + + + + + ) +} + +export { Checkbox } diff --git a/ui/admin/src/components/ui/dialog.tsx b/ui/admin/src/components/ui/dialog.tsx new file mode 100644 index 0000000..18373d9 --- /dev/null +++ b/ui/admin/src/components/ui/dialog.tsx @@ -0,0 +1,141 @@ +import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js" +import { splitProps } from "solid-js" + +import * as DialogPrimitive from "@kobalte/core/dialog" +import type { PolymorphicProps } from "@kobalte/core/polymorphic" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal: Component = (props) => { + const [, rest] = splitProps(props, ["children"]) + return ( + +
+ {props.children} +
+
+ ) +} + +type DialogOverlayProps = + DialogPrimitive.DialogOverlayProps & { class?: string | undefined } + +const DialogOverlay = ( + props: PolymorphicProps> +) => { + const [, rest] = splitProps(props as DialogOverlayProps, ["class"]) + return ( + + ) +} + +type DialogContentProps = + DialogPrimitive.DialogContentProps & { + class?: string | undefined + children?: JSX.Element + } + +const DialogContent = ( + props: PolymorphicProps> +) => { + const [, rest] = splitProps(props as DialogContentProps, ["class", "children"]) + return ( + + + + {props.children} + + + + + + Close + + + + ) +} + +const DialogHeader: Component> = (props) => { + const [, rest] = splitProps(props, ["class"]) + return ( +
+ ) +} + +const DialogFooter: Component> = (props) => { + const [, rest] = splitProps(props, ["class"]) + return ( +
+ ) +} + +type DialogTitleProps = DialogPrimitive.DialogTitleProps & { + class?: string | undefined +} + +const DialogTitle = ( + props: PolymorphicProps> +) => { + const [, rest] = splitProps(props as DialogTitleProps, ["class"]) + return ( + + ) +} + +type DialogDescriptionProps = + DialogPrimitive.DialogDescriptionProps & { + class?: string | undefined + } + +const DialogDescription = ( + props: PolymorphicProps> +) => { + const [, rest] = splitProps(props as DialogDescriptionProps, ["class"]) + return ( + + ) +} + +export { + Dialog, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription +} diff --git a/ui/admin/src/components/ui/hover-card.tsx b/ui/admin/src/components/ui/hover-card.tsx new file mode 100644 index 0000000..3e4e630 --- /dev/null +++ b/ui/admin/src/components/ui/hover-card.tsx @@ -0,0 +1,37 @@ +import type { Component, ValidComponent } from "solid-js" +import { splitProps } from "solid-js" + +import * as HoverCardPrimitive from "@kobalte/core/hover-card" +import type { PolymorphicProps } from "@kobalte/core/polymorphic" + +import { cn } from "@/lib/utils" + +const HoverCardTrigger = HoverCardPrimitive.Trigger + +const HoverCard: Component = (props) => { + return +} + +type HoverCardContentProps = + HoverCardPrimitive.HoverCardContentProps & { + class?: string | undefined + } + +const HoverCardContent = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as HoverCardContentProps, ["class"]) + return ( + + + + ) +} + +export { HoverCard, HoverCardTrigger, HoverCardContent } diff --git a/ui/admin/src/components/ui/label.tsx b/ui/admin/src/components/ui/label.tsx new file mode 100644 index 0000000..afba022 --- /dev/null +++ b/ui/admin/src/components/ui/label.tsx @@ -0,0 +1,19 @@ +import type { Component, ComponentProps } from "solid-js" +import { splitProps } from "solid-js" + +import { cn } from "@/lib/utils" + +const Label: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( +

+ + ) +} + +const TableHeader: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return +} + +const TableBody: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return +} + +const TableFooter: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( + + ) +} + +const TableRow: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( + + ) +} + +const TableHead: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( +
+ ) +} + +const TableCell: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( + + ) +} + +const TableCaption: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return
+} + +export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } diff --git a/ui/admin/src/components/ui/tabs.tsx b/ui/admin/src/components/ui/tabs.tsx new file mode 100644 index 0000000..fdf72e0 --- /dev/null +++ b/ui/admin/src/components/ui/tabs.tsx @@ -0,0 +1,87 @@ +import type { ValidComponent } from "solid-js" +import { splitProps } from "solid-js" + +import type { PolymorphicProps } from "@kobalte/core/polymorphic" +import * as TabsPrimitive from "@kobalte/core/tabs" + +import { cn } from "@/lib/utils" + +const Tabs = TabsPrimitive.Root + +type TabsListProps = TabsPrimitive.TabsListProps & { + class?: string | undefined +} + +const TabsList = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TabsListProps, ["class"]) + return ( + + ) +} + +type TabsTriggerProps = TabsPrimitive.TabsTriggerProps & { + class?: string | undefined +} + +const TabsTrigger = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TabsTriggerProps, ["class"]) + return ( + + ) +} + +type TabsContentProps = TabsPrimitive.TabsContentProps & { + class?: string | undefined +} + +const TabsContent = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TabsContentProps, ["class"]) + return ( + + ) +} + +type TabsIndicatorProps = TabsPrimitive.TabsIndicatorProps & { + class?: string | undefined +} + +const TabsIndicator = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TabsIndicatorProps, ["class"]) + return ( + + ) +} + +export { Tabs, TabsList, TabsTrigger, TabsContent, TabsIndicator } diff --git a/ui/admin/src/components/ui/text-field.tsx b/ui/admin/src/components/ui/text-field.tsx new file mode 100644 index 0000000..c8515cb --- /dev/null +++ b/ui/admin/src/components/ui/text-field.tsx @@ -0,0 +1,143 @@ +import type { ValidComponent } from "solid-js" +import { splitProps } from "solid-js" + +import type { PolymorphicProps } from "@kobalte/core" +import * as TextFieldPrimitive from "@kobalte/core/text-field" +import { cva } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const TextField = TextFieldPrimitive.Root + +export type TextFieldType = + | "button" + | "checkbox" + | "color" + | "date" + | "datetime-local" + | "email" + | "file" + | "hidden" + | "image" + | "month" + | "number" + | "password" + | "radio" + | "range" + | "reset" + | "search" + | "submit" + | "tel" + | "text" + | "time" + | "url" + | "week"; + +type TextFieldInputProps = + TextFieldPrimitive.TextFieldInputProps & { + class?: string | undefined + type:TextFieldType, + } + +const TextFieldInput = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TextFieldInputProps, ["type", "class"]) + return ( + + ) +} + +type TextFieldTextAreaProps = + TextFieldPrimitive.TextFieldTextAreaProps & { class?: string | undefined } + +const TextFieldTextArea = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TextFieldTextAreaProps, ["class"]) + return ( + + ) +} + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", + { + variants: { + variant: { + label: "data-[invalid]:text-destructive", + description: "text-destructive", + error: "font-normal text-muted-foreground" + } + }, + defaultVariants: { + variant: "label" + } + } +) + +type TextFieldLabelProps = + TextFieldPrimitive.TextFieldLabelProps & { class?: string | undefined } + +const TextFieldLabel = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TextFieldLabelProps, ["class"]) + return +} + +type TextFieldDescriptionProps = + TextFieldPrimitive.TextFieldDescriptionProps & { + class?: string | undefined + } + +const TextFieldDescription = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TextFieldDescriptionProps, ["class"]) + return ( + + ) +} + +type TextFieldErrorMessageProps = + TextFieldPrimitive.TextFieldErrorMessageProps & { + class?: string | undefined + } + +const TextFieldErrorMessage = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TextFieldErrorMessageProps, ["class"]) + return ( + + ) +} + +export { + TextField, + TextFieldInput, + TextFieldTextArea, + TextFieldLabel, + TextFieldDescription, + TextFieldErrorMessage +} diff --git a/ui/admin/src/components/ui/toast.tsx b/ui/admin/src/components/ui/toast.tsx new file mode 100644 index 0000000..d43773c --- /dev/null +++ b/ui/admin/src/components/ui/toast.tsx @@ -0,0 +1,163 @@ +import type { JSX, ValidComponent } from "solid-js" +import { Match, splitProps, Switch } from "solid-js" +import { Portal } from "solid-js/web" + +import type { PolymorphicProps } from "@kobalte/core/polymorphic" +import * as ToastPrimitive from "@kobalte/core/toast" +import type { VariantProps } from "class-variance-authority" +import { cva } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const toastVariants = cva( + "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--kb-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--kb-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[opened]:animate-in data-[closed]:animate-out data-[swipe=end]:animate-out data-[closed]:fade-out-80 data-[closed]:slide-out-to-right-full data-[opened]:slide-in-from-top-full data-[opened]:sm:slide-in-from-bottom-full", + { + variants: { + variant: { + default: "border bg-background text-foreground", + destructive: + "destructive group border-destructive bg-destructive text-destructive-foreground", + success: "success border-success-foreground bg-success text-success-foreground", + warning: "warning border-warning-foreground bg-warning text-warning-foreground", + error: "error border-error-foreground bg-error text-error-foreground" + } + }, + defaultVariants: { + variant: "default" + } + } +) +type ToastVariant = NonNullable["variant"]> + +type ToastListProps = ToastPrimitive.ToastListProps & { + class?: string | undefined +} + +const Toaster = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as ToastListProps, ["class"]) + return ( + + + + + + ) +} + +type ToastRootProps = ToastPrimitive.ToastRootProps & + VariantProps & { class?: string | undefined } + +const Toast = (props: PolymorphicProps>) => { + const [local, others] = splitProps(props as ToastRootProps, ["class", "variant"]) + return ( + + ) +} + +type ToastCloseButtonProps = + ToastPrimitive.ToastCloseButtonProps & { class?: string | undefined } + +const ToastClose = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as ToastCloseButtonProps, ["class"]) + return ( + + + + + + + ) +} + +type ToastTitleProps = ToastPrimitive.ToastTitleProps & { + class?: string | undefined +} + +const ToastTitle = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as ToastTitleProps, ["class"]) + return +} + +type ToastDescriptionProps = + ToastPrimitive.ToastDescriptionProps & { class?: string | undefined } + +const ToastDescription = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as ToastDescriptionProps, ["class"]) + return +} + +function showToast(props: { + title?: JSX.Element + description?: JSX.Element + variant?: ToastVariant + duration?: number +}) { + ToastPrimitive.toaster.show((data) => ( + +
+ {props.title && {props.title}} + {props.description && {props.description}} +
+ +
+ )) +} + +function showToastPromise( + promise: Promise | (() => Promise), + options: { + loading?: JSX.Element + success?: (data: T) => JSX.Element + error?: (error: U) => JSX.Element + duration?: number + } +) { + const variant: { [key in ToastPrimitive.ToastPromiseState]: ToastVariant } = { + pending: "default", + fulfilled: "success", + rejected: "error" + } + return ToastPrimitive.toaster.promise(promise, (props) => ( + + + {options.loading} + {options.success?.(props.data!)} + {options.error?.(props.error!)} + + + )) +} + +export { Toaster, Toast, ToastClose, ToastTitle, ToastDescription, showToast, showToastPromise } diff --git a/ui/admin/src/components/ui/toggle.tsx b/ui/admin/src/components/ui/toggle.tsx new file mode 100644 index 0000000..f7cb34b --- /dev/null +++ b/ui/admin/src/components/ui/toggle.tsx @@ -0,0 +1,49 @@ +import type { ValidComponent } from "solid-js" +import { splitProps } from "solid-js" + +import type { PolymorphicProps } from "@kobalte/core/polymorphic" +import * as ToggleButtonPrimitive from "@kobalte/core/toggle-button" +import { cva } from "class-variance-authority" +import type { VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const toggleVariants = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-transparent", + outline: "border border-input bg-transparent shadow-sm" + }, + size: { + default: "h-9 px-3", + sm: "h-8 px-2", + lg: "h-10 px-3" + } + }, + defaultVariants: { + variant: "default", + size: "default" + } + } +) + +type ToggleButtonRootProps = + ToggleButtonPrimitive.ToggleButtonRootProps & + VariantProps & { class?: string | undefined } + +const Toggle = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as ToggleButtonRootProps, ["class", "variant", "size"]) + return ( + + ) +} + +export type { ToggleButtonRootProps as ToggleProps } +export { toggleVariants, Toggle } diff --git a/ui/admin/src/components/ui/tooltip.tsx b/ui/admin/src/components/ui/tooltip.tsx new file mode 100644 index 0000000..948b5b7 --- /dev/null +++ b/ui/admin/src/components/ui/tooltip.tsx @@ -0,0 +1,34 @@ +import { splitProps, type ValidComponent, type Component } from "solid-js" + +import type { PolymorphicProps } from "@kobalte/core/polymorphic" +import * as TooltipPrimitive from "@kobalte/core/tooltip" + +import { cn } from "@/lib/utils" + +const TooltipTrigger = TooltipPrimitive.Trigger + +const Tooltip: Component = (props) => { + return +} + +type TooltipContentProps = + TooltipPrimitive.TooltipContentProps & { class?: string | undefined } + +const TooltipContent = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as TooltipContentProps, ["class"]) + return ( + + + + ) +} + +export { Tooltip, TooltipTrigger, TooltipContent } diff --git a/ui/admin/src/index.css b/ui/admin/src/index.css new file mode 100644 index 0000000..82e8f87 --- /dev/null +++ b/ui/admin/src/index.css @@ -0,0 +1,141 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + + --info: 204 94% 94%; + --info-foreground: 199 89% 48%; + + --success: 149 80% 90%; + --success-foreground: 160 84% 39%; + + --warning: 48 96% 89%; + --warning-foreground: 25 95% 53%; + + --error: 0 93% 94%; + --error-foreground: 0 84% 60%; + + --ring: 240 5.9% 10%; + + --radius: 0.5rem; + } + + .dark, + [data-kb-theme="dark"] { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + + --info: 204 94% 94%; + --info-foreground: 199 89% 48%; + + --success: 149 80% 90%; + --success-foreground: 160 84% 39%; + + --warning: 48 96% 89%; + --warning-foreground: 25 95% 53%; + + --error: 0 93% 94%; + --error-foreground: 0 84% 60%; + + --ring: 240 4.9% 83.9%; + + --radius: 0.5rem; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + font-feature-settings: + "rlig" 1, + "calt" 1; + } +} + +@layer utilities { + .step { + counter-increment: step; + } + + .step:before { + @apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background; + @apply ml-[-50px] mt-[-4px]; + content: counter(step); + } +} + +@media (max-width: 640px) { + .container { + @apply px-4; + } +} + +::-webkit-scrollbar { + width: 16px; +} + +::-webkit-scrollbar-thumb { + border-radius: 9999px; + border: 4px solid transparent; + background-clip: content-box; + @apply bg-accent; +} + +::-webkit-scrollbar-corner { + display: none; +} diff --git a/ui/admin/src/index.tsx b/ui/admin/src/index.tsx new file mode 100644 index 0000000..551e9c4 --- /dev/null +++ b/ui/admin/src/index.tsx @@ -0,0 +1,19 @@ +/* @refresh reload */ +import { render } from "solid-js/web"; + +import "@common/css/global.css"; +import "@common/css/kobalte.css"; + +import App from "./App"; + +const root = document.getElementById("root"); + +if (import.meta.env.DEV && !(root instanceof HTMLElement)) { + throw new Error( + "Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?", + ); +} + +render(() => { + return ; +}, root!); diff --git a/ui/admin/src/lib/bindings.ts b/ui/admin/src/lib/bindings.ts new file mode 100644 index 0000000..a54cf5f --- /dev/null +++ b/ui/admin/src/lib/bindings.ts @@ -0,0 +1,55 @@ +export type * from "@bindings/AlterIndexRequest"; +export type * from "@bindings/AlterTableRequest"; +export type * from "@bindings/Column"; +export type * from "@bindings/ColumnDataType"; +export type * from "@bindings/ColumnOption"; +export type * from "@bindings/ColumnOrder"; +export type * from "@bindings/ConfiguredOAuthProvidersResponse"; +export type * from "@bindings/CreateIndexRequest"; +export type * from "@bindings/CreateIndexResponse"; +export type * from "@bindings/CreateTableRequest"; +export type * from "@bindings/CreateTableResponse"; +export type * from "@bindings/CreateUserRequest"; +export type * from "@bindings/DeleteRowRequest"; +export type * from "@bindings/DeleteRowsRequest"; +export type * from "@bindings/DropIndexRequest"; +export type * from "@bindings/DropTableRequest"; +export type * from "@bindings/ForeignKey"; +export type * from "@bindings/GeneratedExpressionMode"; +export type * from "@bindings/JsonSchema"; +export type * from "@bindings/ListJsonSchemasResponse"; +export type * from "@bindings/ListLogsResponse"; +export type * from "@bindings/ListRowsResponse"; +export type * from "@bindings/ListSchemasResponse"; +export type * from "@bindings/ListUsersResponse"; +export type * from "@bindings/LogJson"; +export type * from "@bindings/LoginRequest"; +export type * from "@bindings/LoginResponse"; +export type * from "@bindings/Mode"; +export type * from "@bindings/OAuthProviderEntry"; +export type * from "@bindings/OAuthProviderResponse"; +export type * from "@bindings/ParseRequest"; +export type * from "@bindings/ParseResponse"; +export type * from "@bindings/QueryRequest"; +export type * from "@bindings/QueryResponse"; +export type * from "@bindings/ReadFilesRequest"; +export type * from "@bindings/ReferentialAction"; +export type * from "@bindings/Stats"; +export type * from "@bindings/Table"; +export type * from "@bindings/TableIndex"; +export type * from "@bindings/TableTrigger"; +export type * from "@bindings/View"; +export type * from "@bindings/UniqueConstraint"; +export type * from "@bindings/UpdateJsonSchemaRequest"; +export type * from "@bindings/UpdateRowRequest"; +export type * from "@bindings/UpdateUserRequest"; +export type * from "@bindings/UserJson"; + +export type FileUpload = { + id: string; + filename: string | undefined; + content_type: string | undefined; + mime_type: string | string; +}; + +export type FileUploads = FileUpload[]; diff --git a/ui/admin/src/lib/config.ts b/ui/admin/src/lib/config.ts new file mode 100644 index 0000000..f7c4b33 --- /dev/null +++ b/ui/admin/src/lib/config.ts @@ -0,0 +1,64 @@ +import { QueryClient, createQuery } from "@tanstack/solid-query"; + +import { Config } from "@proto/config"; +import { GetConfigResponse, UpdateConfigRequest } from "@proto/config_api"; +import { adminFetch } from "@/lib/fetch"; + +const defaultKey = ["default"]; + +function createClient(): QueryClient { + return new QueryClient(); +} +const queryClient = createClient(); + +export async function setConfig(config: Config) { + const data = queryClient.getQueryData(defaultKey); + const hash = data?.hash; + if (!hash) { + console.error("Missing hash from:", data); + return; + } + + const request: UpdateConfigRequest = { + config, + hash, + }; + console.debug("Updating config:", request); + const response = await updateConfig(request); + + queryClient.invalidateQueries(); + + return response; +} + +export function createConfigQuery() { + return createQuery( + () => ({ + queryKey: defaultKey, + queryFn: async () => { + const config = await getConfig(); + console.debug("Fetched config:", config); + return config; + }, + refetchInterval: 120 * 1000, + refetchOnMount: false, + }), + () => queryClient, + ); +} + +async function getConfig(): Promise { + const response = await adminFetch("/config"); + const array = new Uint8Array(await (await response.blob()).arrayBuffer()); + return GetConfigResponse.decode(array); +} + +async function updateConfig(request: UpdateConfigRequest): Promise { + await adminFetch("/config", { + method: "POST", + headers: { + "Content-Type": "application/octet-stream", + }, + body: UpdateConfigRequest.encode(request).finish(), + }); +} diff --git a/ui/admin/src/lib/fetch.ts b/ui/admin/src/lib/fetch.ts new file mode 100644 index 0000000..e0e743c --- /dev/null +++ b/ui/admin/src/lib/fetch.ts @@ -0,0 +1,40 @@ +import { computed } from "nanostores"; +import { persistentAtom } from "@nanostores/persistent"; +import { Client, type Tokens, type User } from "trailbase"; + +import { showToast } from "@/components/ui/toast"; + +const $tokens = persistentAtom("auth_tokens", null, { + encode: JSON.stringify, + decode: JSON.parse, +}); +export const $user = computed($tokens, (_tokens) => client.user()); + +const HOST = import.meta.env.DEV ? "http://localhost:4000" : ""; +export const client = Client.init(HOST, { + tokens: $tokens.get() ?? undefined, + onAuthChange: (c: Client, _user: User | undefined) => { + $tokens.set(c.tokens() ?? null); + }, +}); + +export async function adminFetch( + input: string, + init?: RequestInit, +): Promise { + if (!input.startsWith("/")) { + throw Error("Should start with '/'"); + } + + try { + return await client.fetch(`api/_admin${input}`, init); + } catch (err) { + showToast({ + title: "Fetch Error", + description: `${err}`, + variant: "error", + }); + + throw err; + } +} diff --git a/ui/admin/src/lib/name.ts b/ui/admin/src/lib/name.ts new file mode 100644 index 0000000..807f320 --- /dev/null +++ b/ui/admin/src/lib/name.ts @@ -0,0 +1,33 @@ +function getRandomInt(max: number): number { + return Math.floor(Math.random() * max); +} + +const adjectives = [ + "lucid", + "feral", + "jumpy", + "hasty", + "gnarly", + "friendly", + "fresh", + "funny", + "lengthy", +]; + +const nouns = [ + "lynx", + "badger", + "lion", + "panda", + "ant", + "fink", + "lizard", + "canine", + "tiger", +]; + +export function randomName(): string { + const prefix = adjectives[getRandomInt(adjectives.length - 1)]; + const suffix = nouns[getRandomInt(nouns.length - 1)]; + return `${prefix}_${suffix}`; +} diff --git a/ui/admin/src/lib/parse.ts b/ui/admin/src/lib/parse.ts new file mode 100644 index 0000000..f8a517c --- /dev/null +++ b/ui/admin/src/lib/parse.ts @@ -0,0 +1,23 @@ +import type { ParseRequest, ParseResponse } from "@/lib/bindings"; +import { adminFetch } from "@/lib/fetch"; +import { urlSafeBase64Encode } from "trailbase"; + +async function fetchParse(request: ParseRequest): Promise { + const response = await adminFetch("/parse", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); + return await response.json(); +} + +export async function parseSql(sql: string): Promise { + const response = await fetchParse({ + query: urlSafeBase64Encode(sql), + mode: "Expression", + }); + + return response.ok ? undefined : (response.message ?? "error"); +} diff --git a/ui/admin/src/lib/schema.ts b/ui/admin/src/lib/schema.ts new file mode 100644 index 0000000..9f6d4f4 --- /dev/null +++ b/ui/admin/src/lib/schema.ts @@ -0,0 +1,260 @@ +import type { + Column, + ColumnOption, + ReferentialAction, + Table, + View, +} from "@/lib/bindings"; + +export function isNotNull(options: ColumnOption[]): boolean { + return options.findIndex((o: ColumnOption) => o === "NotNull") >= 0; +} + +export function setNotNull( + options: ColumnOption[], + value: boolean, +): ColumnOption[] { + const newOpts: ColumnOption[] = options.filter( + (o) => o !== "Null" && o !== "NotNull", + ); + newOpts.push(value ? "NotNull" : "Null"); + return newOpts; +} + +function unpackDefaultValue(col: ColumnOption): string | undefined { + if (typeof col === "object" && "Default" in col) { + return col.Default as string; + } +} + +export function getDefaultValue(options: ColumnOption[]): string | undefined { + return options.reduce((acc, cur: ColumnOption) => { + return unpackDefaultValue(cur) ?? acc; + }, undefined); +} + +export function setDefaultValue( + options: ColumnOption[], + defaultValue: string | undefined, +): ColumnOption[] { + const newOpts = options.filter((o) => unpackDefaultValue(o) === undefined); + if (defaultValue !== undefined) { + newOpts.push({ Default: defaultValue }); + } + return newOpts; +} + +function unpackCheckValue(col: ColumnOption): string | undefined { + if (typeof col === "object" && "Check" in col) { + return col.Check as string; + } +} + +export function getCheckValue(options: ColumnOption[]): string | undefined { + return options.reduce((acc, cur: ColumnOption) => { + const maybeCheck = unpackCheckValue(cur); + if (maybeCheck !== undefined) { + return maybeCheck; + } + return acc; + }, undefined); +} + +export function setCheckValue( + options: ColumnOption[], + checkValue: string | undefined, +): ColumnOption[] { + const newOpts = options.filter((o) => unpackCheckValue(o) === undefined); + if (checkValue !== undefined) { + newOpts.push({ Check: checkValue }); + } + return newOpts; +} + +export function isOptional(options: ColumnOption[]): boolean { + let notNull = false; + for (const opt of options) { + if (opt === "NotNull") { + notNull = true; + } + if (unpackDefaultValue(opt)) { + return true; + } + } + return !notNull; +} + +export type ForeignKey = { + foreign_table: string; + referred_columns: Array; + on_delete: ReferentialAction | null; + on_update: ReferentialAction | null; +}; + +export function getForeignKey(options: ColumnOption[]): ForeignKey | undefined { + return options.reduce((acc, cur: ColumnOption) => { + type U = { ForeignKey: ForeignKey }; + + return typeof cur === "object" && "ForeignKey" in cur + ? ((cur as U).ForeignKey as ForeignKey) + : acc; + }, undefined); +} + +export function setForeignKey( + options: ColumnOption[], + fk: ForeignKey | undefined, +): ColumnOption[] { + const newOpts = options.filter( + (o) => typeof o !== "object" || !("ForeignKey" in o), + ); + if (fk) { + newOpts.push({ ForeignKey: fk }); + } + return newOpts; +} + +export type Unique = { is_primary: boolean }; + +export function getUnique(options: ColumnOption[]): Unique | undefined { + return options.reduce((acc, cur: ColumnOption) => { + type U = { Unique: { is_primary: boolean } }; + + return typeof cur === "object" && "Unique" in cur + ? ((cur as U).Unique as Unique) + : acc; + }, undefined); +} + +export function setUnique( + options: ColumnOption[], + unique: Unique | undefined, +): ColumnOption[] { + const newOpts = options.filter( + (o) => typeof o !== "object" || !("Unique" in o), + ); + if (unique) { + newOpts.push({ Unique: unique }); + } + return newOpts; +} + +export function isPrimaryKeyColumn(column: Column): boolean { + return getUnique(column.options)?.is_primary ?? false; +} + +export function findPrimaryKeyColumnIndex(columns: Column[]): number { + const candidate = columns.findIndex(isPrimaryKeyColumn); + return candidate >= 0 ? candidate : 0; +} + +export function isUUIDv7Column(column: Column): boolean { + if (column.data_type === "Blob") { + const check = getCheckValue(column.options); + return (check?.search(/^is_uuid_v7\s*\(/g) ?? -1) === 0; + } + return false; +} + +export function isFileUploadColumn(column: Column): boolean { + if (column.data_type === "Text") { + const check = getCheckValue(column.options); + return (check?.search(/^jsonschema\s*\('std.FileUpload'/g) ?? -1) === 0; + } + return false; +} + +export function isFileUploadsColumn(column: Column): boolean { + if (column.data_type === "Text") { + const check = getCheckValue(column.options); + return (check?.search(/jsonschema\s*\('std.FileUploads'/g) ?? -1) === 0; + } + return false; +} + +export function isJSONColumn(column: Column): boolean { + if (column.data_type === "Text") { + const check = getCheckValue(column.options); + return (check?.search(/^is_json\s*\(/g) ?? -1) === 0; + } + return false; +} + +function columnsSatisfyRecordApiRequirements( + columns: Column[], + all: Table[], +): boolean { + for (const column of columns) { + if (isPrimaryKeyColumn(column)) { + if (column.data_type === "Integer") { + return true; + } + + if (isUUIDv7Column(column)) { + return true; + } + + const foreign_key = getForeignKey(column.options); + if (foreign_key) { + const foreign_col_name = foreign_key.referred_columns[0]; + if (!foreign_col_name) { + continue; + } + + const foreign_table = all.find( + (t) => t.name === foreign_key.foreign_table, + ); + if (!foreign_table) { + continue; + } + + const foreign_col = foreign_table.columns.find( + (c) => c.name === foreign_col_name, + ); + if (foreign_col && isUUIDv7Column(foreign_col)) { + return true; + } + } + } + } + + return false; +} + +export function tableSatisfiesRecordApiRequirements( + table: Table, + all: Table[], +): boolean { + if (table.strict) { + return columnsSatisfyRecordApiRequirements(table.columns, all); + } + return false; +} + +export function viewSatisfiesRecordApiRequirements( + view: View, + all: Table[], +): boolean { + const columns = view.columns; + if (columns) { + return columnsSatisfyRecordApiRequirements(columns, all); + } + return false; +} + +export type TableType = "table" | "virtualTable" | "view"; + +export function tableType(table: Table | View): TableType { + if ("virtual_table" in table) { + if (table.virtual_table) { + return "virtualTable"; + } + return "table"; + } + + return "view"; +} + +export function hiddenTable(table: Table | View): boolean { + return table.name.startsWith("_"); +} diff --git a/ui/admin/src/lib/table.ts b/ui/admin/src/lib/table.ts new file mode 100644 index 0000000..a34b03e --- /dev/null +++ b/ui/admin/src/lib/table.ts @@ -0,0 +1,87 @@ +import { adminFetch } from "@/lib/fetch"; +import type { + AlterIndexRequest, + AlterTableRequest, + CreateIndexRequest, + CreateIndexResponse, + CreateTableRequest, + CreateTableResponse, + DropIndexRequest, + DropTableRequest, + ListSchemasResponse, +} from "@/lib/bindings"; + +export async function getAllTableSchemas(): Promise { + const response = await adminFetch("/tables"); + return (await response.json()) as ListSchemasResponse; +} + +export async function createIndex( + request: CreateIndexRequest, +): Promise { + const response = await adminFetch("/index", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); + return await response.json(); +} + +export async function createTable( + request: CreateTableRequest, +): Promise { + const response = await adminFetch("/table", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); + return await response.json(); +} + +export async function alterIndex(request: AlterIndexRequest) { + const response = await adminFetch("/index", { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); + return await response.text(); +} + +export async function alterTable(request: AlterTableRequest) { + const response = await adminFetch("/table", { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); + return await response.text(); +} + +export async function dropIndex(request: DropIndexRequest) { + const response = await adminFetch("/index", { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); + return await response.text(); +} + +export async function dropTable(request: DropTableRequest) { + const response = await adminFetch("/table", { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); + return await response.text(); +} diff --git a/ui/admin/src/lib/user.ts b/ui/admin/src/lib/user.ts new file mode 100644 index 0000000..ba39511 --- /dev/null +++ b/ui/admin/src/lib/user.ts @@ -0,0 +1,35 @@ +import type { UpdateUserRequest, CreateUserRequest } from "@/lib/bindings"; +import { adminFetch } from "@/lib/fetch"; + +export async function createUser(request: CreateUserRequest) { + await adminFetch("/user", { + method: "Post", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); +} + +export async function deleteUser(id: string): Promise { + // TODO: We should probably have a dedicated delete/disable user endpoint? + await adminFetch("/table/_user", { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: id, + }), + }); +} + +export async function updateUser(request: UpdateUserRequest) { + await adminFetch("/user", { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(request), + }); +} diff --git a/ui/admin/src/lib/utils.ts b/ui/admin/src/lib/utils.ts new file mode 100644 index 0000000..b2a4a6a --- /dev/null +++ b/ui/admin/src/lib/utils.ts @@ -0,0 +1,37 @@ +import type { ClassValue } from "clsx"; +import { clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; +import { stringify as uuidStringify } from "uuid"; +import { urlSafeBase64Decode } from "trailbase"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +export function urlSafeBase64ToUuid(id: string): string { + return uuidStringify( + Uint8Array.from(urlSafeBase64Decode(id), (c) => c.charCodeAt(0)), + ); +} + +export async function showSaveFileDialog(opts: { + contents: string; + filename: string; +}) { + // Not supported by firefox: https://developer.mozilla.org/en-US/docs/Web/API/Window/showSaveFilePicker#browser_compatibility + // possible fallback: https://stackoverflow.com/a/67806663 + if (window.showSaveFilePicker) { + const handle = await window.showSaveFilePicker({ + suggestedName: opts.filename, + }); + const writable = await handle.createWritable(); + await writable.write(opts.contents); + writable.close(); + } else { + const saveFile = document.createElement("a"); + saveFile.href = URL.createObjectURL(new Blob([opts.contents])); + saveFile.download = opts.filename; + saveFile.click(); + setTimeout(() => URL.revokeObjectURL(saveFile.href), 60000); + } +} diff --git a/ui/admin/tailwind.config.ts b/ui/admin/tailwind.config.ts new file mode 100644 index 0000000..70016f0 --- /dev/null +++ b/ui/admin/tailwind.config.ts @@ -0,0 +1,5 @@ +import type { Config } from "tailwindcss"; + +import { commonTailwindConfig } from "../common/tailwind.config.mjs"; + +export default commonTailwindConfig satisfies Config; diff --git a/ui/admin/tests/util.test.ts b/ui/admin/tests/util.test.ts new file mode 100644 index 0000000..e963b73 --- /dev/null +++ b/ui/admin/tests/util.test.ts @@ -0,0 +1,17 @@ +import { expect, test } from "vitest" +import { copyAndConvert } from "@/components/tables/InsertAlterRow"; + +type UnkownRow = { [key: string]: unknown }; +// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types +type ObjectRow = { [key: string]: Object | undefined }; + +test("utils", () => { + const x: UnkownRow = { + "foo": "test", + "bar": "test", + }; + const y: ObjectRow = copyAndConvert(x); + for (const key of Object.keys(x)) { + expect(x[key]).toBe(y[key]); + } +}); diff --git a/ui/admin/tsconfig.json b/ui/admin/tsconfig.json new file mode 100644 index 0000000..6988c1b --- /dev/null +++ b/ui/admin/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "../common/tsconfig.base.json", + "compilerOptions": { + "jsx": "preserve", + "jsxImportSource": "solid-js", + "types": [ + "@types/wicg-file-system-access", + "vite/client" + ], + "paths": { + "@/*": ["./src/*"], + "@proto/*": ["./proto/*"], + "@assets/*": ["../../assets/*"], + "@bindings/*": ["../../trailbase-core/bindings/*"], + "@common/*": ["../common/*"] + } + }, + "exclude": [ + "tailwind.config.ts", + "dist/", + "node_modules/", + "public/" + ] +} diff --git a/ui/admin/ui.config.json b/ui/admin/ui.config.json new file mode 100644 index 0000000..044552c --- /dev/null +++ b/ui/admin/ui.config.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://solid-ui.com/schema.json", + "tsx": true, + "tailwind": { + "css": "src/index.css", + "config": "tailwind.config.ts", + "prefix": "" + }, + "aliases": { + "components": "@/components/ui", + "utils": "@/lib/utils" + } +} diff --git a/ui/admin/vite.config.mts b/ui/admin/vite.config.mts new file mode 100644 index 0000000..348cde9 --- /dev/null +++ b/ui/admin/vite.config.mts @@ -0,0 +1,18 @@ +import { defineConfig } from 'vite'; + +import solidPlugin from 'vite-plugin-solid'; +import tsconfigPaths from 'vite-tsconfig-paths'; + +export default defineConfig({ + base: "/_/admin", + plugins: [ + tsconfigPaths(), + solidPlugin(), + ], + server: { + port: 3000, + }, + build: { + target: 'esnext', + }, +}); diff --git a/ui/auth/.gitignore b/ui/auth/.gitignore new file mode 100644 index 0000000..016b59e --- /dev/null +++ b/ui/auth/.gitignore @@ -0,0 +1,24 @@ +# build output +dist/ + +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ diff --git a/ui/auth/.prettierignore b/ui/auth/.prettierignore new file mode 100644 index 0000000..d2ab818 --- /dev/null +++ b/ui/auth/.prettierignore @@ -0,0 +1,8 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock + +src/components/ui +src/pages/login.astro +src/components/AlertBox.astro diff --git a/ui/auth/.prettierrc.mjs b/ui/auth/.prettierrc.mjs new file mode 100644 index 0000000..85ccfb5 --- /dev/null +++ b/ui/auth/.prettierrc.mjs @@ -0,0 +1,13 @@ +// .prettierrc.mjs +/** @type {import("prettier").Config} */ +export default { + plugins: ['prettier-plugin-astro'], + overrides: [ + { + files: '*.astro', + options: { + parser: 'astro', + }, + }, + ], +}; diff --git a/ui/auth/astro.config.mjs b/ui/auth/astro.config.mjs new file mode 100644 index 0000000..6458f36 --- /dev/null +++ b/ui/auth/astro.config.mjs @@ -0,0 +1,18 @@ +import { defineConfig } from 'astro/config'; + +import solidJs from "@astrojs/solid-js"; +import icon from "astro-icon"; +import tailwind from "@astrojs/tailwind"; + +// https://astro.build/config +export default defineConfig({ + output: "static", + base: "/_/auth", + integrations: [ + icon(), + solidJs(), + tailwind({ + applyBaseStyles: false, + }), + ], +}); diff --git a/ui/auth/package.json b/ui/auth/package.json new file mode 100644 index 0000000..ff8250d --- /dev/null +++ b/ui/auth/package.json @@ -0,0 +1,40 @@ +{ + "name": "trailbase-auth-ui", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro check && astro build", + "preview": "astro preview", + "astro": "astro", + "check": "astro check", + "format": "prettier -w src", + "proto": "protoc --plugin=protoc-gen-ts=${PWD}/node_modules/ts-proto/protoc-gen-ts_proto ../trailbase-core/proto/*.proto -I../trailbase-core/proto -I/usr/include --ts_out=src/proto/ --ts_opt=esModuleInterop=true && prettier -w src" + }, + "dependencies": { + "@astrojs/check": "^0.9.4", + "@astrojs/solid-js": "^4.4.2", + "@astrojs/tailwind": "^5.1.2", + "@kobalte/core": "^0.13.7", + "astro": "^4.16.7", + "astro-icon": "^1.1.1", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "solid-icons": "^1.1.0", + "solid-js": "^1.9.3", + "tailwind-merge": "^2.5.4", + "tailwindcss": "^3.4.14", + "tailwindcss-animate": "^1.0.7", + "trailbase": "workspace:*" + }, + "devDependencies": { + "@iconify-json/tabler": "^1.2.6", + "@tailwindcss/typography": "^0.5.15", + "prettier": "^3.3.3", + "prettier-plugin-astro": "^0.14.1", + "sharp": "^0.33.5", + "ts-proto": "^2.2.5", + "typescript": "^5.6.3" + } +} diff --git a/ui/auth/src/components/AlertBox.astro b/ui/auth/src/components/AlertBox.astro new file mode 100644 index 0000000..e260e5c --- /dev/null +++ b/ui/auth/src/components/AlertBox.astro @@ -0,0 +1,58 @@ +--- +interface Props { + message?: string; +} + +const { message } = Astro.props; +--- + +
+ {message} +
+ +{ + import.meta.env.DEV && ( + + ) +} diff --git a/ui/auth/src/components/Card.astro b/ui/auth/src/components/Card.astro new file mode 100644 index 0000000..f0a6b29 --- /dev/null +++ b/ui/auth/src/components/Card.astro @@ -0,0 +1,7 @@ +--- + +--- + +
+ +
diff --git a/ui/auth/src/components/ErrorBoundary.tsx b/ui/auth/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..c10096d --- /dev/null +++ b/ui/auth/src/components/ErrorBoundary.tsx @@ -0,0 +1,35 @@ +import { + ErrorBoundary as SolidErrorBoundary, + type JSX, + children, +} from "solid-js"; +import { Toaster, showToast } from "@/components/ui/toast"; + +export function ErrorBoundary(props: { children: JSX.Element }) { + const resolved = children(() => props.children); + + // NOTE: the fallback handles errors during component construction. Not + // errors at runtime, e.g.in a button handler. + return ( + { + return
{`${err}`}
; + }} + > + {resolved()} + + +
+ ); +} + +window.onerror = function (message, url, lineNumber) { + const description = `${url}:${lineNumber} ${message}`; + console.error(description); + + showToast({ + title: "Uncaught Error", + description, + variant: "error", + }); +}; diff --git a/ui/auth/src/components/Form.astro b/ui/auth/src/components/Form.astro new file mode 100644 index 0000000..17dd9d2 --- /dev/null +++ b/ui/auth/src/components/Form.astro @@ -0,0 +1,27 @@ +--- +import BaseLayout from "@/layouts/BaseLayout.astro"; +import Card from "@/components/Card.astro"; +import AlertBox from "@/components/AlertBox.astro"; + +interface Props { + title: string; +} + +const { title } = Astro.props; +--- + + +
+ +
+

{title}

+
+ + +
+ + {"{% if alert %}"} + + {"{% endif %}"} +
+
diff --git a/ui/auth/src/components/ListOauthProviders.tsx b/ui/auth/src/components/ListOauthProviders.tsx new file mode 100644 index 0000000..c041b0a --- /dev/null +++ b/ui/auth/src/components/ListOauthProviders.tsx @@ -0,0 +1,53 @@ +import { createResource, For, Suspense, ErrorBoundary } from "solid-js"; +import type { ConfiguredOAuthProvidersResponse } from "@bindings/ConfiguredOAuthProvidersResponse"; + +import { AUTH_API } from "@/lib/constants"; + +async function listConfiguredOAuthProviders(): Promise { + const response = await fetch(`${AUTH_API}/oauth/providers`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw await response.text(); + } + return await response.json(); +} + +export function ConfiguredOAuthProviders() { + let [providersFetch] = createResource(listConfiguredOAuthProviders); + + const providers = () => { + const providers = [...(providersFetch()?.providers ?? [])]; + if (import.meta.env.DEV) { + providers.push(["name", "Display Name"]); + } + return providers; + }; + + return ( +

OAuth: {err.toString()}

}> + Loading...}> +
+ {providers().length > 0 &&

Or use an external provider:

} + + + {([name, displayName]) => { + return ( + + Login with {displayName} + + ); + }} + +
+
+
+ ); +} diff --git a/ui/auth/src/components/Profile.tsx b/ui/auth/src/components/Profile.tsx new file mode 100644 index 0000000..175041d --- /dev/null +++ b/ui/auth/src/components/Profile.tsx @@ -0,0 +1,286 @@ +import { createResource, createSignal, Switch, Match } from "solid-js"; +import { TbUser, TbLogout, TbTrash } from "solid-icons/tb"; +import { Client, type User } from "trailbase"; + +import { + HOST, + RECORD_API, + OUTLINE_BUTTON_STYLE, + ICON_STYLE, + DESTRUCTIVE_ICON_STYLE, +} from "@/lib/constants"; +import { Button } from "@/components/ui/button"; +import { Card } from "@/components/ui/card"; +import { ErrorBoundary } from "@/components/ErrorBoundary"; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +// import { +// TextField, +// TextFieldLabel, +// TextFieldInput, +// } from "@/components/ui/text-field"; + +function DeleteAccountButton(props: { client: Client }) { + const [open, setOpen] = createSignal(false); + + return ( + + +
+ +
+
+ + + + Delete Account + + Are you sure you want to proceed? The deletion is destructive and cannot + be reverted. + + + + + + +
+ ); +} + +// function ChangeEmailButton(props: { oldEmail: string; client: Client }) { +// const [open, setOpen] = createSignal(false); +// const [email, setEmail] = createSignal(props.oldEmail); +// +// return ( +// +// +// +// +// +// +// +// Change E-mail +// +// +// +// New E-mail +// +// { +// const v = (e.currentTarget as HTMLInputElement).value; +// setEmail(v); +// }} +// /> +// +// +// +// +// +// +// +// +// +// ); +// } + +function Avatar(props: { avatarUrl?: () => string | undefined }) { + const url = () => props.avatarUrl?.(); + + const AvatarImage = () => { + return ( + }> + + user avatar + + + ); + }; + + const profilePageUrl = `${window.location.origin}/_/auth/profile`; + const actionUrl = `${RECORD_API}/_user_avatar?redirect_to=${profilePageUrl}`; + + const openFileDialog = () => { + try { + const element = document.getElementById("file-input") as HTMLInputElement; + element.click(); + } catch (err) { + console.debug(err); + } + }; + + return ( +
+ {/* NOTE: user().id is a UUID rather than a b64 string. + + */} + { + const v = (e.currentTarget as HTMLInputElement).value; + if (v) { + const el = document.getElementById( + "avatar-form", + ) as HTMLFormElement; + if (el) { + el.submit(); + } + } + }} + /> + + + + {/* + + */} +
+ ); +} + +function ProfileTable(props: { + user: User; + client: Client; + avatarUrl?: () => string | undefined; +}) { + const user = () => props.user; + + return ( + +
+

User Profile

+ +
+ + + + + +
+
+ +
+ + +
+ {user().email} + +
Id: {user().id}
+
+
+ + + + {import.meta.env.DEV && ( +
+ +
+ )} +
+ ); +} + +export function Profile() { + // FIXME: This is ugly, that state management should be simpler. One option + // might be to return synchronously from tryFromCookies and call onAuthChange + // async later. + const [user, setUser] = createSignal(); + const [client] = createResource(async () => { + return Client.tryFromCookies(HOST, { + onAuthChange: (_client, user) => setUser(user), + }); + }); + + const [avatarUrl] = createResource( + client, + async (c: Client) => await c.avatarUrl(), + ); + + return ( + + Loading...}> + + {`${client.error}`} + + + + + + + + + + + Not logged in. + + + ); +} diff --git a/ui/auth/src/components/ui/button.tsx b/ui/auth/src/components/ui/button.tsx new file mode 100644 index 0000000..6282259 --- /dev/null +++ b/ui/auth/src/components/ui/button.tsx @@ -0,0 +1,52 @@ +import { type JSX, splitProps, type ValidComponent } from "solid-js" + +import * as ButtonPrimitive from "@kobalte/core/button" +import { type PolymorphicProps } from "@kobalte/core/polymorphic" +import type { VariantProps } from "class-variance-authority" +import { cva } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: "border border-input hover:bg-accent hover:text-accent-foreground", + secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline" + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "size-10" + } + }, + defaultVariants: { + variant: "default", + size: "default" + } + } +) + +type ButtonProps = ButtonPrimitive.ButtonRootProps & + VariantProps & { class?: string | undefined; children?: JSX.Element } + +const Button = ( + props: PolymorphicProps> +) => { + const [local, others] = splitProps(props as ButtonProps, ["variant", "size", "class"]) + return ( + + ) +} + +export type { ButtonProps } +export { Button, buttonVariants } diff --git a/ui/auth/src/components/ui/card.tsx b/ui/auth/src/components/ui/card.tsx new file mode 100644 index 0000000..6cfc008 --- /dev/null +++ b/ui/auth/src/components/ui/card.tsx @@ -0,0 +1,43 @@ +import type { Component, ComponentProps } from "solid-js" +import { splitProps } from "solid-js" + +import { cn } from "@/lib/utils" + +const Card: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( +
+ ) +} + +const CardHeader: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return
+} + +const CardTitle: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( +

+ ) +} + +const CardDescription: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return

+} + +const CardContent: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return

+} + +const CardFooter: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return
+} + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/ui/auth/src/components/ui/dialog.tsx b/ui/auth/src/components/ui/dialog.tsx new file mode 100644 index 0000000..18373d9 --- /dev/null +++ b/ui/auth/src/components/ui/dialog.tsx @@ -0,0 +1,141 @@ +import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js" +import { splitProps } from "solid-js" + +import * as DialogPrimitive from "@kobalte/core/dialog" +import type { PolymorphicProps } from "@kobalte/core/polymorphic" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal: Component = (props) => { + const [, rest] = splitProps(props, ["children"]) + return ( + +
+ {props.children} +
+
+ ) +} + +type DialogOverlayProps = + DialogPrimitive.DialogOverlayProps & { class?: string | undefined } + +const DialogOverlay = ( + props: PolymorphicProps> +) => { + const [, rest] = splitProps(props as DialogOverlayProps, ["class"]) + return ( + + ) +} + +type DialogContentProps = + DialogPrimitive.DialogContentProps & { + class?: string | undefined + children?: JSX.Element + } + +const DialogContent = ( + props: PolymorphicProps> +) => { + const [, rest] = splitProps(props as DialogContentProps, ["class", "children"]) + return ( + + + + {props.children} + + + + + + Close + + + + ) +} + +const DialogHeader: Component> = (props) => { + const [, rest] = splitProps(props, ["class"]) + return ( +
+ ) +} + +const DialogFooter: Component> = (props) => { + const [, rest] = splitProps(props, ["class"]) + return ( +
+ ) +} + +type DialogTitleProps = DialogPrimitive.DialogTitleProps & { + class?: string | undefined +} + +const DialogTitle = ( + props: PolymorphicProps> +) => { + const [, rest] = splitProps(props as DialogTitleProps, ["class"]) + return ( + + ) +} + +type DialogDescriptionProps = + DialogPrimitive.DialogDescriptionProps & { + class?: string | undefined + } + +const DialogDescription = ( + props: PolymorphicProps> +) => { + const [, rest] = splitProps(props as DialogDescriptionProps, ["class"]) + return ( + + ) +} + +export { + Dialog, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription +} diff --git a/ui/auth/src/components/ui/label.tsx b/ui/auth/src/components/ui/label.tsx new file mode 100644 index 0000000..afba022 --- /dev/null +++ b/ui/auth/src/components/ui/label.tsx @@ -0,0 +1,19 @@ +import type { Component, ComponentProps } from "solid-js" +import { splitProps } from "solid-js" + +import { cn } from "@/lib/utils" + +const Label: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]) + return ( +