From 2a65fe6c471aa16ded0c9eac02cc4883cc33dd38 Mon Sep 17 00:00:00 2001 From: gharbat Date: Tue, 30 May 2023 17:18:58 +0200 Subject: [PATCH] First commit --- .github/workflows/tests.yml | 34 + Makefile | 51 + README.md | 91 + backend-server/.editorconfig | 18 + backend-server/.env.example | 29 + backend-server/.gitattributes | 11 + backend-server/.gitignore | 19 + backend-server/Dockerfile | 36 + backend-server/app/Console/Kernel.php | 27 + backend-server/app/Exceptions/Handler.php | 30 + .../app/Http/Controllers/AuthController.php | 94 + .../Http/Controllers/ChatbotController.php | 181 + .../Controllers/ChatbotSettingController.php | 148 + .../app/Http/Controllers/Controller.php | 12 + .../MarketingWebsiteController.php | 23 + .../Http/Controllers/OnboardingController.php | 38 + .../Controllers/PdfDataSourceController.php | 31 + .../WebsiteDataSourceController.php | 39 + .../app/Http/Enums/ChatbotStatusType.php | 73 + .../Enums/WebsiteDataSourceStatusType.php | 80 + .../app/Http/Events/ChatbotWasCreated.php | 41 + .../app/Http/Events/PdfDataSourceWasAdded.php | 29 + .../WebsiteDataSourceCrawlingWasCompleted.php | 29 + .../Http/Events/WebsiteDataSourceWasAdded.php | 29 + .../app/Http/GetLogoFromUrlTrait.php | 38 + .../Http/Interfaces/DataSourceInterface.php | 8 + backend-server/app/Http/Kernel.php | 67 + .../CreateWebsiteDataSourceIfNeeded.php | 38 + .../Http/Listeners/IngestPdfDataSource.php | 48 + .../Listeners/IngestWebsiteDataSource.php | 47 + .../Http/Listeners/StartRecursiveCrawler.php | 225 + .../app/Http/Middleware/Authenticate.php | 17 + .../app/Http/Middleware/EncryptCookies.php | 17 + .../app/Http/Middleware/IframeMiddleware.php | 24 + .../PreventRequestsDuringMaintenance.php | 17 + .../Middleware/RedirectIfAuthenticated.php | 30 + .../app/Http/Middleware/TrimStrings.php | 19 + .../app/Http/Middleware/TrustHosts.php | 20 + .../app/Http/Middleware/TrustProxies.php | 28 + .../app/Http/Middleware/ValidateSignature.php | 22 + .../app/Http/Middleware/VerifyCsrfToken.php | 17 + .../Requests/AddWebsiteDataSourceRequest.php | 22 + .../Http/Requests/CreateChatbotRequest.php | 32 + .../CreateChatbotViaPdfFlowRequest.php | 37 + .../Http/Requests/SendChatMessageRequest.php | 27 + .../UpdateCharacterSettingsRequest.php | 29 + .../Http/Requests/UploadPdfFilesRequest.php | 18 + .../app/Http/Responses/ChatbotResponse.php | 20 + .../app/Http/Services/HandlePdfDataSource.php | 45 + backend-server/app/Models/Chatbot.php | 126 + backend-server/app/Models/ChatbotSetting.php | 73 + backend-server/app/Models/CrawledPages.php | 113 + backend-server/app/Models/PdfDataSource.php | 66 + backend-server/app/Models/User.php | 44 + .../app/Models/WebsiteDataSource.php | 112 + .../app/Providers/AppServiceProvider.php | 24 + .../app/Providers/AuthServiceProvider.php | 26 + .../Providers/BroadcastServiceProvider.php | 19 + .../app/Providers/EventServiceProvider.php | 58 + .../app/Providers/RouteServiceProvider.php | 40 + backend-server/artisan | 53 + backend-server/bootstrap/app.php | 55 + backend-server/bootstrap/cache/.gitignore | 2 + backend-server/composer.json | 72 + backend-server/composer.lock | 8483 +++++++++++++++++ backend-server/config/app.php | 189 + backend-server/config/auth.php | 115 + backend-server/config/broadcasting.php | 70 + backend-server/config/cache.php | 110 + backend-server/config/cors.php | 34 + backend-server/config/database.php | 151 + backend-server/config/filesystems.php | 67 + backend-server/config/hashing.php | 52 + backend-server/config/logging.php | 131 + backend-server/config/mail.php | 125 + backend-server/config/queue.php | 109 + backend-server/config/sanctum.php | 67 + backend-server/config/services.php | 34 + backend-server/config/session.php | 201 + backend-server/config/view.php | 36 + backend-server/database/.gitignore | 1 + .../database/factories/UserFactory.php | 38 + ...000_create_password_reset_tokens_table.php | 28 + ..._08_19_000000_create_failed_jobs_table.php | 32 + ...01_create_personal_access_tokens_table.php | 33 + ...023_05_12_110303_create_chatbots_table.php | 35 + ..._12_110323_create_chat_histories_table.php | 30 + ...2_110357_create_chatbot_settings_table.php | 30 + ...2_110416_create_onboarding_steps_table.php | 30 + ...1106_create_website_data_sources_table.php | 33 + .../2023_05_12_214227_create_jobs_table.php | 32 + ...5_14_114015_create_crawled_pages_table.php | 35 + ..._222511_create_text_data_sources_table.php | 27 + ...4_222525_create_pdf_data_sources_table.php | 30 + ...22537_create_notion_data_sources_table.php | 27 + .../database/seeders/DatabaseSeeder.php | 22 + backend-server/nginx.conf | 22 + backend-server/package.json | 13 + backend-server/phpunit.xml | 31 + backend-server/public/.DS_Store | Bin 0 -> 6148 bytes backend-server/public/.htaccess | 21 + backend-server/public/chat.css | 1 + backend-server/public/chat.js | 23 + .../css/additional-styles/flatpickr.css | 229 + .../css/additional-styles/range-slider.css | 57 + .../dashboard/css/additional-styles/theme.css | 8 + .../css/additional-styles/toggle-switch.css | 35 + .../additional-styles/utility-patterns.css | 106 + backend-server/public/dashboard/css/style.css | 22 + .../dashboard/css/vendors/flatpickr.min.css | 13 + .../dashboard/images/404-illustration.svg | 1 + .../dashboard/images/announcement-icon.svg | 34 + .../images/applications-image-01.jpg | Bin 0 -> 59710 bytes .../images/applications-image-02.jpg | Bin 0 -> 29445 bytes .../images/applications-image-03.jpg | Bin 0 -> 57434 bytes .../images/applications-image-04.jpg | Bin 0 -> 51544 bytes .../images/applications-image-05.jpg | Bin 0 -> 58573 bytes .../images/applications-image-06.jpg | Bin 0 -> 60860 bytes .../images/applications-image-07.jpg | Bin 0 -> 57854 bytes .../images/applications-image-08.jpg | Bin 0 -> 58447 bytes .../images/applications-image-09.jpg | Bin 0 -> 59618 bytes .../images/applications-image-10.jpg | Bin 0 -> 64870 bytes .../images/applications-image-11.jpg | Bin 0 -> 70792 bytes .../images/applications-image-12.jpg | Bin 0 -> 62466 bytes .../images/applications-image-13.jpg | Bin 0 -> 56496 bytes .../images/applications-image-14.jpg | Bin 0 -> 76507 bytes .../images/applications-image-15.jpg | Bin 0 -> 63711 bytes .../images/applications-image-16.jpg | Bin 0 -> 66680 bytes .../images/applications-image-17.jpg | Bin 0 -> 48229 bytes .../images/applications-image-18.jpg | Bin 0 -> 51008 bytes .../images/applications-image-19.jpg | Bin 0 -> 46303 bytes .../images/applications-image-20.jpg | Bin 0 -> 72472 bytes .../images/applications-image-21.jpg | Bin 0 -> 106132 bytes .../images/applications-image-22.jpg | Bin 0 -> 90143 bytes .../images/applications-image-23.jpg | Bin 0 -> 66079 bytes .../images/applications-image-24.jpg | Bin 0 -> 94920 bytes .../images/applications-image-25.jpg | Bin 0 -> 55487 bytes .../images/applications-image-26.jpg | Bin 0 -> 56970 bytes .../images/applications-image-27.jpg | Bin 0 -> 69399 bytes .../images/applications-image-28.jpg | Bin 0 -> 75089 bytes .../images/applications-image-29.jpg | Bin 0 -> 72317 bytes .../images/applications-image-30.jpg | Bin 0 -> 60159 bytes .../images/applications-image-31.jpg | Bin 0 -> 81051 bytes .../images/applications-image-32.jpg | Bin 0 -> 68297 bytes .../dashboard/images/auth-decoration.png | Bin 0 -> 17817 bytes .../public/dashboard/images/auth-image.jpg | Bin 0 -> 232046 bytes .../public/dashboard/images/avatar-01.jpg | Bin 0 -> 6273 bytes .../public/dashboard/images/avatar-02.jpg | Bin 0 -> 6208 bytes .../public/dashboard/images/avatar-03.jpg | Bin 0 -> 6340 bytes .../public/dashboard/images/avatar-04.jpg | Bin 0 -> 5387 bytes .../public/dashboard/images/avatar-05.jpg | Bin 0 -> 7024 bytes .../public/dashboard/images/avatar-06.jpg | Bin 0 -> 5995 bytes .../public/dashboard/images/channel-01.png | Bin 0 -> 170 bytes .../public/dashboard/images/channel-02.png | Bin 0 -> 170 bytes .../public/dashboard/images/channel-03.png | Bin 0 -> 170 bytes .../public/dashboard/images/chat-image.jpg | Bin 0 -> 64099 bytes .../public/dashboard/images/company-bg.jpg | Bin 0 -> 268979 bytes .../dashboard/images/company-icon-01.svg | 1 + .../dashboard/images/company-icon-02.svg | 1 + .../dashboard/images/company-icon-03.svg | 1 + .../dashboard/images/company-icon-04.svg | 1 + .../dashboard/images/company-icon-05.svg | 1 + .../dashboard/images/company-icon-06.svg | 1 + .../dashboard/images/company-icon-07.svg | 1 + .../dashboard/images/company-icon-08.svg | 1 + .../public/dashboard/images/favicon.png | Bin 0 -> 484933 bytes .../public/dashboard/images/feed-image-01.jpg | Bin 0 -> 176319 bytes .../public/dashboard/images/feed-image-02.jpg | Bin 0 -> 154749 bytes .../dashboard/images/group-avatar-01.png | Bin 0 -> 210 bytes .../dashboard/images/group-avatar-02.png | Bin 0 -> 277 bytes .../dashboard/images/group-avatar-03.png | Bin 0 -> 425 bytes .../dashboard/images/group-avatar-04.png | Bin 0 -> 290 bytes .../public/dashboard/images/icon-01.svg | 20 + .../public/dashboard/images/icon-02.svg | 20 + .../public/dashboard/images/icon-03.svg | 20 + .../public/dashboard/images/inbox-image.jpg | Bin 0 -> 77885 bytes .../dashboard/images/mastercard-circle.png | Bin 0 -> 235122 bytes .../public/dashboard/images/meetup-image.jpg | Bin 0 -> 252133 bytes .../dashboard/images/meetup-photo-01.jpg | Bin 0 -> 39989 bytes .../dashboard/images/meetup-photo-02.jpg | Bin 0 -> 30428 bytes .../dashboard/images/meetup-photo-03.jpg | Bin 0 -> 40822 bytes .../dashboard/images/meetups-thumb-01.jpg | Bin 0 -> 71299 bytes .../dashboard/images/meetups-thumb-02.jpg | Bin 0 -> 76519 bytes .../dashboard/images/meetups-thumb-03.jpg | Bin 0 -> 69174 bytes .../dashboard/images/meetups-thumb-04.jpg | Bin 0 -> 73251 bytes .../dashboard/images/meetups-thumb-05.jpg | Bin 0 -> 76131 bytes .../dashboard/images/meetups-thumb-06.jpg | Bin 0 -> 66755 bytes .../dashboard/images/meetups-thumb-07.jpg | Bin 0 -> 69831 bytes .../dashboard/images/meetups-thumb-08.jpg | Bin 0 -> 68127 bytes .../public/dashboard/images/modal-image.jpg | Bin 0 -> 121340 bytes .../dashboard/images/onboarding-image.jpg | Bin 0 -> 44893 bytes .../public/dashboard/images/pay-bg.jpg | Bin 0 -> 103218 bytes .../public/dashboard/images/product-image.jpg | Bin 0 -> 264358 bytes .../public/dashboard/images/profile-bg.jpg | Bin 0 -> 260914 bytes .../dashboard/images/related-product-01.jpg | Bin 0 -> 46318 bytes .../dashboard/images/related-product-02.jpg | Bin 0 -> 22205 bytes .../dashboard/images/related-product-03.jpg | Bin 0 -> 39433 bytes .../public/dashboard/images/task-image-01.jpg | Bin 0 -> 13659 bytes .../public/dashboard/images/task-image-02.jpg | Bin 0 -> 43402 bytes .../images/transactions-image-01.svg | 4 + .../images/transactions-image-02.svg | 4 + .../images/transactions-image-03.svg | 4 + .../images/transactions-image-04.svg | 4 + .../images/transactions-image-05.svg | 4 + .../images/transactions-image-06.svg | 4 + .../images/transactions-image-07.svg | 4 + .../images/transactions-image-08.svg | 4 + .../public/dashboard/images/user-128-01.jpg | Bin 0 -> 24140 bytes .../public/dashboard/images/user-28-01.jpg | Bin 0 -> 1247 bytes .../public/dashboard/images/user-28-02.jpg | Bin 0 -> 1731 bytes .../public/dashboard/images/user-28-03.jpg | Bin 0 -> 1052 bytes .../public/dashboard/images/user-28-04.jpg | Bin 0 -> 1200 bytes .../public/dashboard/images/user-28-05.jpg | Bin 0 -> 1094 bytes .../public/dashboard/images/user-28-06.jpg | Bin 0 -> 1786 bytes .../public/dashboard/images/user-28-07.jpg | Bin 0 -> 1819 bytes .../public/dashboard/images/user-28-08.jpg | Bin 0 -> 1641 bytes .../public/dashboard/images/user-28-09.jpg | Bin 0 -> 1460 bytes .../public/dashboard/images/user-28-10.jpg | Bin 0 -> 1695 bytes .../public/dashboard/images/user-28-11.jpg | Bin 0 -> 1887 bytes .../public/dashboard/images/user-28-12.jpg | Bin 0 -> 1720 bytes .../public/dashboard/images/user-32-01.jpg | Bin 0 -> 1849 bytes .../public/dashboard/images/user-32-02.jpg | Bin 0 -> 2024 bytes .../public/dashboard/images/user-32-03.jpg | Bin 0 -> 1973 bytes .../public/dashboard/images/user-32-04.jpg | Bin 0 -> 1610 bytes .../public/dashboard/images/user-32-05.jpg | Bin 0 -> 2278 bytes .../public/dashboard/images/user-32-06.jpg | Bin 0 -> 2302 bytes .../public/dashboard/images/user-32-07.jpg | Bin 0 -> 1691 bytes .../public/dashboard/images/user-32-08.jpg | Bin 0 -> 2160 bytes .../public/dashboard/images/user-36-01.jpg | Bin 0 -> 2460 bytes .../public/dashboard/images/user-36-02.jpg | Bin 0 -> 1417 bytes .../public/dashboard/images/user-36-03.jpg | Bin 0 -> 808 bytes .../public/dashboard/images/user-36-04.jpg | Bin 0 -> 2152 bytes .../public/dashboard/images/user-36-05.jpg | Bin 0 -> 1294 bytes .../public/dashboard/images/user-40-01.jpg | Bin 0 -> 1934 bytes .../public/dashboard/images/user-40-02.jpg | Bin 0 -> 2718 bytes .../public/dashboard/images/user-40-03.jpg | Bin 0 -> 2784 bytes .../public/dashboard/images/user-40-04.jpg | Bin 0 -> 3603 bytes .../public/dashboard/images/user-40-05.jpg | Bin 0 -> 1817 bytes .../public/dashboard/images/user-40-06.jpg | Bin 0 -> 1946 bytes .../public/dashboard/images/user-40-07.jpg | Bin 0 -> 1515 bytes .../public/dashboard/images/user-40-08.jpg | Bin 0 -> 2949 bytes .../public/dashboard/images/user-40-09.jpg | Bin 0 -> 3125 bytes .../public/dashboard/images/user-40-10.jpg | Bin 0 -> 2742 bytes .../public/dashboard/images/user-40-11.jpg | Bin 0 -> 2553 bytes .../public/dashboard/images/user-40-12.jpg | Bin 0 -> 2350 bytes .../public/dashboard/images/user-64-01.jpg | Bin 0 -> 6995 bytes .../public/dashboard/images/user-64-02.jpg | Bin 0 -> 6381 bytes .../public/dashboard/images/user-64-03.jpg | Bin 0 -> 7214 bytes .../public/dashboard/images/user-64-04.jpg | Bin 0 -> 6719 bytes .../public/dashboard/images/user-64-05.jpg | Bin 0 -> 5938 bytes .../public/dashboard/images/user-64-06.jpg | Bin 0 -> 6982 bytes .../public/dashboard/images/user-64-07.jpg | Bin 0 -> 6642 bytes .../public/dashboard/images/user-64-08.jpg | Bin 0 -> 5259 bytes .../public/dashboard/images/user-64-09.jpg | Bin 0 -> 6772 bytes .../public/dashboard/images/user-64-10.jpg | Bin 0 -> 6484 bytes .../public/dashboard/images/user-64-11.jpg | Bin 0 -> 7908 bytes .../public/dashboard/images/user-64-12.jpg | Bin 0 -> 6023 bytes .../public/dashboard/images/user-64-13.jpg | Bin 0 -> 5496 bytes .../public/dashboard/images/user-64-14.jpg | Bin 0 -> 6797 bytes .../dashboard/images/user-avatar-32.png | Bin 0 -> 182 bytes .../dashboard/images/user-avatar-80.png | Bin 0 -> 8019 bytes .../public/dashboard/images/visa-cricle.png | Bin 0 -> 18808 bytes .../public/dashboard/js/analytics-charts.js | 896 ++ .../public/dashboard/js/dashboard-charts.js | 889 ++ .../public/dashboard/js/fintech-charts.js | 1357 +++ .../public/dashboard/js/flatpickr-init.js | 20 + .../dashboard/js/vendors/alpinejs.min.js | 5 + .../public/dashboard/js/vendors/chart.js | 13 + .../js/vendors/chartjs-adapter-moment.js | 8 + .../public/dashboard/js/vendors/flatpickr.js | 2 + .../public/dashboard/js/vendors/moment.js | 15 + backend-server/public/dashboard/style.css | 5369 +++++++++++ backend-server/public/favicon.ico | 0 backend-server/public/index.php | 55 + backend-server/public/notification.mp3 | Bin 0 -> 6587 bytes backend-server/public/robots.txt | 2 + .../public/vendor/telescope/app-dark.css | 8 + .../public/vendor/telescope/app.css | 7 + backend-server/public/vendor/telescope/app.js | 2 + .../public/vendor/telescope/favicon.ico | Bin 0 -> 26622 bytes .../public/vendor/telescope/mix-manifest.json | 5 + backend-server/resources/css/app.css | 0 backend-server/resources/js/app.js | 1 + backend-server/resources/js/bootstrap.js | 32 + backend-server/resources/views/chat.blade.php | 306 + .../resources/views/errors/404.blade.php | 44 + .../resources/views/errors/500.blade.php | 41 + .../resources/views/index.blade.php | 131 + .../resources/views/layout/app.blade.php | 72 + .../resources/views/layout/header.blade.php | 77 + .../views/layout/sidebar-bot-page.blade.php | 68 + .../resources/views/layout/sidebar.blade.php | 264 + .../resources/views/marketing/index.blade.php | 570 ++ .../views/marketing/layout/app.blade.php | 131 + .../views/marketing/pricing.blade.php | 588 ++ .../views/marketing/privacy-policy.blade.php | 148 + .../views/marketing/signin.blade.php | 83 + .../views/marketing/signup.blade.php | 80 + .../other-data-sources-pdf.blade.php | 189 + .../other-data-sources-website.blade.php | 105 + .../views/onboarding/step-0.blade.php | 100 + .../views/onboarding/step-1.blade.php | 165 + .../views/onboarding/step-2-pdf.blade.php | 216 + .../views/onboarding/step-2.blade.php | 106 + .../views/onboarding/step-3.blade.php | 113 + .../views/onboarding/step-4.blade.php | 56 + .../views/settings-analytics.blade.php | 167 + .../resources/views/settings-data.blade.php | 583 ++ .../views/settings-integrations.blade.php | 450 + .../resources/views/settings-theme.blade.php | 176 + .../resources/views/settings.blade.php | 142 + .../widgets/data-sources-updates.blade.php | 102 + backend-server/routes/api.php | 19 + backend-server/routes/channels.php | 18 + backend-server/routes/console.php | 19 + backend-server/routes/web.php | 74 + backend-server/storage/app/.gitignore | 3 + backend-server/storage/app/public/.gitignore | 2 + backend-server/storage/framework/.gitignore | 9 + .../storage/framework/cache/.gitignore | 3 + .../storage/framework/cache/data/.gitignore | 2 + .../storage/framework/sessions/.gitignore | 2 + .../storage/framework/testing/.gitignore | 2 + .../storage/framework/views/.gitignore | 2 + backend-server/storage/logs/.gitignore | 2 + backend-server/tests/CreatesApplication.php | 21 + backend-server/tests/Feature/ExampleTest.php | 19 + backend-server/tests/TestCase.php | 10 + backend-server/tests/Unit/ExampleTest.php | 16 + backend-server/vite.config.js | 11 + common.env | 4 + docker-compose.yml | 67 + llm-server/.eslintrc.json | 3 + llm-server/.gitignore | 40 + llm-server/.prettierrc | 6 + llm-server/Dockerfile | 26 + llm-server/config/pinecone.ts | 13 + llm-server/declarations/pdf-parse.d.ts | 5 + llm-server/next.config.js | 11 + llm-server/package.json | 58 + llm-server/pages/api/chat.ts | 55 + llm-server/pages/api/ingest.ts | 77 + llm-server/postcss.config.cjs | 6 + llm-server/tailwind.config.cjs | 11 + llm-server/tsconfig.json | 29 + llm-server/types/chat.ts | 8 + llm-server/utils/cn.ts | 6 + llm-server/utils/customPDFLoader.ts | 61 + llm-server/utils/makechain.ts | 37 + llm-server/utils/pinecone-client.ts | 23 + llm-server/yarn.lock | 4540 +++++++++ 351 files changed, 33420 insertions(+) create mode 100644 .github/workflows/tests.yml create mode 100644 Makefile create mode 100644 README.md create mode 100644 backend-server/.editorconfig create mode 100644 backend-server/.env.example create mode 100644 backend-server/.gitattributes create mode 100644 backend-server/.gitignore create mode 100644 backend-server/Dockerfile create mode 100644 backend-server/app/Console/Kernel.php create mode 100644 backend-server/app/Exceptions/Handler.php create mode 100644 backend-server/app/Http/Controllers/AuthController.php create mode 100644 backend-server/app/Http/Controllers/ChatbotController.php create mode 100644 backend-server/app/Http/Controllers/ChatbotSettingController.php create mode 100644 backend-server/app/Http/Controllers/Controller.php create mode 100644 backend-server/app/Http/Controllers/MarketingWebsiteController.php create mode 100644 backend-server/app/Http/Controllers/OnboardingController.php create mode 100644 backend-server/app/Http/Controllers/PdfDataSourceController.php create mode 100644 backend-server/app/Http/Controllers/WebsiteDataSourceController.php create mode 100644 backend-server/app/Http/Enums/ChatbotStatusType.php create mode 100644 backend-server/app/Http/Enums/WebsiteDataSourceStatusType.php create mode 100644 backend-server/app/Http/Events/ChatbotWasCreated.php create mode 100644 backend-server/app/Http/Events/PdfDataSourceWasAdded.php create mode 100644 backend-server/app/Http/Events/WebsiteDataSourceCrawlingWasCompleted.php create mode 100644 backend-server/app/Http/Events/WebsiteDataSourceWasAdded.php create mode 100644 backend-server/app/Http/GetLogoFromUrlTrait.php create mode 100644 backend-server/app/Http/Interfaces/DataSourceInterface.php create mode 100644 backend-server/app/Http/Kernel.php create mode 100644 backend-server/app/Http/Listeners/CreateWebsiteDataSourceIfNeeded.php create mode 100644 backend-server/app/Http/Listeners/IngestPdfDataSource.php create mode 100644 backend-server/app/Http/Listeners/IngestWebsiteDataSource.php create mode 100644 backend-server/app/Http/Listeners/StartRecursiveCrawler.php create mode 100644 backend-server/app/Http/Middleware/Authenticate.php create mode 100644 backend-server/app/Http/Middleware/EncryptCookies.php create mode 100644 backend-server/app/Http/Middleware/IframeMiddleware.php create mode 100644 backend-server/app/Http/Middleware/PreventRequestsDuringMaintenance.php create mode 100644 backend-server/app/Http/Middleware/RedirectIfAuthenticated.php create mode 100644 backend-server/app/Http/Middleware/TrimStrings.php create mode 100644 backend-server/app/Http/Middleware/TrustHosts.php create mode 100644 backend-server/app/Http/Middleware/TrustProxies.php create mode 100644 backend-server/app/Http/Middleware/ValidateSignature.php create mode 100644 backend-server/app/Http/Middleware/VerifyCsrfToken.php create mode 100644 backend-server/app/Http/Requests/AddWebsiteDataSourceRequest.php create mode 100644 backend-server/app/Http/Requests/CreateChatbotRequest.php create mode 100644 backend-server/app/Http/Requests/CreateChatbotViaPdfFlowRequest.php create mode 100644 backend-server/app/Http/Requests/SendChatMessageRequest.php create mode 100644 backend-server/app/Http/Requests/UpdateCharacterSettingsRequest.php create mode 100644 backend-server/app/Http/Requests/UploadPdfFilesRequest.php create mode 100644 backend-server/app/Http/Responses/ChatbotResponse.php create mode 100644 backend-server/app/Http/Services/HandlePdfDataSource.php create mode 100644 backend-server/app/Models/Chatbot.php create mode 100644 backend-server/app/Models/ChatbotSetting.php create mode 100644 backend-server/app/Models/CrawledPages.php create mode 100644 backend-server/app/Models/PdfDataSource.php create mode 100644 backend-server/app/Models/User.php create mode 100644 backend-server/app/Models/WebsiteDataSource.php create mode 100644 backend-server/app/Providers/AppServiceProvider.php create mode 100644 backend-server/app/Providers/AuthServiceProvider.php create mode 100644 backend-server/app/Providers/BroadcastServiceProvider.php create mode 100644 backend-server/app/Providers/EventServiceProvider.php create mode 100644 backend-server/app/Providers/RouteServiceProvider.php create mode 100755 backend-server/artisan create mode 100644 backend-server/bootstrap/app.php create mode 100644 backend-server/bootstrap/cache/.gitignore create mode 100644 backend-server/composer.json create mode 100644 backend-server/composer.lock create mode 100644 backend-server/config/app.php create mode 100644 backend-server/config/auth.php create mode 100644 backend-server/config/broadcasting.php create mode 100644 backend-server/config/cache.php create mode 100644 backend-server/config/cors.php create mode 100644 backend-server/config/database.php create mode 100644 backend-server/config/filesystems.php create mode 100644 backend-server/config/hashing.php create mode 100644 backend-server/config/logging.php create mode 100644 backend-server/config/mail.php create mode 100644 backend-server/config/queue.php create mode 100644 backend-server/config/sanctum.php create mode 100644 backend-server/config/services.php create mode 100644 backend-server/config/session.php create mode 100644 backend-server/config/view.php create mode 100644 backend-server/database/.gitignore create mode 100644 backend-server/database/factories/UserFactory.php create mode 100644 backend-server/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php create mode 100644 backend-server/database/migrations/2019_08_19_000000_create_failed_jobs_table.php create mode 100644 backend-server/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php create mode 100644 backend-server/database/migrations/2023_05_12_110303_create_chatbots_table.php create mode 100644 backend-server/database/migrations/2023_05_12_110323_create_chat_histories_table.php create mode 100644 backend-server/database/migrations/2023_05_12_110357_create_chatbot_settings_table.php create mode 100644 backend-server/database/migrations/2023_05_12_110416_create_onboarding_steps_table.php create mode 100644 backend-server/database/migrations/2023_05_12_161106_create_website_data_sources_table.php create mode 100644 backend-server/database/migrations/2023_05_12_214227_create_jobs_table.php create mode 100644 backend-server/database/migrations/2023_05_14_114015_create_crawled_pages_table.php create mode 100644 backend-server/database/migrations/2023_05_14_222511_create_text_data_sources_table.php create mode 100644 backend-server/database/migrations/2023_05_14_222525_create_pdf_data_sources_table.php create mode 100644 backend-server/database/migrations/2023_05_14_222537_create_notion_data_sources_table.php create mode 100644 backend-server/database/seeders/DatabaseSeeder.php create mode 100644 backend-server/nginx.conf create mode 100644 backend-server/package.json create mode 100644 backend-server/phpunit.xml create mode 100644 backend-server/public/.DS_Store create mode 100644 backend-server/public/.htaccess create mode 100644 backend-server/public/chat.css create mode 100644 backend-server/public/chat.js create mode 100644 backend-server/public/dashboard/css/additional-styles/flatpickr.css create mode 100644 backend-server/public/dashboard/css/additional-styles/range-slider.css create mode 100644 backend-server/public/dashboard/css/additional-styles/theme.css create mode 100644 backend-server/public/dashboard/css/additional-styles/toggle-switch.css create mode 100644 backend-server/public/dashboard/css/additional-styles/utility-patterns.css create mode 100644 backend-server/public/dashboard/css/style.css create mode 100644 backend-server/public/dashboard/css/vendors/flatpickr.min.css create mode 100644 backend-server/public/dashboard/images/404-illustration.svg create mode 100644 backend-server/public/dashboard/images/announcement-icon.svg create mode 100644 backend-server/public/dashboard/images/applications-image-01.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-02.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-03.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-04.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-05.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-06.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-07.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-08.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-09.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-10.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-11.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-12.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-13.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-14.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-15.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-16.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-17.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-18.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-19.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-20.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-21.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-22.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-23.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-24.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-25.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-26.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-27.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-28.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-29.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-30.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-31.jpg create mode 100644 backend-server/public/dashboard/images/applications-image-32.jpg create mode 100644 backend-server/public/dashboard/images/auth-decoration.png create mode 100644 backend-server/public/dashboard/images/auth-image.jpg create mode 100644 backend-server/public/dashboard/images/avatar-01.jpg create mode 100644 backend-server/public/dashboard/images/avatar-02.jpg create mode 100644 backend-server/public/dashboard/images/avatar-03.jpg create mode 100644 backend-server/public/dashboard/images/avatar-04.jpg create mode 100644 backend-server/public/dashboard/images/avatar-05.jpg create mode 100644 backend-server/public/dashboard/images/avatar-06.jpg create mode 100644 backend-server/public/dashboard/images/channel-01.png create mode 100644 backend-server/public/dashboard/images/channel-02.png create mode 100644 backend-server/public/dashboard/images/channel-03.png create mode 100644 backend-server/public/dashboard/images/chat-image.jpg create mode 100644 backend-server/public/dashboard/images/company-bg.jpg create mode 100644 backend-server/public/dashboard/images/company-icon-01.svg create mode 100644 backend-server/public/dashboard/images/company-icon-02.svg create mode 100644 backend-server/public/dashboard/images/company-icon-03.svg create mode 100644 backend-server/public/dashboard/images/company-icon-04.svg create mode 100644 backend-server/public/dashboard/images/company-icon-05.svg create mode 100644 backend-server/public/dashboard/images/company-icon-06.svg create mode 100644 backend-server/public/dashboard/images/company-icon-07.svg create mode 100644 backend-server/public/dashboard/images/company-icon-08.svg create mode 100644 backend-server/public/dashboard/images/favicon.png create mode 100644 backend-server/public/dashboard/images/feed-image-01.jpg create mode 100644 backend-server/public/dashboard/images/feed-image-02.jpg create mode 100644 backend-server/public/dashboard/images/group-avatar-01.png create mode 100644 backend-server/public/dashboard/images/group-avatar-02.png create mode 100644 backend-server/public/dashboard/images/group-avatar-03.png create mode 100644 backend-server/public/dashboard/images/group-avatar-04.png create mode 100644 backend-server/public/dashboard/images/icon-01.svg create mode 100644 backend-server/public/dashboard/images/icon-02.svg create mode 100644 backend-server/public/dashboard/images/icon-03.svg create mode 100644 backend-server/public/dashboard/images/inbox-image.jpg create mode 100644 backend-server/public/dashboard/images/mastercard-circle.png create mode 100644 backend-server/public/dashboard/images/meetup-image.jpg create mode 100644 backend-server/public/dashboard/images/meetup-photo-01.jpg create mode 100644 backend-server/public/dashboard/images/meetup-photo-02.jpg create mode 100644 backend-server/public/dashboard/images/meetup-photo-03.jpg create mode 100644 backend-server/public/dashboard/images/meetups-thumb-01.jpg create mode 100644 backend-server/public/dashboard/images/meetups-thumb-02.jpg create mode 100644 backend-server/public/dashboard/images/meetups-thumb-03.jpg create mode 100644 backend-server/public/dashboard/images/meetups-thumb-04.jpg create mode 100644 backend-server/public/dashboard/images/meetups-thumb-05.jpg create mode 100644 backend-server/public/dashboard/images/meetups-thumb-06.jpg create mode 100644 backend-server/public/dashboard/images/meetups-thumb-07.jpg create mode 100644 backend-server/public/dashboard/images/meetups-thumb-08.jpg create mode 100644 backend-server/public/dashboard/images/modal-image.jpg create mode 100644 backend-server/public/dashboard/images/onboarding-image.jpg create mode 100644 backend-server/public/dashboard/images/pay-bg.jpg create mode 100644 backend-server/public/dashboard/images/product-image.jpg create mode 100644 backend-server/public/dashboard/images/profile-bg.jpg create mode 100644 backend-server/public/dashboard/images/related-product-01.jpg create mode 100644 backend-server/public/dashboard/images/related-product-02.jpg create mode 100644 backend-server/public/dashboard/images/related-product-03.jpg create mode 100644 backend-server/public/dashboard/images/task-image-01.jpg create mode 100644 backend-server/public/dashboard/images/task-image-02.jpg create mode 100644 backend-server/public/dashboard/images/transactions-image-01.svg create mode 100644 backend-server/public/dashboard/images/transactions-image-02.svg create mode 100644 backend-server/public/dashboard/images/transactions-image-03.svg create mode 100644 backend-server/public/dashboard/images/transactions-image-04.svg create mode 100644 backend-server/public/dashboard/images/transactions-image-05.svg create mode 100644 backend-server/public/dashboard/images/transactions-image-06.svg create mode 100644 backend-server/public/dashboard/images/transactions-image-07.svg create mode 100644 backend-server/public/dashboard/images/transactions-image-08.svg create mode 100644 backend-server/public/dashboard/images/user-128-01.jpg create mode 100644 backend-server/public/dashboard/images/user-28-01.jpg create mode 100644 backend-server/public/dashboard/images/user-28-02.jpg create mode 100644 backend-server/public/dashboard/images/user-28-03.jpg create mode 100644 backend-server/public/dashboard/images/user-28-04.jpg create mode 100644 backend-server/public/dashboard/images/user-28-05.jpg create mode 100644 backend-server/public/dashboard/images/user-28-06.jpg create mode 100644 backend-server/public/dashboard/images/user-28-07.jpg create mode 100644 backend-server/public/dashboard/images/user-28-08.jpg create mode 100644 backend-server/public/dashboard/images/user-28-09.jpg create mode 100644 backend-server/public/dashboard/images/user-28-10.jpg create mode 100644 backend-server/public/dashboard/images/user-28-11.jpg create mode 100644 backend-server/public/dashboard/images/user-28-12.jpg create mode 100644 backend-server/public/dashboard/images/user-32-01.jpg create mode 100644 backend-server/public/dashboard/images/user-32-02.jpg create mode 100644 backend-server/public/dashboard/images/user-32-03.jpg create mode 100644 backend-server/public/dashboard/images/user-32-04.jpg create mode 100644 backend-server/public/dashboard/images/user-32-05.jpg create mode 100644 backend-server/public/dashboard/images/user-32-06.jpg create mode 100644 backend-server/public/dashboard/images/user-32-07.jpg create mode 100644 backend-server/public/dashboard/images/user-32-08.jpg create mode 100644 backend-server/public/dashboard/images/user-36-01.jpg create mode 100644 backend-server/public/dashboard/images/user-36-02.jpg create mode 100644 backend-server/public/dashboard/images/user-36-03.jpg create mode 100644 backend-server/public/dashboard/images/user-36-04.jpg create mode 100644 backend-server/public/dashboard/images/user-36-05.jpg create mode 100644 backend-server/public/dashboard/images/user-40-01.jpg create mode 100644 backend-server/public/dashboard/images/user-40-02.jpg create mode 100644 backend-server/public/dashboard/images/user-40-03.jpg create mode 100644 backend-server/public/dashboard/images/user-40-04.jpg create mode 100644 backend-server/public/dashboard/images/user-40-05.jpg create mode 100644 backend-server/public/dashboard/images/user-40-06.jpg create mode 100644 backend-server/public/dashboard/images/user-40-07.jpg create mode 100644 backend-server/public/dashboard/images/user-40-08.jpg create mode 100644 backend-server/public/dashboard/images/user-40-09.jpg create mode 100644 backend-server/public/dashboard/images/user-40-10.jpg create mode 100644 backend-server/public/dashboard/images/user-40-11.jpg create mode 100644 backend-server/public/dashboard/images/user-40-12.jpg create mode 100644 backend-server/public/dashboard/images/user-64-01.jpg create mode 100644 backend-server/public/dashboard/images/user-64-02.jpg create mode 100644 backend-server/public/dashboard/images/user-64-03.jpg create mode 100644 backend-server/public/dashboard/images/user-64-04.jpg create mode 100644 backend-server/public/dashboard/images/user-64-05.jpg create mode 100644 backend-server/public/dashboard/images/user-64-06.jpg create mode 100644 backend-server/public/dashboard/images/user-64-07.jpg create mode 100644 backend-server/public/dashboard/images/user-64-08.jpg create mode 100644 backend-server/public/dashboard/images/user-64-09.jpg create mode 100644 backend-server/public/dashboard/images/user-64-10.jpg create mode 100644 backend-server/public/dashboard/images/user-64-11.jpg create mode 100644 backend-server/public/dashboard/images/user-64-12.jpg create mode 100644 backend-server/public/dashboard/images/user-64-13.jpg create mode 100644 backend-server/public/dashboard/images/user-64-14.jpg create mode 100644 backend-server/public/dashboard/images/user-avatar-32.png create mode 100644 backend-server/public/dashboard/images/user-avatar-80.png create mode 100644 backend-server/public/dashboard/images/visa-cricle.png create mode 100644 backend-server/public/dashboard/js/analytics-charts.js create mode 100644 backend-server/public/dashboard/js/dashboard-charts.js create mode 100644 backend-server/public/dashboard/js/fintech-charts.js create mode 100644 backend-server/public/dashboard/js/flatpickr-init.js create mode 100644 backend-server/public/dashboard/js/vendors/alpinejs.min.js create mode 100644 backend-server/public/dashboard/js/vendors/chart.js create mode 100644 backend-server/public/dashboard/js/vendors/chartjs-adapter-moment.js create mode 100644 backend-server/public/dashboard/js/vendors/flatpickr.js create mode 100644 backend-server/public/dashboard/js/vendors/moment.js create mode 100644 backend-server/public/dashboard/style.css create mode 100644 backend-server/public/favicon.ico create mode 100644 backend-server/public/index.php create mode 100644 backend-server/public/notification.mp3 create mode 100644 backend-server/public/robots.txt create mode 100644 backend-server/public/vendor/telescope/app-dark.css create mode 100644 backend-server/public/vendor/telescope/app.css create mode 100644 backend-server/public/vendor/telescope/app.js create mode 100644 backend-server/public/vendor/telescope/favicon.ico create mode 100644 backend-server/public/vendor/telescope/mix-manifest.json create mode 100644 backend-server/resources/css/app.css create mode 100644 backend-server/resources/js/app.js create mode 100644 backend-server/resources/js/bootstrap.js create mode 100644 backend-server/resources/views/chat.blade.php create mode 100644 backend-server/resources/views/errors/404.blade.php create mode 100644 backend-server/resources/views/errors/500.blade.php create mode 100644 backend-server/resources/views/index.blade.php create mode 100644 backend-server/resources/views/layout/app.blade.php create mode 100644 backend-server/resources/views/layout/header.blade.php create mode 100644 backend-server/resources/views/layout/sidebar-bot-page.blade.php create mode 100644 backend-server/resources/views/layout/sidebar.blade.php create mode 100644 backend-server/resources/views/marketing/index.blade.php create mode 100644 backend-server/resources/views/marketing/layout/app.blade.php create mode 100644 backend-server/resources/views/marketing/pricing.blade.php create mode 100644 backend-server/resources/views/marketing/privacy-policy.blade.php create mode 100644 backend-server/resources/views/marketing/signin.blade.php create mode 100644 backend-server/resources/views/marketing/signup.blade.php create mode 100644 backend-server/resources/views/onboarding/other-data-sources-pdf.blade.php create mode 100644 backend-server/resources/views/onboarding/other-data-sources-website.blade.php create mode 100644 backend-server/resources/views/onboarding/step-0.blade.php create mode 100644 backend-server/resources/views/onboarding/step-1.blade.php create mode 100644 backend-server/resources/views/onboarding/step-2-pdf.blade.php create mode 100644 backend-server/resources/views/onboarding/step-2.blade.php create mode 100644 backend-server/resources/views/onboarding/step-3.blade.php create mode 100644 backend-server/resources/views/onboarding/step-4.blade.php create mode 100644 backend-server/resources/views/settings-analytics.blade.php create mode 100644 backend-server/resources/views/settings-data.blade.php create mode 100644 backend-server/resources/views/settings-integrations.blade.php create mode 100644 backend-server/resources/views/settings-theme.blade.php create mode 100644 backend-server/resources/views/settings.blade.php create mode 100644 backend-server/resources/views/widgets/data-sources-updates.blade.php create mode 100644 backend-server/routes/api.php create mode 100644 backend-server/routes/channels.php create mode 100644 backend-server/routes/console.php create mode 100644 backend-server/routes/web.php create mode 100644 backend-server/storage/app/.gitignore create mode 100644 backend-server/storage/app/public/.gitignore create mode 100644 backend-server/storage/framework/.gitignore create mode 100644 backend-server/storage/framework/cache/.gitignore create mode 100644 backend-server/storage/framework/cache/data/.gitignore create mode 100644 backend-server/storage/framework/sessions/.gitignore create mode 100644 backend-server/storage/framework/testing/.gitignore create mode 100644 backend-server/storage/framework/views/.gitignore create mode 100644 backend-server/storage/logs/.gitignore create mode 100644 backend-server/tests/CreatesApplication.php create mode 100644 backend-server/tests/Feature/ExampleTest.php create mode 100644 backend-server/tests/TestCase.php create mode 100644 backend-server/tests/Unit/ExampleTest.php create mode 100644 backend-server/vite.config.js create mode 100644 common.env create mode 100644 docker-compose.yml create mode 100644 llm-server/.eslintrc.json create mode 100644 llm-server/.gitignore create mode 100644 llm-server/.prettierrc create mode 100644 llm-server/Dockerfile create mode 100644 llm-server/config/pinecone.ts create mode 100644 llm-server/declarations/pdf-parse.d.ts create mode 100644 llm-server/next.config.js create mode 100644 llm-server/package.json create mode 100644 llm-server/pages/api/chat.ts create mode 100644 llm-server/pages/api/ingest.ts create mode 100644 llm-server/postcss.config.cjs create mode 100644 llm-server/tailwind.config.cjs create mode 100644 llm-server/tsconfig.json create mode 100644 llm-server/types/chat.ts create mode 100644 llm-server/utils/cn.ts create mode 100644 llm-server/utils/customPDFLoader.ts create mode 100644 llm-server/utils/makechain.ts create mode 100644 llm-server/utils/pinecone-client.ts create mode 100644 llm-server/yarn.lock diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..459c1725 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,34 @@ +name: Backend server tests + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + + - name: Install dependencies + run: cd backend-server && composer install --prefer-dist --no-progress --no-interaction + + - name: Copy .env + run: cd backend-server && cp .env.example .env + + - name: Generate key + run: cd backend-server && php artisan key:generate + + - name: Run tests + run: cd backend-server && vendor/bin/phpunit diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..33921112 --- /dev/null +++ b/Makefile @@ -0,0 +1,51 @@ +# Variables +DOCKER_COMPOSE = docker-compose + +# Colors +COLOR_RESET = \033[0m +COLOR_BOLD = \033[1m +COLOR_GREEN = \033[32m +COLOR_YELLOW = \033[33m + +# Targets +install: + @echo "$(COLOR_BOLD)=== Putting the services down (if already running) ===$(COLOR_RESET)" + $(DOCKER_COMPOSE) down --remove-orphans + + @echo "$(COLOR_BOLD)=== Setting up Docker environment ===$(COLOR_RESET)" + # Copy .env.example to .env for backend-server + # Show warning before continue, and wait for 10 secounds + @echo "$(COLOR_BOLD)=== This will overwrite your .env files, you still have some time to abort ===$(COLOR_RESET)" + @sleep 5 + @echo "$(COLOR_BOLD)=== Copying .env files ===$(COLOR_RESET)" + cp -n backend-server/.env.example backend-server/.env 2>/dev/null || true + cp -n common.env llm-server/.env 2>/dev/null || true + $(DOCKER_COMPOSE) build #--no-cache + $(DOCKER_COMPOSE) up -d #--force-recreate + @echo "$(COLOR_BOLD)=== Waiting for services to start (~20 seconds) ===$(COLOR_RESET)" + @sleep 20 + + @echo "$(COLOR_BOLD)=== Clearing backend server config cache ===$(COLOR_RESET)" + $(DOCKER_COMPOSE) exec backend-server php artisan config:cache + + @echo "$(COLOR_BOLD)=== Run backend server server migrations ===$(COLOR_RESET)" + $(DOCKER_COMPOSE) exec backend-server php artisan migrate --seed + $(DOCKER_COMPOSE) exec backend-server php artisan storage:link + $(DOCKER_COMPOSE) run -d backend-server php artisan queue:work --timeout=200 + + @echo "$(COLOR_BOLD)=== Installation completed ===$(COLOR_RESET)" + @echo "$(COLOR_BOLD)=== 🔥🔥 You can now access the dashboard at -> http://localhost:8000 ===$(COLOR_RESET)" + @echo "$(COLOR_BOLD)=== Enjoy! ===$(COLOR_RESET)" + +run-worker: + $(DOCKER_COMPOSE) exec backend-server php artisan queue:work --timeout=200 + +db-setup: + $(DOCKER_COMPOSE) exec backend-server php artisan migrate:fresh --seed + +down: + $(DOCKER_COMPOSE) down --remove-orphans + +exec-backend-server: + $(DOCKER_COMPOSE) exec backend-server bash +.PHONY: install down diff --git a/README.md b/README.md new file mode 100644 index 00000000..cc433c7b --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ + +[![](https://dcbadge.vercel.app/api/server/Q4DxvXGw?style=flat&compact=True)](https://discord.gg/Q4DxvXGw) + +![Tests](https://github.com/openchatai/OpenChat/actions/workflows/tests.yml/badge.svg) + + + +![](https://gcdnb.pbrd.co/images/gjX4atjx9uKT.png?o=1) + +------ +# 🔥 OpenChat + +**Important disclaimer:** This is an undergoing efforts to create a free & open source chatbot console that allows you to easily create unlimited chatbots using different models for your daily use. Our main goal is to make the interface simple and user-friendly for everyone. If you find this interesting, we would greatly appreciate your support in contributing to this project. We have a highly ambitious plan that we are determined to implement! + +---- +OpenChat is an everyday user chatbot console that simplifies the utilization of large language models. With the advancements in AI, the installation and usage of these models have become overwhelming. OpenChat aims to address this challenge by providing a two-step setup process to create a comprehensive chatbot console. It serves as a central hub for managing multiple customized chatbots. + +> Currently, OpenChat supports GPT models, and we are actively working on incorporating various open-source drivers that can be activated with a single click. + + + +https://github.com/gharbat/OpenChat/assets/32633162/2f0c4587-cd93-496c-8b1b-1ed8d8c162b4 + +## Try it out: +You can try it out on OpenChat.so (we use our own OpenAI/pinecone token for the demo, please be mindful on the usage, we will clear out bots every 3 hours) + +## 🏁 Current Features + +- Create unlimited local chatbots based on GPT-3 (and GPT-4 if available). +- Customize your chatbots by providing PDF files, websites, and soon, integrations with platforms like Notion, Confluence, and Office 365. +- Each chatbot has unlimited memory capacity, enabling seamless interaction with large files such as a 400-page PDF. +- Embed chatbots as widgets on your website or internal company tools. +- And much more! + +## 🛣️ Roadmap: +- [x] Create unlimited chatbots +- [x] Share chatbots via URL +- [x] Integrate chatbots on any website using JS (as a widget on the bottom right corner) +- [x] Support GPT-3 models +- [x] Support vector database to provide chatbots with larger memory +- [x] Accept websites as a data source +- [x] Accept PDF files as a data source +- [x] Support multiple data sources per chatbot +- [ ] Support Slack integration (allow users to connect chatbots with their Slack workspaces) +- [ ] Support Intercom integration (enable users to sync chat conversations with Intercom) +- [ ] Support offline open-source models (e.g., Alpaca, LLM drivers) +- [ ] Support Confluence, Notion, Office 365, and Google Workspace +- [ ] Refactor the codebase to be API ready +- [ ] Create a new UI designer for website-embedded chatbots +- [ ] Support custom input fields for chatbots +- [ ] Support pre-defined messages with a single click + +We love hearing from you! Got any cool ideas or requests? We're all ears! So, if you have something in mind, give us a shout! + + +## 🚀 Getting Started + +- To begin, clone this Git repository: + +```bash +git clone git@github.com:openchatai/OpenChat.git +``` + +- Update common.env with your keys: +``` +OPENAI_API_KEY=# you can get it from your account in openai.com +PINECONE_API_KEY=# you can get from "API Keys" tab in pinecone +PINECONE_ENVIRONMENT=# you can get it after creating your index in pinecone +PINECONE_INDEX_NAME=# you can get it after creating your index in pinecone +``` + +- Navigate to the repository folder and run the following command: +``` +make install +``` + +Once the installation is complete, you can access the OpenChat console at: http://localhost:8000 + + + +## ❤️ Thanks: +- To ![@mayooear](https://github.com/mayooear) for his work and tutorial on chatting with PDF files, we utilized a lot of his code in the LLM server. + + + +## Disclaimer: +We quickly built this project to validate the idea, so please excuse any shortcomings in the code. You may come across several areas that require enhancements, and we truly appreciate your support by opening issues, submitting pull requests, and providing suggestions. + + +## License +This project is licensed under the MIT License. diff --git a/backend-server/.editorconfig b/backend-server/.editorconfig new file mode 100644 index 00000000..8f0de65c --- /dev/null +++ b/backend-server/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 + +[docker-compose.yml] +indent_size = 4 diff --git a/backend-server/.env.example b/backend-server/.env.example new file mode 100644 index 00000000..640f29dc --- /dev/null +++ b/backend-server/.env.example @@ -0,0 +1,29 @@ +APP_NAME=Laravel +APP_ENV=local +APP_KEY= +APP_DEBUG=true + +APP_URL=http://localhost + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DISK=local +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +QUEUE_CONNECTION=database +DB_CONNECTION=mysql + +REDIS_HOST=redis +REDIS_PASSWORD=null +REDIS_PORT=6379 + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false diff --git a/backend-server/.gitattributes b/backend-server/.gitattributes new file mode 100644 index 00000000..fcb21d39 --- /dev/null +++ b/backend-server/.gitattributes @@ -0,0 +1,11 @@ +* text=auto eol=lf + +*.blade.php diff=html +*.css diff=css +*.html diff=html +*.md diff=markdown +*.php diff=php + +/.github export-ignore +CHANGELOG.md export-ignore +.styleci.yml export-ignore diff --git a/backend-server/.gitignore b/backend-server/.gitignore new file mode 100644 index 00000000..7fe978f8 --- /dev/null +++ b/backend-server/.gitignore @@ -0,0 +1,19 @@ +/.phpunit.cache +/node_modules +/public/build +/public/hot +/public/storage +/storage/*.key +/vendor +.env +.env.backup +.env.production +.phpunit.result.cache +Homestead.json +Homestead.yaml +auth.json +npm-debug.log +yarn-error.log +/.fleet +/.idea +/.vscode diff --git a/backend-server/Dockerfile b/backend-server/Dockerfile new file mode 100644 index 00000000..0fc71a89 --- /dev/null +++ b/backend-server/Dockerfile @@ -0,0 +1,36 @@ +# Use an official PHP runtime as the base image +FROM php:8.1-cli + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + libpq-dev \ + libzip-dev \ + zip \ + unzip \ + git + +RUN docker-php-ext-install pdo pdo_mysql + +# Set the working directory +WORKDIR /var/www/html + +# Copy the project files to the container +COPY . . + +# Copy the .env file (assuming it's in the same directory as the Dockerfile) +COPY .env .env + +# Install Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Install Composer dependencies +RUN composer install --no-plugins --no-scripts + +# Generate the Laravel application key +RUN php artisan key:generate + +# Expose the container's port 8000 (default for `php artisan serve`) +EXPOSE 8000 + +# Start the Laravel development server +CMD php artisan serve --host=0.0.0.0 --port=8000 diff --git a/backend-server/app/Console/Kernel.php b/backend-server/app/Console/Kernel.php new file mode 100644 index 00000000..e6b9960e --- /dev/null +++ b/backend-server/app/Console/Kernel.php @@ -0,0 +1,27 @@ +command('inspire')->hourly(); + } + + /** + * Register the commands for the application. + */ + protected function commands(): void + { + $this->load(__DIR__.'/Commands'); + + require base_path('routes/console.php'); + } +} diff --git a/backend-server/app/Exceptions/Handler.php b/backend-server/app/Exceptions/Handler.php new file mode 100644 index 00000000..56af2640 --- /dev/null +++ b/backend-server/app/Exceptions/Handler.php @@ -0,0 +1,30 @@ + + */ + protected $dontFlash = [ + 'current_password', + 'password', + 'password_confirmation', + ]; + + /** + * Register the exception handling callbacks for the application. + */ + public function register(): void + { + $this->reportable(function (Throwable $e) { + // + }); + } +} diff --git a/backend-server/app/Http/Controllers/AuthController.php b/backend-server/app/Http/Controllers/AuthController.php new file mode 100644 index 00000000..2b81b63c --- /dev/null +++ b/backend-server/app/Http/Controllers/AuthController.php @@ -0,0 +1,94 @@ +check()) { + return redirect()->route('index'); + } + + return view('marketing.signin'); + } + + public function marketingRegister() + { + // check if the user is already logged in + if (auth()->check()) { + return redirect()->route('index'); + } + + return view('marketing.signup'); + } + + public function register(Request $request) + { + // Validate the request... + $validatedData = $request->validate(['name' => 'required|max:55', 'email' => 'email|required', 'password' => 'required']); + + // Create user + $validatedData['password'] = bcrypt($request->password); + $user = User::create($validatedData); + + // Login the user + Auth::login($user); + + // Redirect to home + return redirect()->route('onboarding.welcome'); + } + + public function login(Request $request) + { + // Validate the request... + $validatedData = $request->validate(['email' => 'email|required', 'password' => 'required']); + + // Login the user + if (Auth::attempt($validatedData)) { + return redirect()->route('index'); + } + + // Redirect to log in + return redirect()->route('marketing.login')->with('error', 'Invalid credentials'); + } + + + public function redirectToGoogle() + { + return Socialite::driver('google')->redirect(); + } + + public function handleGoogleCallback() + { + $googleUser = Socialite::driver('google')->user(); + + + // Check if the user already exists in the database + $user = User::where('email', $googleUser->getEmail())->first(); + + if (!$user) { + $this->initiateUserAccount($googleUser->getName(), $googleUser->getEmail(), null, 'google', $googleUser->getAvatar()); + } else { + auth()->login($user); + } + // Make the user data is updated as it is from Google + $user->name = $googleUser->getName(); + $user->avatar = $googleUser->getAvatar(); + $user->save(); + + return redirect()->route('index'); + } + + public function logout() + { + Auth::logout(); + return redirect()->route('marketing'); + } +} diff --git a/backend-server/app/Http/Controllers/ChatbotController.php b/backend-server/app/Http/Controllers/ChatbotController.php new file mode 100644 index 00000000..d96c1ee0 --- /dev/null +++ b/backend-server/app/Http/Controllers/ChatbotController.php @@ -0,0 +1,181 @@ + Chatbot::all(), + ]); + } + + /** + * Create a chatbot via website flow. + * + * @param \App\Http\Requests\CreateChatbotRequest $request + * @return \Illuminate\Http\RedirectResponse + */ + public function createViaWebsiteFlow(CreateChatbotRequest $request): RedirectResponse + { + // Create a new Chatbot instance + $chatbot = new Chatbot(); + + // Set the properties of the chatbot + $chatbot->setId(Uuid::uuid4()); + $chatbot->setName($request->getName()); + $chatbot->setToken(Str::random(20)); + $chatbot->setWebsite($request->getWebsite()); + $chatbot->setPromptMessage($request->getPromptMessage()); + + // Save the chatbot to the database + $chatbot->save(); + + // Trigger the ChatbotWasCreated event + event(new ChatbotWasCreated( + $chatbot->getId(), + $chatbot->getName(), + $chatbot->getWebsite(), + $chatbot->getPromptMessage(), + )); + + // Redirect to the onboarding configuration page + return redirect()->route('onboarding.config', ['id' => $chatbot->getId()->toString()]); + } + + /** + * Create a chatbot via PDF flow. + * + * @param \App\Http\Requests\CreateChatbotViaPdfFlowRequest $request + * @return \Illuminate\Http\RedirectResponse + */ + public function createViaPdfFlow(CreateChatbotViaPdfFlowRequest $request): RedirectResponse + { + // Create a new Chatbot instance + $chatbot = new Chatbot(); + + // Set the properties of the chatbot + $chatbot->setId(Uuid::uuid4()); + $chatbot->setName($request->getName()); + $chatbot->setToken(Str::random(20)); + $chatbot->setPromptMessage($request->getPromptMessage()); + + // Save the chatbot to the database + $chatbot->save(); + + // Get the PDF files from the request + $files = $request->file('pdffiles'); + + // Handle the PDF data source + $dataSource = (new HandlePdfDataSource($chatbot, $files))->handle(); // todo this should be moved to an event listener similar to the one in the previous method + + // Trigger the PdfDataSourceWasAdded event + event(new PdfDataSourceWasAdded($chatbot->getId(), $dataSource->getId())); + + // Redirect to the onboarding configuration page + return redirect()->route('onboarding.config', ['id' => $chatbot->getId()->toString()]); + } + + /** + * Update character settings for a chatbot. + * + * @param \App\Http\Requests\UpdateCharacterSettingsRequest $request + * @return \Illuminate\Http\RedirectResponse + */ + public function updateCharacterSettings(UpdateCharacterSettingsRequest $request): RedirectResponse + { + // Get the chatbot ID from the request + $chatbotId = $request->getChatbotId(); + + // Find the chatbot by ID + $chatbot = Chatbot::where('id', $chatbotId->toString())->firstOrFail(); + + // Create or update the character settings + $chatbot->crateOrUpdateSetting('character_name', $request->getCharacterName()); + + // Redirect to the onboarding done page + return redirect()->route('onboarding.done', ['id' => $chatbot->getId()->toString()]); + } + + /** + * Send a chat message to a chatbot. + * + * @param \App\Http\Requests\SendChatMessageRequest $request + * @param string $token + * @return \Illuminate\Http\JsonResponse + */ + public function sendMessage(SendChatMessageRequest $request, $token): JsonResponse + { + // Find the chatbot by token + $bot = Chatbot::where('token', $token)->firstOrFail(); + + // Get the question and history from the request + $question = $request->getMessage(); + $history = $request->getHistory(); + + // Remove null and empty values and empty arrays or objects from the history + $history = array_filter($history, function ($value) { + return !is_null($value) && $value !== '' && $value !== [] && $value !== (object) []; + }); + + // Call the API to send the message to the chatbot with a timeout of 5 seconds + $response = Http::connectTimeout(60)->post("http://llm-server:3000/api/chat", [ + 'question' => $question, + 'history' => $history, + 'namespace' => $bot->getId()->toString(), + ]); + + if ($response->failed()) { + return response()->json([ + 'error' => 'Something went wrong', + ], 500); + } + + // Create a ChatbotResponse instance from the API response + $botResponse = new ChatbotResponse($response->json()); + + // Return the response from the chatbot + return response()->json([ + 'botReply' => $botResponse->getBotReply(), + 'sources' => $botResponse->getSourceDocuments(), + ]); + } + + /** + * Display the chat view for a chatbot. + * + * @param string $token + * @return \Illuminate\View\View + */ + public function getChatView($token) + { + // Find the chatbot by token + $bot = Chatbot::where('token', $token)->firstOrFail(); + + // Render the chat view with the chatbot data + return view('chat', [ + 'bot' => $bot, + ]); + } +} diff --git a/backend-server/app/Http/Controllers/ChatbotSettingController.php b/backend-server/app/Http/Controllers/ChatbotSettingController.php new file mode 100644 index 00000000..27568fd2 --- /dev/null +++ b/backend-server/app/Http/Controllers/ChatbotSettingController.php @@ -0,0 +1,148 @@ +firstOrFail(); + + return view('settings', [ + 'bot' => $bot, + ]); + } + + /** + * Update the general settings for a chatbot. + * + * @param \Illuminate\Http\Request $request + * @param string $id + * @return \Illuminate\Http\RedirectResponse + * + * @throws \Illuminate\Validation\ValidationException + */ + public function generalSettingsUpdate(Request $request, $id) + { + // Find the chatbot by ID + $bot = Chatbot::where('id', $id)->firstOrFail(); + + // Validate the request + $this->validate($request, [ + 'name' => 'required', + ]); + + // Update the chatbot name + $bot->setName($request->input('name')); + $bot->save(); + + return redirect()->route('chatbot.settings', ['id' => $bot->getId()])->with('success', 'Settings updated!'); + } + + /** + * Display the data settings page for a chatbot. + * + * @param \Illuminate\Http\Request $request + * @param string $id + * @return \Illuminate\View\View + */ + public function dataSettings(Request $request, $id) + { + // Find the chatbot by ID + $bot = Chatbot::where('id', $id)->firstOrFail(); + + // Get website data sources and PDF data sources for the chatbot + $websiteDataSources = $bot->getWebsiteDataSources()->get(); + $pdfDataSources = $bot->getPdfFilesDataSources()->get(); + + return view('settings-data', [ + 'bot' => $bot, + 'websiteDataSources' => $websiteDataSources, + 'pdfDataSources' => $pdfDataSources, + ]); + } + + /** + * Display the analytics settings page for a chatbot. + * + * @param \Illuminate\Http\Request $request + * @param string $id + * @return \Illuminate\View\View + */ + public function analyticsSettings(Request $request, $id) + { + // Find the chatbot by ID + $bot = Chatbot::where('id', $id)->firstOrFail(); + + // Get website data sources for the chatbot + $dataSources = $bot->getWebsiteDataSources()->get(); + + return view('settings-analytics', [ + 'bot' => $bot, + 'dataSources' => $dataSources, + ]); + } + + /** + * Display the integrations settings page for a chatbot. + * + * @param \Illuminate\Http\Request $request + * @param string $id + * @return \Illuminate\View\View + */ + public function integrationsSettings(Request $request, $id) + { + // Find the chatbot by ID + $bot = Chatbot::where('id', $id)->firstOrFail(); + + return view('settings-integrations', [ + 'bot' => $bot, + ]); + } + + /** + * Display the data sources updates widget for a chatbot. + * + * @param string $id + * @return \Illuminate\View\View + */ + public function dataSourcesUpdates($id) + { + // Find the chatbot by ID + $bot = Chatbot::where('id', $id)->firstOrFail(); + + // Get website data sources for the chatbot + $dataSources = $bot->getWebsiteDataSources()->get(); + + return view('widgets.data-sources-updates', [ + 'dataSources' => $dataSources, + ]); + } + + /** + * Display the theme settings page for a chatbot. + * + * @param string $id + * @return \Illuminate\View\View + */ + public function themeSettings($id) + { + // Find the chatbot by ID + $bot = Chatbot::where('id', $id)->firstOrFail(); + + return view('settings-theme', [ + 'bot' => $bot, + ]); + } +} diff --git a/backend-server/app/Http/Controllers/Controller.php b/backend-server/app/Http/Controllers/Controller.php new file mode 100644 index 00000000..77ec359a --- /dev/null +++ b/backend-server/app/Http/Controllers/Controller.php @@ -0,0 +1,12 @@ +firstOrFail(); + $files = $request->file('pdffiles'); + $dataSource = (new HandlePdfDataSource($bot, $files))->handle(); + event(new PdfDataSourceWasAdded($bot->getId(), $dataSource->getId())); + + return redirect()->route('chatbot.settings-data', ['id' => $bot->getId()])->with('success', 'Your files have been uploaded successfully, we are training the model now, it should take around 5 minutes to reflect.'); + } + + public function show($id) + { + /** @var Chatbot $bot */ + $bot = Chatbot::where('id', $id)->firstOrFail(); + $pdfDataSources = $bot->getPdfFilesDataSources()->get(); + return view('onboarding.other-data-sources-pdf', ['bot' => $bot, 'pdfDataSources' => $pdfDataSources]); + } + +} diff --git a/backend-server/app/Http/Controllers/WebsiteDataSourceController.php b/backend-server/app/Http/Controllers/WebsiteDataSourceController.php new file mode 100644 index 00000000..865afffc --- /dev/null +++ b/backend-server/app/Http/Controllers/WebsiteDataSourceController.php @@ -0,0 +1,39 @@ +firstOrFail(); + return view('onboarding.other-data-sources-website', ['bot' => $bot]); + } + + public function create(AddWebsiteDataSourceRequest $request, $id){ + /** @var Chatbot $bot */ + $bot = Chatbot::where('id', $id)->firstOrFail(); + + $dataSource = new WebsiteDataSource(); + $dataSource->setId(Uuid::uuid4()); + $dataSource->setChatbotId($bot->getId()); + $dataSource->setRootUrl($request->getWebsite()); + $dataSource->setIcon($this->getLogo($request->getWebsite())); + $dataSource->save(); + + event(new WebsiteDataSourceWasAdded($bot->getId(), $dataSource->getId())); + + return redirect()->route('chatbot.settings-data', ['id' => $bot->getId()->toString()]); + } +} diff --git a/backend-server/app/Http/Enums/ChatbotStatusType.php b/backend-server/app/Http/Enums/ChatbotStatusType.php new file mode 100644 index 00000000..1c131d03 --- /dev/null +++ b/backend-server/app/Http/Enums/ChatbotStatusType.php @@ -0,0 +1,73 @@ + 'Draft', + self::PUBLISHED => 'Published', + self::ARCHIVED => 'Archived', + ]; + } + + public function getLabel(): string + { + return self::getLabels()[$this->getStatus()]; + } + + public static function getValues(): array + { + return array_keys(self::getLabels()); + } + + public static function isValid(string $type): bool + { + return in_array($type, self::getValues()); + } + + public function getStatus(): string + { + return $this->status; + } + + public function isDraft(): bool + { + return $this->getStatus() === self::DRAFT; + } + + public function isPublished(): bool + { + return $this->getStatus() === self::PUBLISHED; + } + + public function isArchived(): bool + { + return $this->getStatus() === self::ARCHIVED; + } + + +} diff --git a/backend-server/app/Http/Enums/WebsiteDataSourceStatusType.php b/backend-server/app/Http/Enums/WebsiteDataSourceStatusType.php new file mode 100644 index 00000000..7a169935 --- /dev/null +++ b/backend-server/app/Http/Enums/WebsiteDataSourceStatusType.php @@ -0,0 +1,80 @@ + 'Pending', + self::IN_PROGRESS => 'In Progress', + self::COMPLETED => 'Completed', + self::FAILED => 'Failed', + ]; + } + + public static function getLabels(): array + { + return [ + self::PENDING => 'Pending', + self::IN_PROGRESS => 'In Progress', + self::COMPLETED => 'Completed', + self::FAILED => 'Failed', + ]; + } + + public function getLabel(): string + { + return self::getLabels()[$this->getStatus()]; + } + + public static function getValues(): array + { + return array_keys(self::getLabels()); + } + + public static function isValid(string $type): bool + { + return in_array($type, self::getValues()); + } + + public function getStatus(): string + { + return $this->status; + } + + public function isPending(): bool + { + return $this->status === self::PENDING; + } + + public function isInProgress(): bool + { + return $this->status === self::IN_PROGRESS; + } + + public function isCompleted(): bool + { + return $this->status === self::COMPLETED; + } + + public function isFailed(): bool + { + return $this->status === self::FAILED; + } +} diff --git a/backend-server/app/Http/Events/ChatbotWasCreated.php b/backend-server/app/Http/Events/ChatbotWasCreated.php new file mode 100644 index 00000000..98d9f374 --- /dev/null +++ b/backend-server/app/Http/Events/ChatbotWasCreated.php @@ -0,0 +1,41 @@ +chatbotId; + } + + public function getChatbotName(): string + { + return $this->chatbotName; + } + + public function getChatbotWebsite(): ?string + { + return $this->chatbotWebsite; + } + + public function getChatbotPromptMessage(): string + { + return $this->chatbotPromptMessage; + } +} diff --git a/backend-server/app/Http/Events/PdfDataSourceWasAdded.php b/backend-server/app/Http/Events/PdfDataSourceWasAdded.php new file mode 100644 index 00000000..ff1865e3 --- /dev/null +++ b/backend-server/app/Http/Events/PdfDataSourceWasAdded.php @@ -0,0 +1,29 @@ +chatbotId; + } + + public function getPdfDataSourceId(): UuidInterface + { + return $this->pdfDataSourceId; + } +} diff --git a/backend-server/app/Http/Events/WebsiteDataSourceCrawlingWasCompleted.php b/backend-server/app/Http/Events/WebsiteDataSourceCrawlingWasCompleted.php new file mode 100644 index 00000000..ecb6fe03 --- /dev/null +++ b/backend-server/app/Http/Events/WebsiteDataSourceCrawlingWasCompleted.php @@ -0,0 +1,29 @@ +chatbotId; + } + + public function getWebsiteDataSourceId(): UuidInterface + { + return $this->websiteDataSourceId; + } +} diff --git a/backend-server/app/Http/Events/WebsiteDataSourceWasAdded.php b/backend-server/app/Http/Events/WebsiteDataSourceWasAdded.php new file mode 100644 index 00000000..d47b0561 --- /dev/null +++ b/backend-server/app/Http/Events/WebsiteDataSourceWasAdded.php @@ -0,0 +1,29 @@ +chatbotId; + } + + public function getWebsiteDataSourceId(): UuidInterface + { + return $this->websiteDataSourceId; + } +} diff --git a/backend-server/app/Http/GetLogoFromUrlTrait.php b/backend-server/app/Http/GetLogoFromUrlTrait.php new file mode 100644 index 00000000..6f227f11 --- /dev/null +++ b/backend-server/app/Http/GetLogoFromUrlTrait.php @@ -0,0 +1,38 @@ +get('https://logo.clearbit.com/' . $domain); + + // Check if request was successful + if ($response->getStatusCode() == 200) { + // Generate hashed name for logo file + $logoName = md5($domain) . '.png'; + + // Store logo file using Laravel's Storage + Storage::disk('public')->put($logoName, $response->getBody()); + + // Return logo file name + return $logoName; + } else { + return null; + } + } catch (Exception $e) { + return null; + } + } +} diff --git a/backend-server/app/Http/Interfaces/DataSourceInterface.php b/backend-server/app/Http/Interfaces/DataSourceInterface.php new file mode 100644 index 00000000..6d53fef4 --- /dev/null +++ b/backend-server/app/Http/Interfaces/DataSourceInterface.php @@ -0,0 +1,8 @@ + + */ + protected $middleware = [ + // \App\Http\Middleware\TrustHosts::class, + \App\Http\Middleware\TrustProxies::class, + \Illuminate\Http\Middleware\HandleCors::class, + \App\Http\Middleware\PreventRequestsDuringMaintenance::class, + \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, + \App\Http\Middleware\TrimStrings::class, + \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + ]; + + /** + * The application's route middleware groups. + * + * @var array> + */ + protected $middlewareGroups = [ + 'web' => [ + \App\Http\Middleware\EncryptCookies::class, + \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, + \Illuminate\Session\Middleware\StartSession::class, + \Illuminate\View\Middleware\ShareErrorsFromSession::class, + \App\Http\Middleware\VerifyCsrfToken::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ], + + 'api' => [ + // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, + \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ], + ]; + + /** + * The application's middleware aliases. + * + * Aliases may be used instead of class names to conveniently assign middleware to routes and groups. + * + * @var array + */ + protected $middlewareAliases = [ + 'auth' => \App\Http\Middleware\Authenticate::class, + 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, + 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class, + 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, + 'can' => \Illuminate\Auth\Middleware\Authorize::class, + 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, + 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, + 'signed' => \App\Http\Middleware\ValidateSignature::class, + 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, + 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + ]; +} diff --git a/backend-server/app/Http/Listeners/CreateWebsiteDataSourceIfNeeded.php b/backend-server/app/Http/Listeners/CreateWebsiteDataSourceIfNeeded.php new file mode 100644 index 00000000..bb67d021 --- /dev/null +++ b/backend-server/app/Http/Listeners/CreateWebsiteDataSourceIfNeeded.php @@ -0,0 +1,38 @@ +getChatbotWebsite()) { + return; + } + + $botId = $event->getChatbotId(); + + $dataSource = new WebsiteDataSource(); + $dataSource->setId(Uuid::uuid4()); + $dataSource->setChatbotId($botId); + $dataSource->setRootUrl($event->getChatbotWebsite()); + $dataSource->setIcon($this->getLogo($event->getChatbotWebsite())); + $dataSource->save(); + + + event(new WebsiteDataSourceWasAdded($botId, $dataSource->getId())); + } + +} diff --git a/backend-server/app/Http/Listeners/IngestPdfDataSource.php b/backend-server/app/Http/Listeners/IngestPdfDataSource.php new file mode 100644 index 00000000..efa89c23 --- /dev/null +++ b/backend-server/app/Http/Listeners/IngestPdfDataSource.php @@ -0,0 +1,48 @@ +getChatbotId(); + $pdfDataSourceId = $event->getPdfDataSourceId(); + + /** @var PdfDataSource $pdfDataSource */ + $pdfDataSource = PdfDataSource::where('id', $pdfDataSourceId)->firstOrFail(); + $files = $pdfDataSource->getFiles(); + + $requestBody = [ + 'type' => 'pdf', + 'shared_folder' => $pdfDataSource->getFolderName(), + 'namespace' => $botId, + ]; + + // Call to ingest service endpoint + $client = new Client(); + $response = $client->request('POST', "http://llm-server:3000/api/ingest", [ + 'json' => $requestBody, + ]); + + if ($response->getStatusCode() !== 200) { + throw new Exception('Ingest service returned an error: ' . $response->getBody()->getContents()); + } + } +} diff --git a/backend-server/app/Http/Listeners/IngestWebsiteDataSource.php b/backend-server/app/Http/Listeners/IngestWebsiteDataSource.php new file mode 100644 index 00000000..8c77ecf9 --- /dev/null +++ b/backend-server/app/Http/Listeners/IngestWebsiteDataSource.php @@ -0,0 +1,47 @@ +getChatbotId(); + $websiteDataSourceId = $event->getWebsiteDataSourceId(); + + /** @var WebsiteDataSource $websiteDataSource */ + $websiteDataSource = WebsiteDataSource::find($websiteDataSourceId); + + $requestBody = [ + 'type' => 'website', + 'shared_folder' => $websiteDataSourceId, + 'namespace' => $botId, + ]; + + // Call to ingest service endpoint + $client = new Client(); + // @todo - this is not optimal, we should use .env + $response = $client->request('POST', "http://llm-server:3000/api/ingest", ['json' => $requestBody,]); + + if ($response->getStatusCode() !== 200) { + throw new Exception('Ingest service returned an error: ' . $response->getBody()->getContents()); + } + } +} diff --git a/backend-server/app/Http/Listeners/StartRecursiveCrawler.php b/backend-server/app/Http/Listeners/StartRecursiveCrawler.php new file mode 100644 index 00000000..b684fb7f --- /dev/null +++ b/backend-server/app/Http/Listeners/StartRecursiveCrawler.php @@ -0,0 +1,225 @@ +getWebsiteDataSourceId()); + $chatbotId = $event->getChatbotId(); + + if($dataSource->getCrawlingStatus()->isCompleted()) { + return; + } + + $rootUrl = $dataSource->getRootUrl(); + $url = $rootUrl; + + // Initialize an empty array to store the crawled URLs + $crawledUrls = []; + + // Set the crawling status to "in progress" + $dataSource->setCrawlingStatus(WebsiteDataSourceStatusType::IN_PROGRESS); + $dataSource->save(); + + // Start crawling from the root URL + $this->crawl($url, $crawledUrls, 15, $rootUrl, $chatbotId, $dataSource->getId()); + + // Set the crawling status to "completed" + $dataSource->setCrawlingStatus(WebsiteDataSourceStatusType::COMPLETED); + $dataSource->save(); + + event(new WebsiteDataSourceCrawlingWasCompleted($chatbotId, $dataSource->getId())); + } + + private function storeOnLocalDesk($htmlPage, $fileName, $folderName) + { + $path = $folderName . '/' . $fileName; + Storage::disk('shared_volume')->put($path, $htmlPage); + } + + private function crawl($url, &$crawledUrls, $maxPages, $rootUrl, $chatbotId, $dataSourceId): void + { + // Check if the maximum page limit has been reached + if (count($crawledUrls) >= $maxPages) { + return; + } + + // Check if the URL has already been crawled + if (in_array($url, $crawledUrls)) { + return; + } + + // Add the current URL to the crawled URLs list + $crawledUrls[] = $url; + + try { + // Send an HTTP GET request to the URL + $client = new Client(); + $response = $client->get($url); + + // Retrieve the HTML content of the page + $html = $response->getBody(); + + // Store the crawled page content in the database + $this->storeCrawledPageContentToDatabase($url, $response, $chatbotId, $dataSourceId, $html); + + // Extract all the links from the HTML content + $links = $this->extractLinks($html, $rootUrl); + + // Recursively crawl each extracted link + foreach ($links as $link) { + // Crawl + $this->crawl($link, $crawledUrls, $maxPages, $rootUrl, $chatbotId, $dataSourceId); + + // Update crawling progress + $progress = $this->calculateCrawlingProgress(count($crawledUrls), $maxPages); + $this->updateCrawlingProgress($chatbotId, $dataSourceId, $progress); + } + } catch (Exception|GuzzleException $e) { + + } + } + + public function storeCrawledPageContentToDatabase(string $url, ResponseInterface $response, UuidInterface $chatbotId, UuidInterface $dataSourceId, ?string $html): void + { + $textPath = $dataSourceId . "/" . Str::random() . ".txt"; + $normalizedText = $this->getNormalizedContent($response->getBody()); + $this->storeOnLocalDesk($normalizedText, $textPath, $dataSourceId); + + $page = new CrawledPages(); + $page->setUrl($url); + $page->setContent($response->getBody()); + $page->setStatusCode($response->getStatusCode()); + $page->setNormalizedContent($this->getNormalizedContent($response->getBody())); + $page->setChatbotId($chatbotId); + $page->setTitle($this->getCrawledPageTitle($response->getBody())); + $page->setId(Uuid::uuid4()); + $page->setWebsiteDataSourceId($dataSourceId); + $page->save(); + } + + private function getNormalizedContent($html): string + { + // Remove inline script and style tags and their contents + $html = preg_replace('/)<[^<]*)*<\/script>/i', '', $html); + $html = preg_replace('/)<[^<]*)*<\/style>/i', '', $html); + + // Remove all HTML tags except for line break and paragraph tags + $html = strip_tags($html, '

'); + + // Replace line breaks and paragraphs with new lines + $html = preg_replace('/<(br|p)[^>]*>/i', "\n", $html); + + // Remove extra whitespace and normalize new lines + $html = preg_replace('/\s+/', ' ', $html); + $html = preg_replace('/\n\s*\n/', "\n", $html); + + // Trim leading and trailing whitespace + return trim($html); + } + + private function getCrawledPageTitle(string $html): ?string + { + $dom = new DOMDocument(); + libxml_use_internal_errors(true); // Disable error reporting for invalid HTML + $dom->loadHTML($html); + libxml_clear_errors(); + + $titleElements = $dom->getElementsByTagName('title'); + if ($titleElements->length > 0) { + $title = $titleElements->item(0)->textContent; + $title = trim($title); + + // Decode any HTML entities in the title + return html_entity_decode($title, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + } + + return null; // Return null if no title element was found + } + + private function extractLinks($html, $rootUrl): array + { + // Use regular expressions or an HTML parsing library + // to extract the URLs from the HTML content. + // Here's a simple example using regular expressions: + + $pattern = '/]*)href="([^"]*)"/i'; + preg_match_all($pattern, $html, $matches); + + // Extract the URLs from the matches + $urls = $matches[1]; + + $links = []; + + foreach ($urls as $url) { + if (str_starts_with($url, 'http')) { + // Full URL starting with "http" + $links[] = $url; + } elseif (str_starts_with($url, '/')) { + // URL starting with "/" + $parsedRoot = parse_url($rootUrl); + $rootHost = $parsedRoot['scheme'] . '://' . $parsedRoot['host']; + $links[] = $rootHost . $url; + } + } + + // Remove any duplicate URLs + $links = array_unique($links); + + // Remove any URL that does not belong to the same root URL host + return array_filter($links, function ($url) use ($rootUrl) { + $urlHost = $this->removeWwwPrefix(parse_url($url, PHP_URL_HOST)); + $rootHost = $this->removeWwwPrefix(parse_url($rootUrl, PHP_URL_HOST)); + return $urlHost === $rootHost; + }); + } + + + private function removeWwwPrefix($host): array|string|null + { + return preg_replace('/^www\./', '', $host); + } + + public function calculateCrawlingProgress($crawledPages, $maxPages) + { + if ($maxPages <= 0) { + return 0; // Avoid division by zero + } + + $progress = ($crawledPages / $maxPages) * 100; + // Cap the progress at 100% + + return min($progress, 100); + } + + public function updateCrawlingProgress($chatbotId, $dataSourceId, $progress): void + { + /** @var WebsiteDataSource $dataSource */ + $dataSource = WebsiteDataSource::find($dataSourceId); + $dataSource->setCrawlingProgress($progress); + $dataSource->save(); + } +} diff --git a/backend-server/app/Http/Middleware/Authenticate.php b/backend-server/app/Http/Middleware/Authenticate.php new file mode 100644 index 00000000..d4ef6447 --- /dev/null +++ b/backend-server/app/Http/Middleware/Authenticate.php @@ -0,0 +1,17 @@ +expectsJson() ? null : route('login'); + } +} diff --git a/backend-server/app/Http/Middleware/EncryptCookies.php b/backend-server/app/Http/Middleware/EncryptCookies.php new file mode 100644 index 00000000..867695bd --- /dev/null +++ b/backend-server/app/Http/Middleware/EncryptCookies.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/backend-server/app/Http/Middleware/IframeMiddleware.php b/backend-server/app/Http/Middleware/IframeMiddleware.php new file mode 100644 index 00000000..f083b6f9 --- /dev/null +++ b/backend-server/app/Http/Middleware/IframeMiddleware.php @@ -0,0 +1,24 @@ +headers->set('X-Frame-Options', 'ALLOW-FROM ' . implode(' ', $domains), false); + return $response; + } +} diff --git a/backend-server/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/backend-server/app/Http/Middleware/PreventRequestsDuringMaintenance.php new file mode 100644 index 00000000..74cbd9a9 --- /dev/null +++ b/backend-server/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/backend-server/app/Http/Middleware/RedirectIfAuthenticated.php b/backend-server/app/Http/Middleware/RedirectIfAuthenticated.php new file mode 100644 index 00000000..afc78c4e --- /dev/null +++ b/backend-server/app/Http/Middleware/RedirectIfAuthenticated.php @@ -0,0 +1,30 @@ +check()) { + return redirect(RouteServiceProvider::HOME); + } + } + + return $next($request); + } +} diff --git a/backend-server/app/Http/Middleware/TrimStrings.php b/backend-server/app/Http/Middleware/TrimStrings.php new file mode 100644 index 00000000..88cadcaa --- /dev/null +++ b/backend-server/app/Http/Middleware/TrimStrings.php @@ -0,0 +1,19 @@ + + */ + protected $except = [ + 'current_password', + 'password', + 'password_confirmation', + ]; +} diff --git a/backend-server/app/Http/Middleware/TrustHosts.php b/backend-server/app/Http/Middleware/TrustHosts.php new file mode 100644 index 00000000..c9c58bdd --- /dev/null +++ b/backend-server/app/Http/Middleware/TrustHosts.php @@ -0,0 +1,20 @@ + + */ + public function hosts(): array + { + return [ + $this->allSubdomainsOfApplicationUrl(), + ]; + } +} diff --git a/backend-server/app/Http/Middleware/TrustProxies.php b/backend-server/app/Http/Middleware/TrustProxies.php new file mode 100644 index 00000000..3391630e --- /dev/null +++ b/backend-server/app/Http/Middleware/TrustProxies.php @@ -0,0 +1,28 @@ +|string|null + */ + protected $proxies; + + /** + * The headers that should be used to detect proxies. + * + * @var int + */ + protected $headers = + Request::HEADER_X_FORWARDED_FOR | + Request::HEADER_X_FORWARDED_HOST | + Request::HEADER_X_FORWARDED_PORT | + Request::HEADER_X_FORWARDED_PROTO | + Request::HEADER_X_FORWARDED_AWS_ELB; +} diff --git a/backend-server/app/Http/Middleware/ValidateSignature.php b/backend-server/app/Http/Middleware/ValidateSignature.php new file mode 100644 index 00000000..093bf64a --- /dev/null +++ b/backend-server/app/Http/Middleware/ValidateSignature.php @@ -0,0 +1,22 @@ + + */ + protected $except = [ + // 'fbclid', + // 'utm_campaign', + // 'utm_content', + // 'utm_medium', + // 'utm_source', + // 'utm_term', + ]; +} diff --git a/backend-server/app/Http/Middleware/VerifyCsrfToken.php b/backend-server/app/Http/Middleware/VerifyCsrfToken.php new file mode 100644 index 00000000..9e865217 --- /dev/null +++ b/backend-server/app/Http/Middleware/VerifyCsrfToken.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/backend-server/app/Http/Requests/AddWebsiteDataSourceRequest.php b/backend-server/app/Http/Requests/AddWebsiteDataSourceRequest.php new file mode 100644 index 00000000..25398180 --- /dev/null +++ b/backend-server/app/Http/Requests/AddWebsiteDataSourceRequest.php @@ -0,0 +1,22 @@ + 'required|string|url', + ]; + } + public function getWebsite(): string + { + return $this->get('website'); + } + +} diff --git a/backend-server/app/Http/Requests/CreateChatbotRequest.php b/backend-server/app/Http/Requests/CreateChatbotRequest.php new file mode 100644 index 00000000..5d31a09e --- /dev/null +++ b/backend-server/app/Http/Requests/CreateChatbotRequest.php @@ -0,0 +1,32 @@ + 'required|string|url', + ]; + } + + public function getName(): string + { + return $this->get('name', 'My first chatbot'); + } + + public function getWebsite(): string + { + return $this->get('website'); + } + + public function getPromptMessage(): string + { + return $this->get('prompt_message', ""); + } +} diff --git a/backend-server/app/Http/Requests/CreateChatbotViaPdfFlowRequest.php b/backend-server/app/Http/Requests/CreateChatbotViaPdfFlowRequest.php new file mode 100644 index 00000000..638e7923 --- /dev/null +++ b/backend-server/app/Http/Requests/CreateChatbotViaPdfFlowRequest.php @@ -0,0 +1,37 @@ + 'required', + ]; + } + + public function getName(): string + { + return $this->get('name', 'My first chatbot'); + } + + public function getWebsite(): string + { + return $this->get('website'); + } + + public function getPromptMessage(): string + { + return $this->get('prompt_message', ""); + } + + public function getFiles() + { + return $this->get('pdffiles'); + } +} diff --git a/backend-server/app/Http/Requests/SendChatMessageRequest.php b/backend-server/app/Http/Requests/SendChatMessageRequest.php new file mode 100644 index 00000000..11a1257f --- /dev/null +++ b/backend-server/app/Http/Requests/SendChatMessageRequest.php @@ -0,0 +1,27 @@ + 'required|string', + ]; + } + + public function getMessage(): string + { + return $this->get('message'); + } + + public function getHistory(): array + { + return $this->get('history'); + } +} diff --git a/backend-server/app/Http/Requests/UpdateCharacterSettingsRequest.php b/backend-server/app/Http/Requests/UpdateCharacterSettingsRequest.php new file mode 100644 index 00000000..ddd13d0d --- /dev/null +++ b/backend-server/app/Http/Requests/UpdateCharacterSettingsRequest.php @@ -0,0 +1,29 @@ + 'nullable|string|in:knowledgeable,wise', + ]; + } + + + public function getCharacterName(): string + { + return $this->get('character_name', 'knowledgeable'); + } + + public function getChatbotId(): UuidInterface + { + return Uuid::fromString($this->route('id')); + } +} diff --git a/backend-server/app/Http/Requests/UploadPdfFilesRequest.php b/backend-server/app/Http/Requests/UploadPdfFilesRequest.php new file mode 100644 index 00000000..70a73809 --- /dev/null +++ b/backend-server/app/Http/Requests/UploadPdfFilesRequest.php @@ -0,0 +1,18 @@ + 'required', + ]; + } +} diff --git a/backend-server/app/Http/Responses/ChatbotResponse.php b/backend-server/app/Http/Responses/ChatbotResponse.php new file mode 100644 index 00000000..350e3d18 --- /dev/null +++ b/backend-server/app/Http/Responses/ChatbotResponse.php @@ -0,0 +1,20 @@ +response['text']; + } + + public function getSourceDocuments(): array + { + return $this->response['sourceDocuments']; + } +} diff --git a/backend-server/app/Http/Services/HandlePdfDataSource.php b/backend-server/app/Http/Services/HandlePdfDataSource.php new file mode 100644 index 00000000..ace21b48 --- /dev/null +++ b/backend-server/app/Http/Services/HandlePdfDataSource.php @@ -0,0 +1,45 @@ +setChatbotId($this->bot->getId()); + $dataSource->setId(Uuid::uuid4()); + + $files = $this->files; + $filesUrls = []; + $folderName = Str::random(20); + foreach ($files as $file) { + $extension = $file->getClientOriginalExtension(); + $fileName = Str::random(20) . '.' . $extension; + // random folder name + try { + $file->storeAs($folderName, $fileName, ['disk' => 'shared_volume']); + $filesUrls[] = $fileName; + } catch (\Exception $e) { + // Handle exception + } + } + + $dataSource->setFiles($filesUrls); + $dataSource->setFolderName($folderName); + + $dataSource->save(); + return $dataSource; + } +} diff --git a/backend-server/app/Models/Chatbot.php b/backend-server/app/Models/Chatbot.php new file mode 100644 index 00000000..6ed48b3a --- /dev/null +++ b/backend-server/app/Models/Chatbot.php @@ -0,0 +1,126 @@ + + */ + protected $casts = [ + 'id' => 'string', + ]; + + public function getId(): UuidInterface + { + return Uuid::fromString($this->id); + } + + public function setId(UuidInterface $id): void + { + $this->id = $id->toString(); + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function getWebsite(): string + { + return $this->website; + } + + public function setWebsite(string $website): void + { + $this->website = $website; + } + + public function getStatus(): ChatbotStatusType + { + return new ChatbotStatusType($this->status); + } + + public function setStatus(ChatbotStatusType $status): void + { + $this->status = $status->getStatus(); + } + + public function getPromptMessage(): string + { + return $this->prompt_message; + } + + public function setPromptMessage(string $promptMessage): void + { + $this->prompt_message = $promptMessage; + } + + public function setToken(string $token): void + { + $this->token = $token; + } + + public function getToken(): string + { + return $this->token; + } + + public function settings(): HasMany + { + return $this->hasMany(ChatbotSetting::class); + } + + public function crateOrUpdateSetting($name, $value): void + { + $setting = $this->settings()->where('name', $name)->first(); + if ($setting) { + $setting->value = $value; + $setting->save(); + } else { + $setting = new ChatbotSetting(); + $setting->setId(Uuid::uuid4()); + $setting->setChatbotId($this->getId()); + $setting->setName($name); + $setting->setValue($value); + $setting->save(); + } + } + + public function getSetting($name) + { + $setting = $this->settings()->where('name', $name)->first(); + if ($setting) { + return $setting->value; + } + return null; + } + + public function getWebsiteDataSources() + { + return $this->hasMany(WebsiteDataSource::class); + } + + public function getPdfFilesDataSources() + { + return $this->hasMany(PdfDataSource::class); + } +} diff --git a/backend-server/app/Models/ChatbotSetting.php b/backend-server/app/Models/ChatbotSetting.php new file mode 100644 index 00000000..59992a28 --- /dev/null +++ b/backend-server/app/Models/ChatbotSetting.php @@ -0,0 +1,73 @@ + 'string', + 'chatbot_id' => 'string', + ]; + + public function setChatbotId(UuidInterface $chatbotId): void + { + $this->chatbot_id = $chatbotId; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function setValue(string $value): void + { + $this->value = $value; + } + + public function getId(): UuidInterface + { + return $this->id; + } + + public function setId(UuidInterface $id): void + { + $this->id = $id; + } + + + public function getChatbotId(): UuidInterface + { + return $this->chatbot_id; + } + + public function getName(): string + { + return $this->name; + } + + public function getValue(): string + { + return $this->value; + } + + public function chatbot() + { + return $this->belongsTo(Chatbot::class); + } + +} diff --git a/backend-server/app/Models/CrawledPages.php b/backend-server/app/Models/CrawledPages.php new file mode 100644 index 00000000..9f3615f9 --- /dev/null +++ b/backend-server/app/Models/CrawledPages.php @@ -0,0 +1,113 @@ +id); + } + + public function getChatbotId(): UuidInterface + { + return Uuid::fromString($this->chatbot_id); + } + + public function getWebsiteDataSourceId(): UuidInterface + { + return Uuid::fromString($this->website_data_source_id); + } + + public function getUrl(): string + { + return $this->url; + } + + public function getTitle(): ?string + { + return $this->title; + } + + + public function getStatusCode(): string + { + return $this->status_code; + } + + public function getContent(): string + { + return $this->content; + } + + public function getNormalizedContent(): string + { + return $this->normalized_content; + } + + public function setId(UuidInterface $id): void + { + $this->id = $id; + } + + public function setChatbotId(UuidInterface $chatbotId): void + { + $this->chatbot_id = $chatbotId; + } + + public function setWebsiteDataSourceId(UuidInterface $websiteDataSourceId): void + { + $this->website_data_source_id = $websiteDataSourceId; + } + + public function setUrl(string $url): void + { + $this->url = $url; + } + + public function setTitle(?string $title): void + { + $this->title = $title; + } + + public function setStatusCode(?string $statusCode): void + { + $this->status_code = $statusCode; + } + + public function setContent(?string $content): void + { + $this->content = $content; + } + + public function setNormalizedContent(?string $normalizedContent): void + { + $this->normalized_content = $normalizedContent; + } + + public function getCreatedAt(): DateTimeInterface + { + return $this->created_at; + } +} diff --git a/backend-server/app/Models/PdfDataSource.php b/backend-server/app/Models/PdfDataSource.php new file mode 100644 index 00000000..7791356c --- /dev/null +++ b/backend-server/app/Models/PdfDataSource.php @@ -0,0 +1,66 @@ + 'string', + 'chatbot_id' => 'string', + 'files' => 'array', + ]; + + public function setChatbotId(UuidInterface $chatbotId): void + { + $this->chatbot_id = $chatbotId; + } + + public function getId(): UuidInterface + { + return Uuid::fromString($this->id); + } + + public function getChatbotId(): UuidInterface + { + return Uuid::fromString($this->chatbot_id); + } + + public function setId(UuidInterface $id): void + { + $this->id = $id; + } + + public function setFiles($files): void + { + $this->files = $files; + } + + public function setFolderName($folderName): void + { + $this->folder_name = $folderName; + } + + public function getFolderName(): string + { + return $this->folder_name; + } + + public function getFiles() + { + return $this->files; + } + + public function getCreatedAt(): \DateTimeInterface + { + return $this->created_at; + } +} diff --git a/backend-server/app/Models/User.php b/backend-server/app/Models/User.php new file mode 100644 index 00000000..23b40634 --- /dev/null +++ b/backend-server/app/Models/User.php @@ -0,0 +1,44 @@ + + */ + protected $fillable = [ + 'name', + 'email', + 'password', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + 'email_verified_at' => 'datetime', + ]; +} diff --git a/backend-server/app/Models/WebsiteDataSource.php b/backend-server/app/Models/WebsiteDataSource.php new file mode 100644 index 00000000..4365f274 --- /dev/null +++ b/backend-server/app/Models/WebsiteDataSource.php @@ -0,0 +1,112 @@ + 'string', + 'chatbot_id' => 'string', + 'html_files' => 'array', + ]; + + public function setChatbotId(UuidInterface $chatbotId): void + { + $this->chatbot_id = $chatbotId; + } + + public function getId(): UuidInterface + { + return Uuid::fromString($this->id); + } + + public function getChatbotId(): UuidInterface + { + return Uuid::fromString($this->chatbot_id); + } + + public function setId(UuidInterface $id): void + { + $this->id = $id; + } + + public function setRootUrl(string $rootUrl): void + { + $this->root_url = $rootUrl; + } + + public function setIcon(?string $icon): void + { + $this->icon = $icon; + } + + public function setVectorDatabasedLastIngestedAt(string $vectorDatabasedLastIngestedAt): void + { + $this->vector_databased_last_ingested_at = $vectorDatabasedLastIngestedAt; + } + + public function setCrawlingStatus(string $crawlingStatus): void + { + $this->crawling_status = $crawlingStatus; + } + + + public function getRootUrl(): string + { + return $this->root_url; + } + + public function getIcon(): ?string + { + if (is_null($this->icon)) { + return '/dashboard/images/user-40-07.jpg'; + } + return url(Storage::url($this->icon)); + } + + public function getVectorDatabasedLastIngestedAt(): string + { + return $this->vector_databased_last_ingested_at; + } + + public function getCrawlingStatus(): WebsiteDataSourceStatusType + { + return new WebsiteDataSourceStatusType($this->crawling_status); + } + + public function chatbot() + { + return $this->belongsTo(Chatbot::class); + } + + public function setCrawlingProgress(float $crawlingProgress): void + { + $this->crawling_progress = $crawlingProgress; + } + + public function getCrawlingProgress(): float + { + return $this->crawling_progress; + } + + public function getCrawledPages() + { + return $this->hasMany(CrawledPages::class, 'website_data_source_id', 'id'); + } + + public function getCreatedAt(): \DateTimeInterface + { + return $this->created_at; + } +} diff --git a/backend-server/app/Providers/AppServiceProvider.php b/backend-server/app/Providers/AppServiceProvider.php new file mode 100644 index 00000000..452e6b65 --- /dev/null +++ b/backend-server/app/Providers/AppServiceProvider.php @@ -0,0 +1,24 @@ + + */ + protected $policies = [ + // + ]; + + /** + * Register any authentication / authorization services. + */ + public function boot(): void + { + // + } +} diff --git a/backend-server/app/Providers/BroadcastServiceProvider.php b/backend-server/app/Providers/BroadcastServiceProvider.php new file mode 100644 index 00000000..2be04f5d --- /dev/null +++ b/backend-server/app/Providers/BroadcastServiceProvider.php @@ -0,0 +1,19 @@ +> + */ + protected $listen = [ + Registered::class => [ + SendEmailVerificationNotification::class, + ], + + ChatbotWasCreated::class => [ + CreateWebsiteDataSourceIfNeeded::class + ], + WebsiteDataSourceWasAdded::class => [ + StartRecursiveCrawler::class + ], + PdfDataSourceWasAdded::class => [ + IngestPdfDataSource::class + ], + WebsiteDataSourceCrawlingWasCompleted::class => [ + IngestWebsiteDataSource::class + ] + ]; + + /** + * Register any events for your application. + */ + public function boot(): void + { + // + } + + /** + * Determine if events and listeners should be automatically discovered. + */ + public function shouldDiscoverEvents(): bool + { + return false; + } +} diff --git a/backend-server/app/Providers/RouteServiceProvider.php b/backend-server/app/Providers/RouteServiceProvider.php new file mode 100644 index 00000000..1cf5f15c --- /dev/null +++ b/backend-server/app/Providers/RouteServiceProvider.php @@ -0,0 +1,40 @@ +by($request->user()?->id ?: $request->ip()); + }); + + $this->routes(function () { + Route::middleware('api') + ->prefix('api') + ->group(base_path('routes/api.php')); + + Route::middleware('web') + ->group(base_path('routes/web.php')); + }); + } +} diff --git a/backend-server/artisan b/backend-server/artisan new file mode 100755 index 00000000..67a3329b --- /dev/null +++ b/backend-server/artisan @@ -0,0 +1,53 @@ +#!/usr/bin/env php +make(Illuminate\Contracts\Console\Kernel::class); + +$status = $kernel->handle( + $input = new Symfony\Component\Console\Input\ArgvInput, + new Symfony\Component\Console\Output\ConsoleOutput +); + +/* +|-------------------------------------------------------------------------- +| Shutdown The Application +|-------------------------------------------------------------------------- +| +| Once Artisan has finished running, we will fire off the shutdown events +| so that any final work may be done by the application before we shut +| down the process. This is the last thing to happen to the request. +| +*/ + +$kernel->terminate($input, $status); + +exit($status); diff --git a/backend-server/bootstrap/app.php b/backend-server/bootstrap/app.php new file mode 100644 index 00000000..037e17df --- /dev/null +++ b/backend-server/bootstrap/app.php @@ -0,0 +1,55 @@ +singleton( + Illuminate\Contracts\Http\Kernel::class, + App\Http\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Console\Kernel::class, + App\Console\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Debug\ExceptionHandler::class, + App\Exceptions\Handler::class +); + +/* +|-------------------------------------------------------------------------- +| Return The Application +|-------------------------------------------------------------------------- +| +| This script returns the application instance. The instance is given to +| the calling script so we can separate the building of the instances +| from the actual running of the application and sending responses. +| +*/ + +return $app; diff --git a/backend-server/bootstrap/cache/.gitignore b/backend-server/bootstrap/cache/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/backend-server/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/backend-server/composer.json b/backend-server/composer.json new file mode 100644 index 00000000..1e2b6dd6 --- /dev/null +++ b/backend-server/composer.json @@ -0,0 +1,72 @@ +{ + "name": "laravel/laravel", + "type": "project", + "description": "The Laravel Framework.", + "keywords": ["framework", "laravel"], + "license": "MIT", + "require": { + "php": "^8.1", + "ext-dom": "*", + "ext-libxml": "*", + "aws/aws-sdk-php-laravel": "^3.8", + "fiveam-code/laravel-notion-api": "^1.0", + "guzzlehttp/guzzle": "^7.2", + "laravel/framework": "^10.8", + "laravel/sanctum": "^3.2", + "laravel/socialite": "^5.6", + "laravel/telescope": "^4.14", + "laravel/tinker": "^2.8" + }, + "require-dev": { + "fakerphp/faker": "^1.9.1", + "laravel/pint": "^1.0", + "laravel/sail": "^1.18", + "mockery/mockery": "^1.4.4", + "nunomaduro/collision": "^7.0", + "phpunit/phpunit": "^10.1", + "spatie/laravel-ignition": "^2.0" + }, + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Factories\\": "database/factories/", + "Database\\Seeders\\": "database/seeders/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, + "scripts": { + "post-autoload-dump": [ + "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", + "@php artisan package:discover --ansi" + ], + "post-update-cmd": [ + "@php artisan vendor:publish --tag=laravel-assets --ansi --force" + ], + "post-root-package-install": [ + "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" + ], + "post-create-project-cmd": [ + "@php artisan key:generate --ansi" + ] + }, + "extra": { + "laravel": { + "dont-discover": [] + } + }, + "config": { + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true, + "allow-plugins": { + "pestphp/pest-plugin": true, + "php-http/discovery": true + } + }, + "minimum-stability": "stable", + "prefer-stable": true +} diff --git a/backend-server/composer.lock b/backend-server/composer.lock new file mode 100644 index 00000000..e98db0f1 --- /dev/null +++ b/backend-server/composer.lock @@ -0,0 +1,8483 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "022a9eaeec285398cdcbd69cde0a3eb1", + "packages": [ + { + "name": "aws/aws-crt-php", + "version": "v1.2.1", + "source": { + "type": "git", + "url": "https://github.com/awslabs/aws-crt-php.git", + "reference": "1926277fc71d253dfa820271ac5987bdb193ccf5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/1926277fc71d253dfa820271ac5987bdb193ccf5", + "reference": "1926277fc71d253dfa820271ac5987bdb193ccf5", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality." + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "AWS SDK Common Runtime Team", + "email": "aws-sdk-common-runtime@amazon.com" + } + ], + "description": "AWS Common Runtime for PHP", + "homepage": "https://github.com/awslabs/aws-crt-php", + "keywords": [ + "amazon", + "aws", + "crt", + "sdk" + ], + "support": { + "issues": "https://github.com/awslabs/aws-crt-php/issues", + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.1" + }, + "time": "2023-03-24T20:22:19+00:00" + }, + { + "name": "aws/aws-sdk-php", + "version": "3.269.0", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78", + "reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78", + "shasum": "" + }, + "require": { + "aws/aws-crt-php": "^1.0.4", + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", + "guzzlehttp/promises": "^1.4.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "mtdowling/jmespath.php": "^2.6", + "php": ">=5.5" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "composer/composer": "^1.10.22", + "dms/phpunit-arraysubset-asserts": "^0.4.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "paragonie/random_compat": ">= 2", + "phpunit/phpunit": "^4.8.35 || ^5.6.3 || ^9.5", + "psr/cache": "^1.0", + "psr/http-message": "^1.0", + "psr/simple-cache": "^1.0", + "sebastian/comparator": "^1.2.3 || ^4.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Aws\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "support": { + "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "issues": "https://github.com/aws/aws-sdk-php/issues", + "source": "https://github.com/aws/aws-sdk-php/tree/3.269.0" + }, + "time": "2023-04-26T18:21:04+00:00" + }, + { + "name": "aws/aws-sdk-php-laravel", + "version": "3.8.1", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php-laravel.git", + "reference": "fdecc2c8c15b3bf3843401b257229c7f883d6bab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php-laravel/zipball/fdecc2c8c15b3bf3843401b257229c7f883d6bab", + "reference": "fdecc2c8c15b3bf3843401b257229c7f883d6bab", + "shasum": "" + }, + "require": { + "aws/aws-sdk-php": "~3.0", + "illuminate/support": "^5.1 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0", + "php": ">=5.5.9" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^9.0", + "vlucas/phpdotenv": "^1.0 || ^2.0 || ^3.0 || ^4.0 || ^5.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "laravel/framework": "To test the Laravel bindings", + "laravel/lumen-framework": "To test the Lumen bindings" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Aws\\Laravel\\AwsServiceProvider" + ], + "aliases": { + "AWS": "Aws\\Laravel\\AwsFacade" + } + } + }, + "autoload": { + "psr-4": { + "Aws\\Laravel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "A simple Laravel 5/6/7/8/9 service provider for including the AWS SDK for PHP.", + "homepage": "http://aws.amazon.com/sdkforphp2", + "keywords": [ + "amazon", + "aws", + "dynamodb", + "ec2", + "laravel", + "laravel 10", + "laravel 5", + "laravel 6", + "laravel 7", + "laravel 8", + "laravel 9", + "s3", + "sdk" + ], + "support": { + "issues": "https://github.com/aws/aws-sdk-php-laravel/issues", + "source": "https://github.com/aws/aws-sdk-php-laravel/tree/3.8.1" + }, + "time": "2023-03-24T20:26:35+00:00" + }, + { + "name": "brick/math", + "version": "0.11.0", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478", + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^9.0", + "vimeo/psalm": "5.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "brick", + "math" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.11.0" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2023-01-15T23:15:59+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "f41715465d65213d644d3141a6a93081be5d3549" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549", + "reference": "f41715465d65213d644d3141a6a93081be5d3549", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2" + }, + "time": "2022-10-27T11:44:00+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", + "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.6" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2022-10-20T09:10:12+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "84a527db05647743d50373e0ec53a152f2cde568" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568", + "reference": "84a527db05647743d50373e0ec53a152f2cde568", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-12-15T16:57:16+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.3.2", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8", + "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-webmozart-assert": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2022-09-10T18:51:20+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/3a85486b709bc384dae8eb78fb2eec649bdb64ff", + "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^4.30" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2023-01-14T14:17:03+00:00" + }, + { + "name": "fiveam-code/laravel-notion-api", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/5am-code/laravel-notion-api.git", + "reference": "4d5e55661c774ccfdedd4d7d55438d7889bfccd9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/5am-code/laravel-notion-api/zipball/4d5e55661c774ccfdedd4d7d55438d7889bfccd9", + "reference": "4d5e55661c774ccfdedd4d7d55438d7889bfccd9", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^7.0.1", + "illuminate/support": "^8.0|^9.0|^10.0", + "php": "^8.0" + }, + "require-dev": { + "orchestra/testbench": "^6.0|^8.0", + "pestphp/pest": "^1.22", + "pestphp/pest-plugin-laravel": "^1.3", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "FiveamCode\\LaravelNotionApi\\LaravelNotionApiServiceProvider" + ], + "aliases": { + "Notion": "FiveamCode\\LaravelNotionApi\\NotionFacade" + } + } + }, + "autoload": { + "psr-4": { + "FiveamCode\\LaravelNotionApi\\": "src", + "FiveamCode\\LaravelNotionApi\\Endpoints\\": "src/Endpoints", + "FiveamCode\\LaravelNotionApi\\Exceptions\\": "src/Exceptions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Diana Scharf", + "email": "hello@dianaweb.dev", + "role": "Developer" + }, + { + "name": "Johannes Güntner", + "email": "johannes.guentner@it-guentner.de", + "role": "Developer" + } + ], + "description": "Laravel Wrapper for the Notion API", + "homepage": "https://github.com/fiveam-code/laravel-notion-api", + "keywords": [ + "api-wrapper", + "fiveam-code", + "laravel", + "laravel-notion-api", + "notion", + "notion-api" + ], + "support": { + "issues": "https://github.com/5am-code/laravel-notion-api/issues", + "source": "https://github.com/5am-code/laravel-notion-api/tree/v1.0.1" + }, + "funding": [ + { + "url": "https://www.patreon.com/5amcode", + "type": "patreon" + } + ], + "time": "2023-04-21T03:39:06+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/58571acbaa5f9f462c9c77e911700ac66f446d4e", + "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2022-02-20T15:07:15+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", + "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2023-02-25T20:23:15+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.5.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b964ca597e86b752cd994f27293e9fa6b6a95ed9", + "reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "7.5-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.5.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-04-17T16:30:08+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.5.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "b94b2807d85443f9719887892882d0329d1e2598" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", + "reference": "b94b2807d85443f9719887892882d0329d1e2598", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.5.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2022-08-28T14:55:35+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.5.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "b635f279edd83fc275f822a1188157ffea568ff6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", + "reference": "b635f279edd83fc275f822a1188157ffea568ff6", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.5.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-04-17T16:11:26+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/b945d74a55a25a949158444f09ec0d3c120d69e2", + "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.17" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.19 || ^9.5.8", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2021-10-07T12:57:01+00:00" + }, + { + "name": "laravel/framework", + "version": "v10.10.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "0da22a8d179f79b49d4e71f4822f759651f35012" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/0da22a8d179f79b49d4e71f4822f759651f35012", + "reference": "0da22a8d179f79b49d4e71f4822f759651f35012", + "shasum": "" + }, + "require": { + "brick/math": "^0.9.3|^0.10.2|^0.11", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.3.2", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/serializable-closure": "^1.3", + "league/commonmark": "^2.2.1", + "league/flysystem": "^3.8.0", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^2.62.1", + "nunomaduro/termwind": "^1.13", + "php": "^8.1", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^6.2", + "symfony/error-handler": "^6.2", + "symfony/finder": "^6.2", + "symfony/http-foundation": "^6.2", + "symfony/http-kernel": "^6.2", + "symfony/mailer": "^6.2", + "symfony/mime": "^6.2", + "symfony/process": "^6.2", + "symfony/routing": "^6.2", + "symfony/uid": "^6.2", + "symfony/var-dumper": "^6.2", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.4.1", + "voku/portable-ascii": "^2.0" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.235.5", + "doctrine/dbal": "^3.5.1", + "ext-gmp": "*", + "fakerphp/faker": "^1.21", + "guzzlehttp/guzzle": "^7.5", + "league/flysystem-aws-s3-v3": "^3.0", + "league/flysystem-ftp": "^3.0", + "league/flysystem-path-prefixing": "^3.3", + "league/flysystem-read-only": "^3.3", + "league/flysystem-sftp-v3": "^3.0", + "mockery/mockery": "^1.5.1", + "orchestra/testbench-core": "^8.4", + "pda/pheanstalk": "^4.0", + "phpstan/phpdoc-parser": "^1.15", + "phpstan/phpstan": "^1.4.7", + "phpunit/phpunit": "^10.0.7", + "predis/predis": "^2.0.2", + "symfony/cache": "^6.2", + "symfony/http-client": "^6.2.4" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", + "brianium/paratest": "Required to run tests in parallel (^6.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^3.5.1).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "guzzlehttp/guzzle": "Required to use the HTTP Client and the ping methods on schedules (^7.5).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", + "league/flysystem-read-only": "Required to use read-only disks (^3.3)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", + "mockery/mockery": "Required to use mocking (^1.5.1).", + "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", + "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8|^10.0.7).", + "predis/predis": "Required to use the predis connector (^2.0.2).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^6.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^6.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-05-09T13:08:05+00:00" + }, + { + "name": "laravel/sanctum", + "version": "v3.2.5", + "source": { + "type": "git", + "url": "https://github.com/laravel/sanctum.git", + "reference": "8ebda85d59d3c414863a7f4d816ef8302faad876" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/8ebda85d59d3c414863a7f4d816ef8302faad876", + "reference": "8ebda85d59d3c414863a7f4d816ef8302faad876", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^9.21|^10.0", + "illuminate/contracts": "^9.21|^10.0", + "illuminate/database": "^9.21|^10.0", + "illuminate/support": "^9.21|^10.0", + "php": "^8.0.2" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^7.0|^8.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Sanctum\\SanctumServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sanctum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", + "keywords": [ + "auth", + "laravel", + "sanctum" + ], + "support": { + "issues": "https://github.com/laravel/sanctum/issues", + "source": "https://github.com/laravel/sanctum" + }, + "time": "2023-05-01T19:39:51+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "f23fe9d4e95255dacee1bf3525e0810d1a1b0f37" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f23fe9d4e95255dacee1bf3525e0810d1a1b0f37", + "reference": "f23fe9d4e95255dacee1bf3525e0810d1a1b0f37", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "nesbot/carbon": "^2.61", + "pestphp/pest": "^1.21.3", + "phpstan/phpstan": "^1.8.2", + "symfony/var-dumper": "^5.4.11" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2023-01-30T18:31:20+00:00" + }, + { + "name": "laravel/socialite", + "version": "v5.6.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/socialite.git", + "reference": "a14a177f2cc71d8add71e2b19e00800e83bdda09" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/socialite/zipball/a14a177f2cc71d8add71e2b19e00800e83bdda09", + "reference": "a14a177f2cc71d8add71e2b19e00800e83bdda09", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0", + "league/oauth1-client": "^1.10.1", + "php": "^7.2|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0", + "phpunit/phpunit": "^8.0|^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Socialite\\SocialiteServiceProvider" + ], + "aliases": { + "Socialite": "Laravel\\Socialite\\Facades\\Socialite" + } + } + }, + "autoload": { + "psr-4": { + "Laravel\\Socialite\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", + "homepage": "https://laravel.com", + "keywords": [ + "laravel", + "oauth" + ], + "support": { + "issues": "https://github.com/laravel/socialite/issues", + "source": "https://github.com/laravel/socialite" + }, + "time": "2023-01-20T15:42:35+00:00" + }, + { + "name": "laravel/telescope", + "version": "v4.14.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/telescope.git", + "reference": "222bbea975d9f3a10879af153db5c34ffac08034" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/telescope/zipball/222bbea975d9f3a10879af153db5c34ffac08034", + "reference": "222bbea975d9f3a10879af153db5c34ffac08034", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel/framework": "^8.37|^9.0|^10.0", + "php": "^8.0", + "symfony/var-dumper": "^5.0|^6.0" + }, + "require-dev": { + "ext-gd": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "laravel/octane": "^1.4", + "orchestra/testbench": "^6.0|^7.0|^8.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Telescope\\TelescopeServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Telescope\\": "src/", + "Laravel\\Telescope\\Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mohamed Said", + "email": "mohamed@laravel.com" + } + ], + "description": "An elegant debug assistant for the Laravel framework.", + "keywords": [ + "debugging", + "laravel", + "monitoring" + ], + "support": { + "issues": "https://github.com/laravel/telescope/issues", + "source": "https://github.com/laravel/telescope/tree/v4.14.2" + }, + "time": "2023-04-19T15:24:14+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.8.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "04a2d3bd0d650c0764f70bf49d1ee39393e4eb10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/04a2d3bd0d650c0764f70bf49d1ee39393e4eb10", + "reference": "04a2d3bd0d650c0764f70bf49d1ee39393e4eb10", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.10.4|^0.11.1", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpunit/phpunit": "^8.5.8|^9.3.3" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.8.1" + }, + "time": "2023-02-15T16:40:09+00:00" + }, + { + "name": "league/commonmark", + "version": "2.4.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d44a24690f16b8c1808bf13b1bd54ae4c63ea048", + "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.30.0", + "commonmark/commonmark.js": "0.30.0", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2023-03-24T15:16:10+00:00" + }, + { + "name": "league/config", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2022-12-11T20:36:23+00:00" + }, + { + "name": "league/flysystem", + "version": "3.15.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "a141d430414fcb8bf797a18716b09f759a385bed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a141d430414fcb8bf797a18716b09f759a385bed", + "reference": "a141d430414fcb8bf797a18716b09f759a385bed", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5", + "async-aws/simple-s3": "^1.1", + "aws/aws-sdk-php": "^3.220.0", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "microsoft/azure-storage-blob": "^1.1", + "phpseclib/phpseclib": "^3.0.14", + "phpstan/phpstan": "^0.12.26", + "phpunit/phpunit": "^9.5.11", + "sabre/dav": "^4.3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.15.1" + }, + "funding": [ + { + "url": "https://ecologi.com/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" + } + ], + "time": "2023-05-04T09:04:26+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.15.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "543f64c397fefdf9cfeac443ffb6beff602796b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/543f64c397fefdf9cfeac443ffb6beff602796b3", + "reference": "543f64c397fefdf9cfeac443ffb6beff602796b3", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem-local/issues", + "source": "https://github.com/thephpleague/flysystem-local/tree/3.15.0" + }, + "funding": [ + { + "url": "https://ecologi.com/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" + } + ], + "time": "2023-05-02T20:02:14+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd", + "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2022-04-17T13:12:02+00:00" + }, + { + "name": "league/oauth1-client", + "version": "v1.10.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth1-client.git", + "reference": "d6365b901b5c287dd41f143033315e2f777e1167" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/d6365b901b5c287dd41f143033315e2f777e1167", + "reference": "d6365b901b5c287dd41f143033315e2f777e1167", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-openssl": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "guzzlehttp/psr7": "^1.7|^2.0", + "php": ">=7.1||>=8.0" + }, + "require-dev": { + "ext-simplexml": "*", + "friendsofphp/php-cs-fixer": "^2.17", + "mockery/mockery": "^1.3.3", + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5||9.5" + }, + "suggest": { + "ext-simplexml": "For decoding XML-based responses." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev", + "dev-develop": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth1\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Corlett", + "email": "bencorlett@me.com", + "homepage": "http://www.webcomm.com.au", + "role": "Developer" + } + ], + "description": "OAuth 1.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "bitbucket", + "identity", + "idp", + "oauth", + "oauth1", + "single sign on", + "trello", + "tumblr", + "twitter" + ], + "support": { + "issues": "https://github.com/thephpleague/oauth1-client/issues", + "source": "https://github.com/thephpleague/oauth1-client/tree/v1.10.1" + }, + "time": "2022-04-15T14:02:14+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.3.1", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "9b5daeaffce5b926cac47923798bba91059e60e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/9b5daeaffce5b926cac47923798bba91059e60e2", + "reference": "9b5daeaffce5b926cac47923798bba91059e60e2", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.4", + "phpunit/phpunit": "^9.5.26", + "predis/predis": "^1.1 || ^2", + "ruflin/elastica": "^7", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.3.1" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2023-02-06T13:46:10+00:00" + }, + { + "name": "mtdowling/jmespath.php", + "version": "2.6.1", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/9b87907a81b87bc76d19a7fb2d61e61486ee9edb", + "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^7.5.15" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "files": [ + "src/JmesPath.php" + ], + "psr-4": { + "JmesPath\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.6.1" + }, + "time": "2021-06-14T00:11:39+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.66.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "496712849902241f04902033b0441b269effe001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/496712849902241f04902033b0441b269effe001", + "reference": "496712849902241f04902033b0441b269effe001", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "doctrine/dbal": "^2.0 || ^3.1.4", + "doctrine/orm": "^2.7", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "*", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.x-dev", + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2023-01-29T18:53:47+00:00" + }, + { + "name": "nette/schema", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/abbdbb70e0245d5f3bf77874cea1dfb0c930d06f", + "reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f", + "shasum": "" + }, + "require": { + "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", + "php": ">=7.1 <8.3" + }, + "require-dev": { + "nette/tester": "^2.3 || ^2.4", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.2.3" + }, + "time": "2022-10-13T01:24:26+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "cacdbf5a91a657ede665c541eda28941d4b09c1e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/cacdbf5a91a657ede665c541eda28941d4b09c1e", + "reference": "cacdbf5a91a657ede665c541eda28941d4b09c1e", + "shasum": "" + }, + "require": { + "php": ">=8.0 <8.3" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "dev-master", + "nette/tester": "^2.4", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.0" + }, + "time": "2023-02-02T10:41:53+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.15.4", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" + }, + "time": "2023-03-05T19:49:14+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v1.15.1", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "8ab0b32c8caa4a2e09700ea32925441385e4a5dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/8ab0b32c8caa4a2e09700ea32925441385e4a5dc", + "reference": "8ab0b32c8caa4a2e09700ea32925441385e4a5dc", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.0", + "symfony/console": "^5.3.0|^6.0.0" + }, + "require-dev": { + "ergebnis/phpstan-rules": "^1.0.", + "illuminate/console": "^8.0|^9.0", + "illuminate/support": "^8.0|^9.0", + "laravel/pint": "^1.0.0", + "pestphp/pest": "^1.21.0", + "pestphp/pest-plugin-mock": "^1.0", + "phpstan/phpstan": "^1.4.6", + "phpstan/phpstan-strict-rules": "^1.1.0", + "symfony/var-dumper": "^5.2.7|^6.0.0", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v1.15.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2023-02-08T01:06:31+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2023-02-25T19:38:58+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/1.0.2" + }, + "time": "2023-04-10T20:12:12+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + }, + "time": "2023-04-10T20:10:41+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.11.17", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "3dc5d4018dabd80bceb8fe1e3191ba8460569f0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/3dc5d4018dabd80bceb8fe1e3191ba8460569f0a", + "reference": "3dc5d4018dabd80bceb8fe1e3191ba8460569f0a", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^4.0 || ^3.1", + "php": "^8.0 || ^7.0.8", + "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.11.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.11.17" + }, + "time": "2023-05-05T20:02:42+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2022-12-31T21:50:55+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.4", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "60a4c63ab724854332900504274f6150ff26d286" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/60a4c63ab724854332900504274f6150ff26d286", + "reference": "60a4c63ab724854332900504274f6150ff26d286", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.7.4" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2023-04-15T23:01:58+00:00" + }, + { + "name": "symfony/console", + "version": "v6.2.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "12288d9f4500f84a4d02254d4aa968b15488476f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/12288d9f4500f84a4d02254d4aa968b15488476f", + "reference": "12288d9f4500f84a4d02254d4aa968b15488476f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.2.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-04-28T13:37:43+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v6.2.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "aedf3cb0f5b929ec255d96bbb4909e9932c769e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/aedf3cb0f5b929ec255d96bbb4909e9932c769e0", + "reference": "aedf3cb0f5b929ec255d96bbb4909e9932c769e0", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v6.2.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-14T08:44:56+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-01T10:25:55+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v6.2.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "8b7e9f124640cb0611624a9383176c3e5f7d8cfb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/8b7e9f124640cb0611624a9383176c3e5f7d8cfb", + "reference": "8b7e9f124640cb0611624a9383176c3e5f7d8cfb", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^5.4|^6.0" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v6.2.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-04-18T13:46:08+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v6.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "04046f35fd7d72f9646e721fc2ecb8f9c67d3339" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/04046f35fd7d72f9646e721fc2ecb8f9c67d3339", + "reference": "04046f35fd7d72f9646e721fc2ecb8f9c67d3339", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2|^3" + }, + "conflict": { + "symfony/dependency-injection": "<5.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^5.4|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v6.2.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-20T16:06:02+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "0ad3b6f1e4e2da5690fefe075cd53a238646d8dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0ad3b6f1e4e2da5690fefe075cd53a238646d8dd", + "reference": "0ad3b6f1e4e2da5690fefe075cd53a238646d8dd", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-01T10:32:47+00:00" + }, + { + "name": "symfony/finder", + "version": "v6.2.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "20808dc6631aecafbe67c186af5dcb370be3a0eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/20808dc6631aecafbe67c186af5dcb370be3a0eb", + "reference": "20808dc6631aecafbe67c186af5dcb370be3a0eb", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v6.2.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-16T09:57:23+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v6.2.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "49adbb92bcb4e3c2943719d2756271e8b9602acc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/49adbb92bcb4e3c2943719d2756271e8b9602acc", + "reference": "49adbb92bcb4e3c2943719d2756271e8b9602acc", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.1" + }, + "conflict": { + "symfony/cache": "<6.2" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/cache": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", + "symfony/mime": "^5.4|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" + }, + "suggest": { + "symfony/mime": "To use the file extension guesser" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v6.2.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-04-18T13:46:08+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v6.2.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "81064a65a5496f17d2b6984f6519406f98864215" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/81064a65a5496f17d2b6984f6519406f98864215", + "reference": "81064a65a5496f17d2b6984f6519406f98864215", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^6.1", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/http-foundation": "^5.4.21|^6.2.7", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<5.4", + "symfony/cache": "<5.4", + "symfony/config": "<6.1", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<6.2", + "symfony/doctrine-bridge": "<5.4", + "symfony/form": "<5.4", + "symfony/http-client": "<5.4", + "symfony/mailer": "<5.4", + "symfony/messenger": "<5.4", + "symfony/translation": "<5.4", + "symfony/twig-bridge": "<5.4", + "symfony/validator": "<5.4", + "twig/twig": "<2.13" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^5.4|^6.0", + "symfony/config": "^6.1", + "symfony/console": "^5.4|^6.0", + "symfony/css-selector": "^5.4|^6.0", + "symfony/dependency-injection": "^6.2", + "symfony/dom-crawler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^1.1|^2|^3", + "symfony/process": "^5.4|^6.0", + "symfony/routing": "^5.4|^6.0", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/uid": "^5.4|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v6.2.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-04-28T13:50:28+00:00" + }, + { + "name": "symfony/mailer", + "version": "v6.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "bfcfa015c67e19c6fdb7ca6fe70700af1e740a17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/bfcfa015c67e19c6fdb7ca6fe70700af1e740a17", + "reference": "bfcfa015c67e19c6fdb7ca6fe70700af1e740a17", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.1", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/mime": "^6.2", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/messenger": "^6.2", + "symfony/twig-bridge": "^6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v6.2.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-14T15:00:05+00:00" + }, + { + "name": "symfony/mime", + "version": "v6.2.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "b6c137fc53a9f7c4c951cd3f362b3734c7a97723" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/b6c137fc53a9f7c4c951cd3f362b3734c7a97723", + "reference": "b6c137fc53a9f7c4c951cd3f362b3734c7a97723", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<5.4", + "symfony/serializer": "<6.2" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/serializer": "^6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v6.2.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-04-19T09:54:16+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "639084e360537a19f9ee352433b84ce831f3d2da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da", + "reference": "639084e360537a19f9ee352433b84ce831f3d2da", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-intl-normalizer": "^1.10", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "869329b1e9894268a8a61dabb69153029b7a8c97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", + "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/f3cf1a645c2734236ed1e2e671e273eeb3586166", + "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/process", + "version": "v6.2.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e", + "reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v6.2.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-04-18T13:56:57+00:00" + }, + { + "name": "symfony/routing", + "version": "v6.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "69062e2823f03b82265d73a966999660f0e1e404" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/69062e2823f03b82265d73a966999660f0e1e404", + "reference": "69062e2823f03b82265d73a966999660f0e1e404", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "conflict": { + "doctrine/annotations": "<1.12", + "symfony/config": "<6.2", + "symfony/dependency-injection": "<5.4", + "symfony/yaml": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12|^2", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.2", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v6.2.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-14T15:00:05+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "a8c9cedf55f314f3a186041d19537303766df09a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a8c9cedf55f314f3a186041d19537303766df09a", + "reference": "a8c9cedf55f314f3a186041d19537303766df09a", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.2.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-01T10:32:47+00:00" + }, + { + "name": "symfony/string", + "version": "v6.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/193e83bbd6617d6b2151c37fff10fa7168ebddef", + "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.2.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-20T16:06:02+00:00" + }, + { + "name": "symfony/translation", + "version": "v6.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "817535dbb1721df8b3a8f2489dc7e50bcd6209b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/817535dbb1721df8b3a8f2489dc7e50bcd6209b5", + "reference": "817535dbb1721df8b3a8f2489dc7e50bcd6209b5", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.3|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^4.13", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0", + "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "nikic/php-parser": "To use PhpAstExtractor", + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.2.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-31T09:14:44+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "dfec258b9dd17a6b24420d464c43bffe347441c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dfec258b9dd17a6b24420d464c43bffe347441c8", + "reference": "dfec258b9dd17a6b24420d464c43bffe347441c8", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.2.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-01T10:32:47+00:00" + }, + { + "name": "symfony/uid", + "version": "v6.2.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "d30c72a63897cfa043e1de4d4dd2ffa9ecefcdc0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/d30c72a63897cfa043e1de4d4dd2ffa9ecefcdc0", + "reference": "d30c72a63897cfa043e1de4d4dd2ffa9ecefcdc0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v6.2.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-14T08:44:56+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v6.2.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/41a750a23412ca76fdbbf5096943b4134272c1ab", + "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.2.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-04-18T13:46:08+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "2.2.6", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/c42125b83a4fa63b187fdf29f9c93cb7733da30c", + "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^5.5 || ^7.0 || ^8.0", + "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.6" + }, + "time": "2023-01-03T09:29:04+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.5.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.0.2", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.8", + "symfony/polyfill-ctype": "^1.23", + "symfony/polyfill-mbstring": "^1.23.1", + "symfony/polyfill-php80": "^1.23.1" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-filter": "*", + "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "5.5-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2022-10-16T01:01:54+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b56450eed252f6801410d810c8e1727224ae0743" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", + "reference": "b56450eed252f6801410d810c8e1727224ae0743", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "http://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.1" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2022-03-08T17:03:00+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "fakerphp/faker", + "version": "v1.21.0", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "92efad6a967f0b79c499705c69b662f738cc9e4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/92efad6a967f0b79c499705c69b662f738cc9e4d", + "reference": "92efad6a967f0b79c499705c69b662f738cc9e4d", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "v1.21-dev" + } + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.21.0" + }, + "time": "2022-12-13T13:54:32+00:00" + }, + { + "name": "filp/whoops", + "version": "2.15.2", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/aac9304c5ed61bf7b1b7a6064bf9806ab842ce73", + "reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^0.9 || ^1.0", + "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.15.2" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2023-04-12T12:00:00+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, + "time": "2020-07-09T08:09:16+00:00" + }, + { + "name": "laravel/pint", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/pint.git", + "reference": "c7a01fa9bdd79819e7a2f1ba63ac1b02e6692dbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pint/zipball/c7a01fa9bdd79819e7a2f1ba63ac1b02e6692dbc", + "reference": "c7a01fa9bdd79819e7a2f1ba63ac1b02e6692dbc", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.16.0", + "illuminate/view": "^10.5.1", + "laravel-zero/framework": "^10.0.2", + "mockery/mockery": "^1.5.1", + "nunomaduro/larastan": "^2.5.1", + "nunomaduro/termwind": "^1.15.1", + "pestphp/pest": "^2.4.0" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "support": { + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" + }, + "time": "2023-04-25T14:52:30+00:00" + }, + { + "name": "laravel/sail", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/sail.git", + "reference": "923e1e112b6a8598664dbb0ee79dd3137f1c9d56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sail/zipball/923e1e112b6a8598664dbb0ee79dd3137f1c9d56", + "reference": "923e1e112b6a8598664dbb0ee79dd3137f1c9d56", + "shasum": "" + }, + "require": { + "illuminate/console": "^8.0|^9.0|^10.0", + "illuminate/contracts": "^8.0|^9.0|^10.0", + "illuminate/support": "^8.0|^9.0|^10.0", + "php": "^8.0", + "symfony/yaml": "^6.0" + }, + "require-dev": { + "orchestra/testbench": "^6.0|^7.0|^8.0", + "phpstan/phpstan": "^1.10" + }, + "bin": [ + "bin/sail" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Sail\\SailServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Docker files for running a basic Laravel application.", + "keywords": [ + "docker", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/sail/issues", + "source": "https://github.com/laravel/sail" + }, + "time": "2023-05-04T14:52:56+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/e92dcc83d5a51851baf5f5591d32cb2b16e3684e", + "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": "^7.3 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Mockery": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "issues": "https://github.com/mockery/mockery/issues", + "source": "https://github.com/mockery/mockery/tree/1.5.1" + }, + "time": "2022-09-07T15:32:08+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v7.5.2", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "76b3cabda0aabda455fc3b9db6c3615f5a87c7ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/76b3cabda0aabda455fc3b9db6c3615f5a87c7ff", + "reference": "76b3cabda0aabda455fc3b9db6c3615f5a87c7ff", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.15.2", + "nunomaduro/termwind": "^1.15.1", + "php": "^8.1.0", + "symfony/console": "^6.2.8" + }, + "conflict": { + "phpunit/phpunit": "<10.1.2" + }, + "require-dev": { + "brianium/paratest": "^7.1.3", + "laravel/framework": "^10.8.0", + "laravel/pint": "^1.9.0", + "laravel/sail": "^1.21.4", + "laravel/sanctum": "^3.2.1", + "laravel/tinker": "^2.8.1", + "nunomaduro/larastan": "^2.6.0", + "orchestra/testbench-core": "^8.5.0", + "pestphp/pest": "^2.5.2", + "phpunit/phpunit": "^10.1.1", + "sebastian/environment": "^6.0.1", + "spatie/laravel-ignition": "^2.1.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2023-04-22T22:12:40+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "884a0da7f9f46f28b2cb69134217fd810b793974" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/884a0da7f9f46f28b2cb69134217fd810b793974", + "reference": "884a0da7f9f46f28b2cb69134217fd810b793974", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.15", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-04-17T12:15:40+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "5647d65443818959172645e7ed999217360654b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6", + "reference": "5647d65443818959172645e7ed999217360654b6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-05-07T09:13:23+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:46+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "2379ebafc1737e71cdc84f402acb6b7f04198b9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2379ebafc1737e71cdc84f402acb6b7f04198b9d", + "reference": "2379ebafc1737e71cdc84f402acb6b7f04198b9d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.0", + "sebastian/global-state": "^6.0", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.1.3" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-05-11T05:16:22+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:15+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/72f01e6586e0caf6af81297897bd112eb7e9627c", + "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:07:16+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:47+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-05-01T07:48:21+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-04-11T05:39:26+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0", + "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:49+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "aab257c712de87b90194febd52e4d184551c2d44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/aab257c712de87b90194febd52e4d184551c2d44", + "reference": "aab257c712de87b90194febd52e4d184551c2d44", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:07:38+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130", + "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:02+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:32+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:05:40+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:10:45+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-07T11:34:05+00:00" + }, + { + "name": "spatie/backtrace", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/backtrace.git", + "reference": "ec4dd16476b802dbdc6b4467f84032837e316b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/ec4dd16476b802dbdc6b4467f84032837e316b8c", + "reference": "ec4dd16476b802dbdc6b4467f84032837e316b8c", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "ext-json": "*", + "phpunit/phpunit": "^9.3", + "spatie/phpunit-snapshot-assertions": "^4.2", + "symfony/var-dumper": "^5.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Backtrace\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van de Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A better backtrace", + "homepage": "https://github.com/spatie/backtrace", + "keywords": [ + "Backtrace", + "spatie" + ], + "support": { + "source": "https://github.com/spatie/backtrace/tree/1.4.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/spatie", + "type": "github" + }, + { + "url": "https://spatie.be/open-source/support-us", + "type": "other" + } + ], + "time": "2023-03-04T08:57:24+00:00" + }, + { + "name": "spatie/flare-client-php", + "version": "1.3.6", + "source": { + "type": "git", + "url": "https://github.com/spatie/flare-client-php.git", + "reference": "530ac81255af79f114344286e4275f8869c671e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/530ac81255af79f114344286e4275f8869c671e2", + "reference": "530ac81255af79f114344286e4275f8869c671e2", + "shasum": "" + }, + "require": { + "illuminate/pipeline": "^8.0|^9.0|^10.0", + "php": "^8.0", + "spatie/backtrace": "^1.2", + "symfony/http-foundation": "^5.0|^6.0", + "symfony/mime": "^5.2|^6.0", + "symfony/process": "^5.2|^6.0", + "symfony/var-dumper": "^5.2|^6.0" + }, + "require-dev": { + "dms/phpunit-arraysubset-asserts": "^0.3.0", + "pestphp/pest": "^1.20", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "spatie/phpunit-snapshot-assertions": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.1.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\FlareClient\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Send PHP errors to Flare", + "homepage": "https://github.com/spatie/flare-client-php", + "keywords": [ + "exception", + "flare", + "reporting", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/flare-client-php/issues", + "source": "https://github.com/spatie/flare-client-php/tree/1.3.6" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-04-12T07:57:12+00:00" + }, + { + "name": "spatie/ignition", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/ignition.git", + "reference": "f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/ignition/zipball/f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78", + "reference": "f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.0", + "spatie/backtrace": "^1.4", + "spatie/flare-client-php": "^1.1", + "symfony/console": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "require-dev": { + "illuminate/cache": "^9.52", + "mockery/mockery": "^1.4", + "pestphp/pest": "^1.20", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "psr/simple-cache-implementation": "*", + "symfony/cache": "^6.2", + "symfony/process": "^5.4|^6.0", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "simple-cache-implementation": "To cache solutions from OpenAI" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Spatie\\Ignition\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spatie", + "email": "info@spatie.be", + "role": "Developer" + } + ], + "description": "A beautiful error page for PHP applications.", + "homepage": "https://flareapp.io/ignition", + "keywords": [ + "error", + "flare", + "laravel", + "page" + ], + "support": { + "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", + "forum": "https://twitter.com/flareappio", + "issues": "https://github.com/spatie/ignition/issues", + "source": "https://github.com/spatie/ignition" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-05-04T13:20:26+00:00" + }, + { + "name": "spatie/laravel-ignition", + "version": "2.1.2", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-ignition.git", + "reference": "2f99fa6b732a6049e78ed34e4608ce589605ae54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/2f99fa6b732a6049e78ed34e4608ce589605ae54", + "reference": "2f99fa6b732a6049e78ed34e4608ce589605ae54", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "illuminate/support": "^10.0", + "php": "^8.1", + "spatie/flare-client-php": "^1.3.5", + "spatie/ignition": "^1.5.0", + "symfony/console": "^6.2.3", + "symfony/var-dumper": "^6.2.3" + }, + "require-dev": { + "livewire/livewire": "^2.11", + "mockery/mockery": "^1.5.1", + "openai-php/client": "^0.3.4", + "orchestra/testbench": "^8.0", + "pestphp/pest": "^1.22.3", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan-deprecation-rules": "^1.1.1", + "phpstan/phpstan-phpunit": "^1.3.3", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "psr/simple-cache-implementation": "Needed to cache solutions from OpenAI" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelIgnition\\IgnitionServiceProvider" + ], + "aliases": { + "Flare": "Spatie\\LaravelIgnition\\Facades\\Flare" + } + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\LaravelIgnition\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spatie", + "email": "info@spatie.be", + "role": "Developer" + } + ], + "description": "A beautiful error page for Laravel applications.", + "homepage": "https://flareapp.io/ignition", + "keywords": [ + "error", + "flare", + "laravel", + "page" + ], + "support": { + "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", + "forum": "https://twitter.com/flareappio", + "issues": "https://github.com/spatie/laravel-ignition/issues", + "source": "https://github.com/spatie/laravel-ignition" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-05-09T07:19:31+00:00" + }, + { + "name": "symfony/yaml", + "version": "v6.2.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "61916f3861b1e9705b18cfde723921a71dd1559d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/61916f3861b1e9705b18cfde723921a71dd1559d", + "reference": "61916f3861b1e9705b18cfde723921a71dd1559d", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v6.2.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-04-28T13:25:36+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^8.1", + "ext-dom": "*", + "ext-libxml": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/backend-server/config/app.php b/backend-server/config/app.php new file mode 100644 index 00000000..6cdd9f5b --- /dev/null +++ b/backend-server/config/app.php @@ -0,0 +1,189 @@ + env('APP_NAME', 'Laravel'), + + /* + |-------------------------------------------------------------------------- + | Application Environment + |-------------------------------------------------------------------------- + | + | This value determines the "environment" your application is currently + | running in. This may determine how you prefer to configure various + | services the application utilizes. Set this in your ".env" file. + | + */ + + 'env' => env('APP_ENV', 'production'), + + /* + |-------------------------------------------------------------------------- + | Application Debug Mode + |-------------------------------------------------------------------------- + | + | When your application is in debug mode, detailed error messages with + | stack traces will be shown on every error that occurs within your + | application. If disabled, a simple generic error page is shown. + | + */ + + 'debug' => (bool) env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | your application so that it is used when running Artisan tasks. + | + */ + + 'url' => env('APP_URL', 'http://localhost'), + + 'asset_url' => env('ASSET_URL'), + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. We have gone + | ahead and set this to a sensible default for you out of the box. + | + */ + + 'timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by the translation service provider. You are free to set this value + | to any of the locales which will be supported by the application. + | + */ + + 'locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Application Fallback Locale + |-------------------------------------------------------------------------- + | + | The fallback locale determines the locale to use when the current one + | is not available. You may change the value to correspond to any of + | the language folders that are provided through your application. + | + */ + + 'fallback_locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Faker Locale + |-------------------------------------------------------------------------- + | + | This locale will be used by the Faker PHP library when generating fake + | data for your database seeds. For example, this will be used to get + | localized telephone numbers, street address information and more. + | + */ + + 'faker_locale' => 'en_US', + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is used by the Illuminate encrypter service and should be set + | to a random, 32 character string, otherwise these encrypted strings + | will not be safe. Please do this before deploying an application! + | + */ + + 'key' => env('APP_KEY'), + + 'cipher' => 'AES-256-CBC', + + /* + |-------------------------------------------------------------------------- + | Maintenance Mode Driver + |-------------------------------------------------------------------------- + | + | These configuration options determine the driver used to determine and + | manage Laravel's "maintenance mode" status. The "cache" driver will + | allow maintenance mode to be controlled across multiple machines. + | + | Supported drivers: "file", "cache" + | + */ + + 'maintenance' => [ + 'driver' => 'file', + // 'store' => 'redis', + ], + + /* + |-------------------------------------------------------------------------- + | Autoloaded Service Providers + |-------------------------------------------------------------------------- + | + | The service providers listed here will be automatically loaded on the + | request to your application. Feel free to add your own services to + | this array to grant expanded functionality to your applications. + | + */ + + 'providers' => ServiceProvider::defaultProviders()->merge([ + /* + * Package Service Providers... + */ + + /* + * Application Service Providers... + */ + App\Providers\AppServiceProvider::class, + App\Providers\AuthServiceProvider::class, + // App\Providers\BroadcastServiceProvider::class, + App\Providers\EventServiceProvider::class, + App\Providers\RouteServiceProvider::class, + Laravel\Telescope\TelescopeServiceProvider::class, + ])->toArray(), + + /* + |-------------------------------------------------------------------------- + | Class Aliases + |-------------------------------------------------------------------------- + | + | This array of class aliases will be registered when this application + | is started. However, feel free to register as many as you wish as + | the aliases are "lazy" loaded so they don't hinder performance. + | + */ + + 'aliases' => Facade::defaultAliases()->merge([ + // 'Example' => App\Facades\Example::class, + ])->toArray(), + +]; diff --git a/backend-server/config/auth.php b/backend-server/config/auth.php new file mode 100644 index 00000000..9548c15d --- /dev/null +++ b/backend-server/config/auth.php @@ -0,0 +1,115 @@ + [ + 'guard' => 'web', + 'passwords' => 'users', + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | here which uses session storage and the Eloquent user provider. + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | Supported: "session" + | + */ + + 'guards' => [ + 'web' => [ + 'driver' => 'session', + 'provider' => 'users', + ], + ], + + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | If you have multiple user tables or models you may configure multiple + | sources which represent each model / table. These sources may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + + 'providers' => [ + 'users' => [ + 'driver' => 'eloquent', + 'model' => App\Models\User::class, + ], + + // 'users' => [ + // 'driver' => 'database', + // 'table' => 'users', + // ], + ], + + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | You may specify multiple password reset configurations if you have more + | than one user table or model in the application and you want to have + | separate password reset settings based on the specific user types. + | + | The expiry time is the number of minutes that each reset token will be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + | The throttle setting is the number of seconds a user must wait before + | generating more password reset tokens. This prevents the user from + | quickly generating a very large amount of password reset tokens. + | + */ + + 'passwords' => [ + 'users' => [ + 'provider' => 'users', + 'table' => 'password_reset_tokens', + 'expire' => 60, + 'throttle' => 60, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Password Confirmation Timeout + |-------------------------------------------------------------------------- + | + | Here you may define the amount of seconds before a password confirmation + | times out and the user is prompted to re-enter their password via the + | confirmation screen. By default, the timeout lasts for three hours. + | + */ + + 'password_timeout' => 10800, + +]; diff --git a/backend-server/config/broadcasting.php b/backend-server/config/broadcasting.php new file mode 100644 index 00000000..9e4d4aa4 --- /dev/null +++ b/backend-server/config/broadcasting.php @@ -0,0 +1,70 @@ + env('BROADCAST_DRIVER', 'null'), + + /* + |-------------------------------------------------------------------------- + | Broadcast Connections + |-------------------------------------------------------------------------- + | + | Here you may define all of the broadcast connections that will be used + | to broadcast events to other systems or over websockets. Samples of + | each available type of connection are provided inside this array. + | + */ + + 'connections' => [ + + 'pusher' => [ + 'driver' => 'pusher', + 'key' => env('PUSHER_APP_KEY'), + 'secret' => env('PUSHER_APP_SECRET'), + 'app_id' => env('PUSHER_APP_ID'), + 'options' => [ + 'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com', + 'port' => env('PUSHER_PORT', 443), + 'scheme' => env('PUSHER_SCHEME', 'https'), + 'encrypted' => true, + 'useTLS' => env('PUSHER_SCHEME', 'https') === 'https', + ], + 'client_options' => [ + // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html + ], + ], + + 'ably' => [ + 'driver' => 'ably', + 'key' => env('ABLY_KEY'), + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + ], + + 'log' => [ + 'driver' => 'log', + ], + + 'null' => [ + 'driver' => 'null', + ], + + ], + +]; diff --git a/backend-server/config/cache.php b/backend-server/config/cache.php new file mode 100644 index 00000000..33bb2954 --- /dev/null +++ b/backend-server/config/cache.php @@ -0,0 +1,110 @@ + env('CACHE_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + | Supported drivers: "apc", "array", "database", "file", + | "memcached", "redis", "dynamodb", "octane", "null" + | + */ + + 'stores' => [ + + 'apc' => [ + 'driver' => 'apc', + ], + + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + 'lock_connection' => null, + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache/data'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'cache', + 'lock_connection' => 'default', + ], + + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + 'endpoint' => env('DYNAMODB_ENDPOINT'), + ], + + 'octane' => [ + 'driver' => 'octane', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing the APC, database, memcached, Redis, or DynamoDB cache + | stores there might be other applications using the same cache. For + | that reason, you may prefix every cache key to avoid collisions. + | + */ + + 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), + +]; diff --git a/backend-server/config/cors.php b/backend-server/config/cors.php new file mode 100644 index 00000000..8a39e6da --- /dev/null +++ b/backend-server/config/cors.php @@ -0,0 +1,34 @@ + ['api/*', 'sanctum/csrf-cookie'], + + 'allowed_methods' => ['*'], + + 'allowed_origins' => ['*'], + + 'allowed_origins_patterns' => [], + + 'allowed_headers' => ['*'], + + 'exposed_headers' => [], + + 'max_age' => 0, + + 'supports_credentials' => false, + +]; diff --git a/backend-server/config/database.php b/backend-server/config/database.php new file mode 100644 index 00000000..137ad18c --- /dev/null +++ b/backend-server/config/database.php @@ -0,0 +1,151 @@ + env('DB_CONNECTION', 'mysql'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Here are each of the database connections setup for your application. + | Of course, examples of configuring each database platform that is + | supported by Laravel is shown below to make development simple. + | + | + | All database work in Laravel is done through the PHP PDO facilities + | so make sure you have the driver for your particular database of + | choice installed on your machine before you begin development. + | + */ + + 'connections' => [ + + 'sqlite' => [ + 'driver' => 'sqlite', + 'url' => env('DATABASE_URL'), + 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'prefix' => '', + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '5432'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + ], + + 'sqlsrv' => [ + 'driver' => 'sqlsrv', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '1433'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + // 'encrypt' => env('DB_ENCRYPT', 'yes'), + // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + + 'migrations' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as APC or Memcached. Laravel makes it easy to dig right in. + | + */ + + 'redis' => [ + + 'client' => env('REDIS_CLIENT', 'phpredis'), + + 'options' => [ + 'cluster' => env('REDIS_CLUSTER', 'redis'), + 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), + ], + + 'default' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_DB', '0'), + ], + + 'cache' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_CACHE_DB', '1'), + ], + + ], + +]; diff --git a/backend-server/config/filesystems.php b/backend-server/config/filesystems.php new file mode 100644 index 00000000..45ec2f18 --- /dev/null +++ b/backend-server/config/filesystems.php @@ -0,0 +1,67 @@ + env('FILESYSTEM_DISK', 'local'), + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Here you may configure as many filesystem "disks" as you wish, and you + | may even configure multiple disks of the same driver. Defaults have + | been set up for each driver as an example of the required values. + | + | Supported Drivers: "local", "ftp", "sftp", "s3" + | + */ + + 'disks' => [ + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app'), + 'throw' => false, + ], + + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL').'/storage', + 'visibility' => 'public', + 'throw' => false, + ], + + 'shared_volume' => [ + 'driver' => 'local', + 'root' => '/app/shared_data', + ], + ], + + /* + |-------------------------------------------------------------------------- + | Symbolic Links + |-------------------------------------------------------------------------- + | + | Here you may configure the symbolic links that will be created when the + | `storage:link` Artisan command is executed. The array keys should be + | the locations of the links and the values should be their targets. + | + */ + + 'links' => [ + public_path('storage') => storage_path('app/public'), + ], + +]; diff --git a/backend-server/config/hashing.php b/backend-server/config/hashing.php new file mode 100644 index 00000000..bcd3be4c --- /dev/null +++ b/backend-server/config/hashing.php @@ -0,0 +1,52 @@ + 'bcrypt', + + /* + |-------------------------------------------------------------------------- + | Bcrypt Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Bcrypt algorithm. This will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'bcrypt' => [ + 'rounds' => env('BCRYPT_ROUNDS', 10), + ], + + /* + |-------------------------------------------------------------------------- + | Argon Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Argon algorithm. These will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'argon' => [ + 'memory' => 65536, + 'threads' => 1, + 'time' => 4, + ], + +]; diff --git a/backend-server/config/logging.php b/backend-server/config/logging.php new file mode 100644 index 00000000..c44d2763 --- /dev/null +++ b/backend-server/config/logging.php @@ -0,0 +1,131 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | Deprecations Log Channel + |-------------------------------------------------------------------------- + | + | This option controls the log channel that should be used to log warnings + | regarding deprecated PHP and library features. This allows you to get + | your application ready for upcoming major versions of dependencies. + | + */ + + 'deprecations' => [ + 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'), + 'trace' => false, + ], + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Out of + | the box, Laravel uses the Monolog PHP logging library. This gives + | you a variety of powerful log handlers / formatters to utilize. + | + | Available Drivers: "single", "daily", "slack", "syslog", + | "errorlog", "monolog", + | "custom", "stack" + | + */ + + 'channels' => [ + 'stack' => [ + 'driver' => 'stack', + 'channels' => ['single'], + 'ignore_exceptions' => false, + ], + + 'single' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'daily' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'days' => 14, + 'replace_placeholders' => true, + ], + + 'slack' => [ + 'driver' => 'slack', + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => 'Laravel Log', + 'emoji' => ':boom:', + 'level' => env('LOG_LEVEL', 'critical'), + 'replace_placeholders' => true, + ], + + 'papertrail' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class), + 'handler_with' => [ + 'host' => env('PAPERTRAIL_URL'), + 'port' => env('PAPERTRAIL_PORT'), + 'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'), + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'stderr' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => StreamHandler::class, + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'with' => [ + 'stream' => 'php://stderr', + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'syslog' => [ + 'driver' => 'syslog', + 'level' => env('LOG_LEVEL', 'debug'), + 'facility' => LOG_USER, + 'replace_placeholders' => true, + ], + + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'null' => [ + 'driver' => 'monolog', + 'handler' => NullHandler::class, + ], + + 'emergency' => [ + 'path' => storage_path('logs/laravel.log'), + ], + ], + +]; diff --git a/backend-server/config/mail.php b/backend-server/config/mail.php new file mode 100644 index 00000000..e652bd02 --- /dev/null +++ b/backend-server/config/mail.php @@ -0,0 +1,125 @@ + env('MAIL_MAILER', 'smtp'), + + /* + |-------------------------------------------------------------------------- + | Mailer Configurations + |-------------------------------------------------------------------------- + | + | Here you may configure all of the mailers used by your application plus + | their respective settings. Several examples have been configured for + | you and you are free to add your own as your application requires. + | + | Laravel supports a variety of mail "transport" drivers to be used while + | sending an e-mail. You will specify which one you are using for your + | mailers below. You are free to add additional mailers as required. + | + | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2", + | "postmark", "log", "array", "failover" + | + */ + + 'mailers' => [ + 'smtp' => [ + 'transport' => 'smtp', + 'url' => env('MAIL_URL'), + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), + 'port' => env('MAIL_PORT', 587), + 'encryption' => env('MAIL_ENCRYPTION', 'tls'), + 'username' => env('MAIL_USERNAME'), + 'password' => env('MAIL_PASSWORD'), + 'timeout' => null, + 'local_domain' => env('MAIL_EHLO_DOMAIN'), + ], + + 'ses' => [ + 'transport' => 'ses', + ], + + 'mailgun' => [ + 'transport' => 'mailgun', + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'postmark' => [ + 'transport' => 'postmark', + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'sendmail' => [ + 'transport' => 'sendmail', + 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), + ], + + 'log' => [ + 'transport' => 'log', + 'channel' => env('MAIL_LOG_CHANNEL'), + ], + + 'array' => [ + 'transport' => 'array', + ], + + 'failover' => [ + 'transport' => 'failover', + 'mailers' => [ + 'smtp', + 'log', + ], + ], + ], + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all e-mails sent by your application to be sent from + | the same address. Here, you may specify a name and address that is + | used globally for all e-mails that are sent by your application. + | + */ + + 'from' => [ + 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), + 'name' => env('MAIL_FROM_NAME', 'Example'), + ], + + /* + |-------------------------------------------------------------------------- + | Markdown Mail Settings + |-------------------------------------------------------------------------- + | + | If you are using Markdown based email rendering, you may configure your + | theme and component paths here, allowing you to customize the design + | of the emails. Or, you may simply stick with the Laravel defaults! + | + */ + + 'markdown' => [ + 'theme' => 'default', + + 'paths' => [ + resource_path('views/vendor/mail'), + ], + ], + +]; diff --git a/backend-server/config/queue.php b/backend-server/config/queue.php new file mode 100644 index 00000000..01c6b054 --- /dev/null +++ b/backend-server/config/queue.php @@ -0,0 +1,109 @@ + env('QUEUE_CONNECTION', 'sync'), + + /* + |-------------------------------------------------------------------------- + | Queue Connections + |-------------------------------------------------------------------------- + | + | Here you may configure the connection information for each server that + | is used by your application. A default configuration has been added + | for each back-end shipped with Laravel. You are free to add more. + | + | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" + | + */ + + 'connections' => [ + + 'sync' => [ + 'driver' => 'sync', + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'jobs', + 'queue' => 'default', + 'retry_after' => 90, + 'after_commit' => false, + ], + + 'beanstalkd' => [ + 'driver' => 'beanstalkd', + 'host' => 'localhost', + 'queue' => 'default', + 'retry_after' => 90, + 'block_for' => 0, + 'after_commit' => false, + ], + + 'sqs' => [ + 'driver' => 'sqs', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), + 'queue' => env('SQS_QUEUE', 'default'), + 'suffix' => env('SQS_SUFFIX'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'after_commit' => false, + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => env('REDIS_QUEUE', 'default'), + 'retry_after' => 90, + 'block_for' => null, + 'after_commit' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Job Batching + |-------------------------------------------------------------------------- + | + | The following options configure the database and table that store job + | batching information. These options can be updated to any database + | connection and table which has been defined by your application. + | + */ + + 'batching' => [ + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'job_batches', + ], + + /* + |-------------------------------------------------------------------------- + | Failed Queue Jobs + |-------------------------------------------------------------------------- + | + | These options configure the behavior of failed queue job logging so you + | can control which database and table are used to store the jobs that + | have failed. You may change them to any database / table you wish. + | + */ + + 'failed' => [ + 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'failed_jobs', + ], + +]; diff --git a/backend-server/config/sanctum.php b/backend-server/config/sanctum.php new file mode 100644 index 00000000..529cfdc9 --- /dev/null +++ b/backend-server/config/sanctum.php @@ -0,0 +1,67 @@ + explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( + '%s%s', + 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', + Sanctum::currentApplicationUrlWithPort() + ))), + + /* + |-------------------------------------------------------------------------- + | Sanctum Guards + |-------------------------------------------------------------------------- + | + | This array contains the authentication guards that will be checked when + | Sanctum is trying to authenticate a request. If none of these guards + | are able to authenticate the request, Sanctum will use the bearer + | token that's present on an incoming request for authentication. + | + */ + + 'guard' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Expiration Minutes + |-------------------------------------------------------------------------- + | + | This value controls the number of minutes until an issued token will be + | considered expired. If this value is null, personal access tokens do + | not expire. This won't tweak the lifetime of first-party sessions. + | + */ + + 'expiration' => null, + + /* + |-------------------------------------------------------------------------- + | Sanctum Middleware + |-------------------------------------------------------------------------- + | + | When authenticating your first-party SPA with Sanctum you may need to + | customize some of the middleware Sanctum uses while processing the + | request. You may change the middleware listed below as required. + | + */ + + 'middleware' => [ + 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, + 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, + ], + +]; diff --git a/backend-server/config/services.php b/backend-server/config/services.php new file mode 100644 index 00000000..0ace530e --- /dev/null +++ b/backend-server/config/services.php @@ -0,0 +1,34 @@ + [ + 'domain' => env('MAILGUN_DOMAIN'), + 'secret' => env('MAILGUN_SECRET'), + 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), + 'scheme' => 'https', + ], + + 'postmark' => [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + +]; diff --git a/backend-server/config/session.php b/backend-server/config/session.php new file mode 100644 index 00000000..8fed97c0 --- /dev/null +++ b/backend-server/config/session.php @@ -0,0 +1,201 @@ + env('SESSION_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to immediately expire on the browser closing, set that option. + | + */ + + 'lifetime' => env('SESSION_LIFETIME', 120), + + 'expire_on_close' => false, + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it is stored. All encryption will be run + | automatically by Laravel and you can use the Session like normal. + | + */ + + 'encrypt' => false, + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When using the native session driver, we need a location where session + | files may be stored. A default has been set for you but a different + | location may be specified. This is only needed for file sessions. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => env('SESSION_CONNECTION'), + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table we + | should use to manage the sessions. Of course, a sensible default is + | provided for you; however, you are free to change this as needed. + | + */ + + 'table' => 'sessions', + + /* + |-------------------------------------------------------------------------- + | Session Cache Store + |-------------------------------------------------------------------------- + | + | While using one of the framework's cache driven session backends you may + | list a cache store that should be used for these sessions. This value + | must match with one of the application's configured cache "stores". + | + | Affects: "apc", "dynamodb", "memcached", "redis" + | + */ + + 'store' => env('SESSION_STORE'), + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [2, 100], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the cookie used to identify a session + | instance by ID. The name specified here will get used every time a + | new session cookie is created by the framework for every driver. + | + */ + + 'cookie' => env( + 'SESSION_COOKIE', + Str::slug(env('APP_NAME', 'laravel'), '_').'_session' + ), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application but you are free to change this when necessary. + | + */ + + 'path' => '/', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | Here you may change the domain of the cookie used to identify a session + | in your application. This will determine which domains the cookie is + | available to in your application. A sensible default has been set. + | + */ + + 'domain' => env('SESSION_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you when it can't be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE'), + + /* + |-------------------------------------------------------------------------- + | HTTP Access Only + |-------------------------------------------------------------------------- + | + | Setting this value to true will prevent JavaScript from accessing the + | value of the cookie and the cookie will only be accessible through + | the HTTP protocol. You are free to modify this option if needed. + | + */ + + 'http_only' => true, + + /* + |-------------------------------------------------------------------------- + | Same-Site Cookies + |-------------------------------------------------------------------------- + | + | This option determines how your cookies behave when cross-site requests + | take place, and can be used to mitigate CSRF attacks. By default, we + | will set this value to "lax" since this is a secure default value. + | + | Supported: "lax", "strict", "none", null + | + */ + + 'same_site' => 'lax', + +]; diff --git a/backend-server/config/view.php b/backend-server/config/view.php new file mode 100644 index 00000000..22b8a18d --- /dev/null +++ b/backend-server/config/view.php @@ -0,0 +1,36 @@ + [ + resource_path('views'), + ], + + /* + |-------------------------------------------------------------------------- + | Compiled View Path + |-------------------------------------------------------------------------- + | + | This option determines where all the compiled Blade templates will be + | stored for your application. Typically, this is within the storage + | directory. However, as usual, you are free to change this value. + | + */ + + 'compiled' => env( + 'VIEW_COMPILED_PATH', + realpath(storage_path('framework/views')) + ), + +]; diff --git a/backend-server/database/.gitignore b/backend-server/database/.gitignore new file mode 100644 index 00000000..9b19b93c --- /dev/null +++ b/backend-server/database/.gitignore @@ -0,0 +1 @@ +*.sqlite* diff --git a/backend-server/database/factories/UserFactory.php b/backend-server/database/factories/UserFactory.php new file mode 100644 index 00000000..a6ecc0af --- /dev/null +++ b/backend-server/database/factories/UserFactory.php @@ -0,0 +1,38 @@ + + */ +class UserFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => fake()->name(), + 'email' => fake()->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password + 'remember_token' => Str::random(10), + ]; + } + + /** + * Indicate that the model's email address should be unverified. + */ + public function unverified(): static + { + return $this->state(fn (array $attributes) => [ + 'email_verified_at' => null, + ]); + } +} diff --git a/backend-server/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php b/backend-server/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php new file mode 100644 index 00000000..81a7229b --- /dev/null +++ b/backend-server/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php @@ -0,0 +1,28 @@ +string('email')->primary(); + $table->string('token'); + $table->timestamp('created_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('password_reset_tokens'); + } +}; diff --git a/backend-server/database/migrations/2019_08_19_000000_create_failed_jobs_table.php b/backend-server/database/migrations/2019_08_19_000000_create_failed_jobs_table.php new file mode 100644 index 00000000..249da817 --- /dev/null +++ b/backend-server/database/migrations/2019_08_19_000000_create_failed_jobs_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('failed_jobs'); + } +}; diff --git a/backend-server/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/backend-server/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php new file mode 100644 index 00000000..e828ad81 --- /dev/null +++ b/backend-server/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php @@ -0,0 +1,33 @@ +id(); + $table->morphs('tokenable'); + $table->string('name'); + $table->string('token', 64)->unique(); + $table->text('abilities')->nullable(); + $table->timestamp('last_used_at')->nullable(); + $table->timestamp('expires_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('personal_access_tokens'); + } +}; diff --git a/backend-server/database/migrations/2023_05_12_110303_create_chatbots_table.php b/backend-server/database/migrations/2023_05_12_110303_create_chatbots_table.php new file mode 100644 index 00000000..ecb8e331 --- /dev/null +++ b/backend-server/database/migrations/2023_05_12_110303_create_chatbots_table.php @@ -0,0 +1,35 @@ +uuid('id'); + $table->string('name'); + $table->string('token'); + $table->string('website')->nullable(); + $table->string('status')->default('draft'); + $table->text('prompt_message'); + $table->boolean('enhanced_privacy')->default(false); + $table->boolean('smart_sync')->default(false); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chatbots'); + } +}; diff --git a/backend-server/database/migrations/2023_05_12_110323_create_chat_histories_table.php b/backend-server/database/migrations/2023_05_12_110323_create_chat_histories_table.php new file mode 100644 index 00000000..60d8e5cc --- /dev/null +++ b/backend-server/database/migrations/2023_05_12_110323_create_chat_histories_table.php @@ -0,0 +1,30 @@ +uuid('id'); + $table->uuid('chatbot_id'); + $table->string('from'); // user or bot + $table->text('message'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chat_histories'); + } +}; diff --git a/backend-server/database/migrations/2023_05_12_110357_create_chatbot_settings_table.php b/backend-server/database/migrations/2023_05_12_110357_create_chatbot_settings_table.php new file mode 100644 index 00000000..069892e0 --- /dev/null +++ b/backend-server/database/migrations/2023_05_12_110357_create_chatbot_settings_table.php @@ -0,0 +1,30 @@ +uuid('id'); + $table->uuid('chatbot_id'); + $table->string('name'); + $table->string('value'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chatbot_settings'); + } +}; diff --git a/backend-server/database/migrations/2023_05_12_110416_create_onboarding_steps_table.php b/backend-server/database/migrations/2023_05_12_110416_create_onboarding_steps_table.php new file mode 100644 index 00000000..4d94ad29 --- /dev/null +++ b/backend-server/database/migrations/2023_05_12_110416_create_onboarding_steps_table.php @@ -0,0 +1,30 @@ +uuid('id'); + $table->uuid('chatbot_id'); + $table->string('name'); + $table->boolean('finished')->default(false); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('onboarding_steps'); + } +}; diff --git a/backend-server/database/migrations/2023_05_12_161106_create_website_data_sources_table.php b/backend-server/database/migrations/2023_05_12_161106_create_website_data_sources_table.php new file mode 100644 index 00000000..be49f8dc --- /dev/null +++ b/backend-server/database/migrations/2023_05_12_161106_create_website_data_sources_table.php @@ -0,0 +1,33 @@ +uuid('id'); + $table->uuid('chatbot_id'); + $table->string('root_url'); + $table->string('icon')->nullable(); + $table->datetime('vector_databased_last_ingested_at')->nullable(); + $table->string('crawling_status')->default('pending'); + $table->float('crawling_progress')->default(0.0); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('website_data_sources'); + } +}; diff --git a/backend-server/database/migrations/2023_05_12_214227_create_jobs_table.php b/backend-server/database/migrations/2023_05_12_214227_create_jobs_table.php new file mode 100644 index 00000000..6098d9b1 --- /dev/null +++ b/backend-server/database/migrations/2023_05_12_214227_create_jobs_table.php @@ -0,0 +1,32 @@ +bigIncrements('id'); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('jobs'); + } +}; diff --git a/backend-server/database/migrations/2023_05_14_114015_create_crawled_pages_table.php b/backend-server/database/migrations/2023_05_14_114015_create_crawled_pages_table.php new file mode 100644 index 00000000..3dd1be5f --- /dev/null +++ b/backend-server/database/migrations/2023_05_14_114015_create_crawled_pages_table.php @@ -0,0 +1,35 @@ +uuid('id')->primary(); + $table->uuid('chatbot_id'); + $table->uuid('website_data_source_id'); + $table->string('url'); + $table->string('title')->nullable(); + $table->string('status_code')->nullable(); + $table->longText('content')->nullable(); + $table->longText('normalized_content')->nullable(); + $table->text('aws_url')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('crawled_pages'); + } +}; diff --git a/backend-server/database/migrations/2023_05_14_222511_create_text_data_sources_table.php b/backend-server/database/migrations/2023_05_14_222511_create_text_data_sources_table.php new file mode 100644 index 00000000..7278f807 --- /dev/null +++ b/backend-server/database/migrations/2023_05_14_222511_create_text_data_sources_table.php @@ -0,0 +1,27 @@ +id(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('text_data_sources'); + } +}; diff --git a/backend-server/database/migrations/2023_05_14_222525_create_pdf_data_sources_table.php b/backend-server/database/migrations/2023_05_14_222525_create_pdf_data_sources_table.php new file mode 100644 index 00000000..40ba39d6 --- /dev/null +++ b/backend-server/database/migrations/2023_05_14_222525_create_pdf_data_sources_table.php @@ -0,0 +1,30 @@ +uuid('id')->primary(); + $table->uuid('chatbot_id'); + $table->json('files'); + $table->string('folder_name')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('pdf_data_sources'); + } +}; diff --git a/backend-server/database/migrations/2023_05_14_222537_create_notion_data_sources_table.php b/backend-server/database/migrations/2023_05_14_222537_create_notion_data_sources_table.php new file mode 100644 index 00000000..9ec290b4 --- /dev/null +++ b/backend-server/database/migrations/2023_05_14_222537_create_notion_data_sources_table.php @@ -0,0 +1,27 @@ +id(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('notion_data_sources'); + } +}; diff --git a/backend-server/database/seeders/DatabaseSeeder.php b/backend-server/database/seeders/DatabaseSeeder.php new file mode 100644 index 00000000..a9f4519f --- /dev/null +++ b/backend-server/database/seeders/DatabaseSeeder.php @@ -0,0 +1,22 @@ +create(); + + // \App\Models\User::factory()->create([ + // 'name' => 'Test User', + // 'email' => 'test@example.com', + // ]); + } +} diff --git a/backend-server/nginx.conf b/backend-server/nginx.conf new file mode 100644 index 00000000..948adbce --- /dev/null +++ b/backend-server/nginx.conf @@ -0,0 +1,22 @@ +server { + listen 80; + server_name localhost; + root /var/www/html/public; + + index index.php index.html; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass php-fpm:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\.ht { + deny all; + } +} diff --git a/backend-server/package.json b/backend-server/package.json new file mode 100644 index 00000000..e543e0d1 --- /dev/null +++ b/backend-server/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build" + }, + "devDependencies": { + "axios": "^1.1.2", + "laravel-vite-plugin": "^0.7.5", + "vite": "^4.0.0" + } +} diff --git a/backend-server/phpunit.xml b/backend-server/phpunit.xml new file mode 100644 index 00000000..e9f533da --- /dev/null +++ b/backend-server/phpunit.xml @@ -0,0 +1,31 @@ + + + + + ./tests/Unit + + + ./tests/Feature + + + + + ./app + + + + + + + + + + + + + + diff --git a/backend-server/public/.DS_Store b/backend-server/public/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..fc8018a5acaeb3451aa3e628610dae09ee7c34fd GIT binary patch literal 6148 zcmeHKL2uJA6n^f?nyeu80Maf&1WO+nlcVt$hSIrjVF`17+J6OroAqI*OwBJz+J>pRGPVcgDX!)mtX zI#9_w+H^!Y<P z&1x@sf3A4@6ye=DdI(9QG^L35ho1~}yTWMFG5pRcK|h)@e3g_ctdA9z53dY;#dHD2 z1pQ4ajBgu^Gx?rVa0+3M*BQ0(pBdpipV+Z{2`6ci7oE;mRokjx+irLbuj#!Voap(W z7!|X;KbpSgrx#kM;bnOgzD(lzuyyl^&Wcfz#Zw_9Q4E(iuaYd%^S+*CQ7+tpY4Ci{ zAGUTEi|)hDUhrVQyW9&F2lu($-Cr(!@7A5WkDd=t)3Z!}z$jn}d$iaMi({fmGHB?e?Bzq*o|V0! zDCr&V55%2R&!Eel0#1Q-1-8s%i_ib3zrX*lliZV2z$x%wDWK|ygTp?CWY5-(!SPue tAiYCkW51O_p&+xzu@v|y-bE5aTfhZi&*I7;YGCe1KxA;4Q{b;E@B`4i*69EM literal 0 HcmV?d00001 diff --git a/backend-server/public/.htaccess b/backend-server/public/.htaccess new file mode 100644 index 00000000..3aec5e27 --- /dev/null +++ b/backend-server/public/.htaccess @@ -0,0 +1,21 @@ + + + Options -MultiViews -Indexes + + + RewriteEngine On + + # Handle Authorization Header + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + # Redirect Trailing Slashes If Not A Folder... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} (.+)/$ + RewriteRule ^ %1 [L,R=301] + + # Send Requests To Front Controller... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + diff --git a/backend-server/public/chat.css b/backend-server/public/chat.css new file mode 100644 index 00000000..4bbdeac4 --- /dev/null +++ b/backend-server/public/chat.css @@ -0,0 +1 @@ +.closed,.open{transition:opacity .1s ease-in-out}#chat-container{position:fixed;bottom:20px;right:20px;z-index:9999}.open{opacity:1;visibility:visible}.closed{opacity:0;visibility:hidden}#chat-bubble{display:flex;align-items:center;justify-content:center;color:#fff;border-radius:50%;cursor:pointer;width:60px;height:60px;font-family:Arial,sans-serif;background:linear-gradient(135deg,#2a27da,#0cf);box-shadow:rgba(0,77,255,.5) 0 4px 24px;transition:background .3s ease-in-out}#chat-bubble:hover{background:linear-gradient(135deg,#da2792,#0cf)}#chat-box{position:absolute;bottom:72px;right:0;width:450px;height:600px;background-color:#fff;overflow:auto;text-align:right;border-radius:20px;box-shadow:rgba(149,157,165,.2) 0 8px 24px;border:1px solid #d2d2d2}@media (max-width:767px){#chat-box{width:calc(100% - -300px)!important}} diff --git a/backend-server/public/chat.js b/backend-server/public/chat.js new file mode 100644 index 00000000..64ab145a --- /dev/null +++ b/backend-server/public/chat.js @@ -0,0 +1,23 @@ +function toggleChat() { + var e = document.getElementById("chat-box"); + e.classList.contains("open") ? (e.classList.remove("open"), e.classList.add("closed")) : (e.classList.remove("closed"), e.classList.add("open")) +} + +function initializeChatWidget(e) { + var t = document.createElement("div"); + t.id = "chat-container"; + var a = document.createElement("div"); + a.id = "chat-bubble", a.onclick = toggleChat, a.innerHTML = ''; + var i = document.createElement("div"); + i.id = "chat-box", i.classList.add("closed"); + var d = "https://openchat.so/chat/" + e.token; + i.innerHTML = '', t.appendChild(a), t.appendChild(i), document.body.appendChild(t) +} + +function loadCSS() { + var e = document.createElement("link"); + e.rel = "stylesheet", e.href = "https://openchat.so/chat.css", document.head.appendChild(e) +} + +loadCSS(); + diff --git a/backend-server/public/dashboard/css/additional-styles/flatpickr.css b/backend-server/public/dashboard/css/additional-styles/flatpickr.css new file mode 100644 index 00000000..d099c6db --- /dev/null +++ b/backend-server/public/dashboard/css/additional-styles/flatpickr.css @@ -0,0 +1,229 @@ +/* Customise flatpickr */ +* { + --calendarPadding: 24px; + --daySize: 36px; + --daysWidth: calc(var(--daySize)*7); +} + +@keyframes fpFadeInDown { + from { + opacity: 0; + transform: translate3d(0, -8px, 0); + } + to { + opacity: 1; + transform: translate3d(0, 0, 0); + } +} + +.flatpickr-calendar { + border: inherit; + @apply rounded shadow-lg border border-slate-200 left-1/2; + margin-left: calc(calc(var(--daysWidth) + calc(var(--calendarPadding)*2))*0.5*-1); + padding: var(--calendarPadding); + width: calc(var(--daysWidth) + calc(var(--calendarPadding)*2)); +} + +@screen lg { + .flatpickr-calendar { + @apply left-0 right-auto; + margin-left: 0; + } +} + +.flatpickr-right.flatpickr-calendar { + @apply right-0 left-auto; + margin-left: 0; +} + +.flatpickr-calendar.animate.open { + animation: fpFadeInDown 200ms ease-out; +} + +.flatpickr-calendar.static { + position: absolute; + top: calc(100% + 4px); +} + +.flatpickr-calendar.static.open { + z-index: 20; +} + +.flatpickr-days { + width: var(--daysWidth); +} + +.dayContainer { + width: var(--daysWidth); + min-width: var(--daysWidth); + max-width: var(--daysWidth); +} + +.flatpickr-day { + @apply bg-slate-50 text-sm font-medium text-slate-600; + max-width: var(--daySize); + height: var(--daySize); + line-height: var(--daySize); +} + +.flatpickr-day, +.flatpickr-day.prevMonthDay, +.flatpickr-day.nextMonthDay { + border: none; +} + +.flatpickr-day, +.flatpickr-day.prevMonthDay, +.flatpickr-day.nextMonthDay, +.flatpickr-day.selected.startRange, +.flatpickr-day.startRange.startRange, +.flatpickr-day.endRange.startRange, +.flatpickr-day.selected.endRange, +.flatpickr-day.startRange.endRange, +.flatpickr-day.endRange.endRange, +.flatpickr-day.selected.startRange.endRange, +.flatpickr-day.startRange.startRange.endRange, +.flatpickr-day.endRange.startRange.endRange { + border-radius: 0; +} + +.flatpickr-day.flatpickr-disabled, +.flatpickr-day.flatpickr-disabled:hover, +.flatpickr-day.prevMonthDay, +.flatpickr-day.nextMonthDay, +.flatpickr-day.notAllowed, +.flatpickr-day.notAllowed.prevMonthDay, +.flatpickr-day.notAllowed.nextMonthDay { + @apply text-slate-400; +} + +.rangeMode .flatpickr-day { + margin: 0; +} + +.flatpickr-day.selected, +.flatpickr-day.startRange, +.flatpickr-day.endRange, +.flatpickr-day.selected.inRange, +.flatpickr-day.startRange.inRange, +.flatpickr-day.endRange.inRange, +.flatpickr-day.selected:focus, +.flatpickr-day.startRange:focus, +.flatpickr-day.endRange:focus, +.flatpickr-day.selected:hover, +.flatpickr-day.startRange:hover, +.flatpickr-day.endRange:hover, +.flatpickr-day.selected.prevMonthDay, +.flatpickr-day.startRange.prevMonthDay, +.flatpickr-day.endRange.prevMonthDay, +.flatpickr-day.selected.nextMonthDay, +.flatpickr-day.startRange.nextMonthDay, +.flatpickr-day.endRange.nextMonthDay { + @apply bg-indigo-500 text-indigo-50; +} + +.flatpickr-day.inRange, +.flatpickr-day.prevMonthDay.inRange, +.flatpickr-day.nextMonthDay.inRange, +.flatpickr-day.today.inRange, +.flatpickr-day.prevMonthDay.today.inRange, +.flatpickr-day.nextMonthDay.today.inRange, +.flatpickr-day:hover, +.flatpickr-day.prevMonthDay:hover, +.flatpickr-day.nextMonthDay:hover, +.flatpickr-day:focus, +.flatpickr-day.prevMonthDay:focus, +.flatpickr-day.nextMonthDay:focus, +.flatpickr-day.today:hover, +.flatpickr-day.today:focus { + @apply bg-indigo-400 text-indigo-50; +} + +.flatpickr-day.inRange, +.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)), +.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)), +.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)) { + box-shadow: none; +} + +.flatpickr-months { + align-items: center; + margin-top: -8px; + margin-bottom: 6px; +} + +.flatpickr-months .flatpickr-prev-month, +.flatpickr-months .flatpickr-next-month { + position: static; + height: auto; + @apply text-slate-600; +} + +.flatpickr-months .flatpickr-prev-month svg, +.flatpickr-months .flatpickr-next-month svg { + width: 7px; + height: 11px; +} + +.flatpickr-months .flatpickr-prev-month:hover, +.flatpickr-months .flatpickr-next-month:hover, +.flatpickr-months .flatpickr-prev-month:hover svg, +.flatpickr-months .flatpickr-next-month:hover svg { + fill: inherit; + @apply text-slate-400; +} + +.flatpickr-months .flatpickr-prev-month { + margin-left: -10px; +} + +.flatpickr-months .flatpickr-next-month { + margin-right: -10px; +} + +.flatpickr-months .flatpickr-month { + @apply text-slate-800; + height: auto; + line-height: inherit; +} + +.flatpickr-current-month { + @apply text-sm font-medium; + position: static; + height: auto; + width: auto; + left: auto; + padding: 0; +} + +.flatpickr-current-month span.cur-month { + @apply font-medium m-0; +} + +.flatpickr-current-month span.cur-month:hover { + background: none; +} + +.flatpickr-current-month input.cur-year { + font-weight: inherit; + box-shadow: none !important; +} + +.numInputWrapper:hover { + background: none; +} + +.numInputWrapper span { + display: none; +} + +span.flatpickr-weekday { + @apply text-slate-400 font-medium text-xs; +} + +.flatpickr-calendar.arrowTop::before, +.flatpickr-calendar.arrowTop::after, +.flatpickr-calendar.arrowBottom::before, +.flatpickr-calendar.arrowBottom::after { + display: none; +} \ No newline at end of file diff --git a/backend-server/public/dashboard/css/additional-styles/range-slider.css b/backend-server/public/dashboard/css/additional-styles/range-slider.css new file mode 100644 index 00000000..8d19a09e --- /dev/null +++ b/backend-server/public/dashboard/css/additional-styles/range-slider.css @@ -0,0 +1,57 @@ +/* Range slider */ +:root { + --range-thumb-size: 36px; +} + +input[type=range] { + appearance: none; + background: #ccc; + border-radius: 3px; + height: 6px; + margin-top: (--range-thumb-size - 6px) * 0.5; + margin-bottom: (--range-thumb-size - 6px) * 0.5; + --thumb-size: #{--range-thumb-size}; +} + +input[type=range]::-webkit-slider-thumb { + appearance: none; + -webkit-appearance: none; + background-color: #000; + background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 .5v7L12 4zM0 4l4 3.5v-7z' fill='%23FFF' fill-rule='nonzero'/%3E%3C/svg%3E"); + background-position: center; + background-repeat: no-repeat; + border: 0; + border-radius: 50%; + cursor: pointer; + height: --range-thumb-size; + width: --range-thumb-size; +} + +input[type=range]::-moz-range-thumb { + background-color: #000; + background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 .5v7L12 4zM0 4l4 3.5v-7z' fill='%23FFF' fill-rule='nonzero'/%3E%3C/svg%3E"); + background-position: center; + background-repeat: no-repeat; + border: 0; + border: none; + border-radius: 50%; + cursor: pointer; + height: --range-thumb-size; + width: --range-thumb-size; +} + +input[type=range]::-ms-thumb { + background-color: #000; + background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 .5v7L12 4zM0 4l4 3.5v-7z' fill='%23FFF' fill-rule='nonzero'/%3E%3C/svg%3E"); + background-position: center; + background-repeat: no-repeat; + border: 0; + border-radius: 50%; + cursor: pointer; + height: --range-thumb-size; + width: --range-thumb-size; +} + +input[type=range]::-moz-focus-outer { + border: 0; +} \ No newline at end of file diff --git a/backend-server/public/dashboard/css/additional-styles/theme.css b/backend-server/public/dashboard/css/additional-styles/theme.css new file mode 100644 index 00000000..0b69cb3b --- /dev/null +++ b/backend-server/public/dashboard/css/additional-styles/theme.css @@ -0,0 +1,8 @@ +.form-input:focus, +.form-textarea:focus, +.form-multiselect:focus, +.form-select:focus, +.form-checkbox:focus, +.form-radio:focus { + @apply ring-0; +} diff --git a/backend-server/public/dashboard/css/additional-styles/toggle-switch.css b/backend-server/public/dashboard/css/additional-styles/toggle-switch.css new file mode 100644 index 00000000..857fef40 --- /dev/null +++ b/backend-server/public/dashboard/css/additional-styles/toggle-switch.css @@ -0,0 +1,35 @@ +/* Switch element */ +.form-switch { + @apply relative select-none; + width: 44px; +} + +.form-switch label { + @apply block overflow-hidden cursor-pointer h-6 rounded-full; +} + +.form-switch label > span:first-child { + @apply absolute block rounded-full; + width: 20px; + height: 20px; + top: 2px; + left: 2px; + right: 50%; + transition: all .15s ease-out; +} + +.form-switch input[type="checkbox"]:checked + label { + @apply bg-indigo-500; +} + +.form-switch input[type="checkbox"]:checked + label > span:first-child { + left: 22px; +} + +.form-switch input[type="checkbox"]:disabled + label { + @apply cursor-not-allowed bg-slate-100 border border-slate-200; +} + +.form-switch input[type="checkbox"]:disabled + label > span:first-child { + @apply bg-slate-400; +} \ No newline at end of file diff --git a/backend-server/public/dashboard/css/additional-styles/utility-patterns.css b/backend-server/public/dashboard/css/additional-styles/utility-patterns.css new file mode 100644 index 00000000..e5b321fe --- /dev/null +++ b/backend-server/public/dashboard/css/additional-styles/utility-patterns.css @@ -0,0 +1,106 @@ +/* Typography */ +.h1 { + @apply text-4xl font-extrabold tracking-tighter; +} + +.h2 { + @apply text-3xl font-extrabold tracking-tighter; +} + +.h3 { + @apply text-3xl font-extrabold; +} + +.h4 { + @apply text-2xl font-extrabold tracking-tight; +} + +@screen md { + .h1 { + @apply text-5xl; + } + + .h2 { + @apply text-4xl; + } +} + +/* Buttons */ +.btn, +.btn-lg, +.btn-sm, +.btn-xs { + @apply font-medium text-sm inline-flex items-center justify-center border border-transparent rounded leading-5 shadow-sm transition duration-150 ease-in-out; +} + +.btn { + @apply px-3 py-2; +} + +.btn-lg { + @apply px-4 py-3; +} + +.btn-sm { + @apply px-2 py-1; +} + +.btn-xs { + @apply px-2 py-0.5; +} + +/* Forms */ +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-results-button, +input[type="search"]::-webkit-search-results-decoration { + -webkit-appearance: none; +} + +.form-input, +.form-textarea, +.form-multiselect, +.form-select, +.form-checkbox, +.form-radio { + @apply text-sm text-slate-800 bg-white border; +} + +.form-input, +.form-textarea, +.form-multiselect, +.form-select, +.form-checkbox { + @apply rounded; +} + +.form-input, +.form-textarea, +.form-multiselect, +.form-select { + @apply leading-5 py-2 px-3 border-slate-200 hover:border-slate-300 focus:border-indigo-300 shadow-sm; +} + +.form-input, +.form-textarea { + @apply placeholder-slate-400; +} + +.form-select { + @apply pr-10; +} + +.form-checkbox, +.form-radio { + @apply text-indigo-500 border border-slate-300; +} + +/* Chrome, Safari and Opera */ +.no-scrollbar::-webkit-scrollbar { + display: none; +} + +.no-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ +} \ No newline at end of file diff --git a/backend-server/public/dashboard/css/style.css b/backend-server/public/dashboard/css/style.css new file mode 100644 index 00000000..73a0ed9d --- /dev/null +++ b/backend-server/public/dashboard/css/style.css @@ -0,0 +1,22 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=fallback'); + +@import 'tailwindcss/base'; +@import 'tailwindcss/components'; + +/* Additional styles */ +@import 'additional-styles/utility-patterns.css'; +@import 'additional-styles/range-slider.css'; +@import 'additional-styles/toggle-switch.css'; +@import 'additional-styles/flatpickr.css'; +@import 'additional-styles/theme.css'; + +@import 'tailwindcss/utilities'; + +/* See Alpine.js: https://github.com/alpinejs/alpine#x-cloak */ +[x-cloak=""] { + display: none; +} + +@media screen and (max-width: theme('screens.lg')) { + [x-cloak="lg"] { display: none; } +} \ No newline at end of file diff --git a/backend-server/public/dashboard/css/vendors/flatpickr.min.css b/backend-server/public/dashboard/css/vendors/flatpickr.min.css new file mode 100644 index 00000000..a10acc62 --- /dev/null +++ b/backend-server/public/dashboard/css/vendors/flatpickr.min.css @@ -0,0 +1,13 @@ +.flatpickr-calendar{background:transparent;opacity:0;display:none;text-align:center;visibility:hidden;padding:0;-webkit-animation:none;animation:none;direction:ltr;border:0;font-size:14px;line-height:24px;border-radius:5px;position:absolute;width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-touch-action:manipulation;touch-action:manipulation;background:#fff;-webkit-box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08);box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08)}.flatpickr-calendar.open,.flatpickr-calendar.inline{opacity:1;max-height:640px;visibility:visible}.flatpickr-calendar.open{display:inline-block;z-index:99999}.flatpickr-calendar.animate.open{-webkit-animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1);animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1)}.flatpickr-calendar.inline{display:block;position:relative;top:2px}.flatpickr-calendar.static{position:absolute;top:calc(100% + 2px)}.flatpickr-calendar.static.open{z-index:999;display:block}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7){-webkit-box-shadow:none !important;box-shadow:none !important}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1){-webkit-box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-calendar .hasWeeks .dayContainer,.flatpickr-calendar .hasTime .dayContainer{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.flatpickr-calendar .hasWeeks .dayContainer{border-left:0}.flatpickr-calendar.hasTime .flatpickr-time{height:40px;border-top:1px solid #e6e6e6}.flatpickr-calendar.noCalendar.hasTime .flatpickr-time{height:auto}.flatpickr-calendar:before,.flatpickr-calendar:after{position:absolute;display:block;pointer-events:none;border:solid transparent;content:'';height:0;width:0;left:22px}.flatpickr-calendar.rightMost:before,.flatpickr-calendar.arrowRight:before,.flatpickr-calendar.rightMost:after,.flatpickr-calendar.arrowRight:after{left:auto;right:22px}.flatpickr-calendar.arrowCenter:before,.flatpickr-calendar.arrowCenter:after{left:50%;right:50%}.flatpickr-calendar:before{border-width:5px;margin:0 -5px}.flatpickr-calendar:after{border-width:4px;margin:0 -4px}.flatpickr-calendar.arrowTop:before,.flatpickr-calendar.arrowTop:after{bottom:100%}.flatpickr-calendar.arrowTop:before{border-bottom-color:#e6e6e6}.flatpickr-calendar.arrowTop:after{border-bottom-color:#fff}.flatpickr-calendar.arrowBottom:before,.flatpickr-calendar.arrowBottom:after{top:100%}.flatpickr-calendar.arrowBottom:before{border-top-color:#e6e6e6}.flatpickr-calendar.arrowBottom:after{border-top-color:#fff}.flatpickr-calendar:focus{outline:0}.flatpickr-wrapper{position:relative;display:inline-block}.flatpickr-months{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flatpickr-months .flatpickr-month{background:transparent;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9);height:34px;line-height:1;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.flatpickr-months .flatpickr-prev-month,.flatpickr-months .flatpickr-next-month{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;cursor:pointer;position:absolute;top:0;height:34px;padding:10px;z-index:3;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9)}.flatpickr-months .flatpickr-prev-month.flatpickr-disabled,.flatpickr-months .flatpickr-next-month.flatpickr-disabled{display:none}.flatpickr-months .flatpickr-prev-month i,.flatpickr-months .flatpickr-next-month i{position:relative}.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,.flatpickr-months .flatpickr-next-month.flatpickr-prev-month{/* + /*rtl:begin:ignore*/left:0/* + /*rtl:end:ignore*/}/* + /*rtl:begin:ignore*/ +/* + /*rtl:end:ignore*/ +.flatpickr-months .flatpickr-prev-month.flatpickr-next-month,.flatpickr-months .flatpickr-next-month.flatpickr-next-month{/* + /*rtl:begin:ignore*/right:0/* + /*rtl:end:ignore*/}/* + /*rtl:begin:ignore*/ +/* + /*rtl:end:ignore*/ +.flatpickr-months .flatpickr-prev-month:hover,.flatpickr-months .flatpickr-next-month:hover{color:#959ea9}.flatpickr-months .flatpickr-prev-month:hover svg,.flatpickr-months .flatpickr-next-month:hover svg{fill:#f64747}.flatpickr-months .flatpickr-prev-month svg,.flatpickr-months .flatpickr-next-month svg{width:14px;height:14px}.flatpickr-months .flatpickr-prev-month svg path,.flatpickr-months .flatpickr-next-month svg path{-webkit-transition:fill .1s;transition:fill .1s;fill:inherit}.numInputWrapper{position:relative;height:auto}.numInputWrapper input,.numInputWrapper span{display:inline-block}.numInputWrapper input{width:100%}.numInputWrapper input::-ms-clear{display:none}.numInputWrapper input::-webkit-outer-spin-button,.numInputWrapper input::-webkit-inner-spin-button{margin:0;-webkit-appearance:none}.numInputWrapper span{position:absolute;right:0;width:14px;padding:0 4px 0 2px;height:50%;line-height:50%;opacity:0;cursor:pointer;border:1px solid rgba(57,57,57,0.15);-webkit-box-sizing:border-box;box-sizing:border-box}.numInputWrapper span:hover{background:rgba(0,0,0,0.1)}.numInputWrapper span:active{background:rgba(0,0,0,0.2)}.numInputWrapper span:after{display:block;content:"";position:absolute}.numInputWrapper span.arrowUp{top:0;border-bottom:0}.numInputWrapper span.arrowUp:after{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:4px solid rgba(57,57,57,0.6);top:26%}.numInputWrapper span.arrowDown{top:50%}.numInputWrapper span.arrowDown:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(57,57,57,0.6);top:40%}.numInputWrapper span svg{width:inherit;height:auto}.numInputWrapper span svg path{fill:rgba(0,0,0,0.5)}.numInputWrapper:hover{background:rgba(0,0,0,0.05)}.numInputWrapper:hover span{opacity:1}.flatpickr-current-month{font-size:135%;line-height:inherit;font-weight:300;color:inherit;position:absolute;width:75%;left:12.5%;padding:7.48px 0 0 0;line-height:1;height:34px;display:inline-block;text-align:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.flatpickr-current-month span.cur-month{font-family:inherit;font-weight:700;color:inherit;display:inline-block;margin-left:.5ch;padding:0}.flatpickr-current-month span.cur-month:hover{background:rgba(0,0,0,0.05)}.flatpickr-current-month .numInputWrapper{width:6ch;width:7ch\0;display:inline-block}.flatpickr-current-month .numInputWrapper span.arrowUp:after{border-bottom-color:rgba(0,0,0,0.9)}.flatpickr-current-month .numInputWrapper span.arrowDown:after{border-top-color:rgba(0,0,0,0.9)}.flatpickr-current-month input.cur-year{background:transparent;-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;cursor:text;padding:0 0 0 .5ch;margin:0;display:inline-block;font-size:inherit;font-family:inherit;font-weight:300;line-height:inherit;height:auto;border:0;border-radius:0;vertical-align:initial;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-current-month input.cur-year:focus{outline:0}.flatpickr-current-month input.cur-year[disabled],.flatpickr-current-month input.cur-year[disabled]:hover{font-size:100%;color:rgba(0,0,0,0.5);background:transparent;pointer-events:none}.flatpickr-current-month .flatpickr-monthDropdown-months{appearance:menulist;background:transparent;border:none;border-radius:0;box-sizing:border-box;color:inherit;cursor:pointer;font-size:inherit;font-family:inherit;font-weight:300;height:auto;line-height:inherit;margin:-1px 0 0 0;outline:none;padding:0 0 0 .5ch;position:relative;vertical-align:initial;-webkit-box-sizing:border-box;-webkit-appearance:menulist;-moz-appearance:menulist;width:auto}.flatpickr-current-month .flatpickr-monthDropdown-months:focus,.flatpickr-current-month .flatpickr-monthDropdown-months:active{outline:none}.flatpickr-current-month .flatpickr-monthDropdown-months:hover{background:rgba(0,0,0,0.05)}.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month{background-color:transparent;outline:none;padding:0}.flatpickr-weekdays{background:transparent;text-align:center;overflow:hidden;width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:28px}.flatpickr-weekdays .flatpickr-weekdaycontainer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}span.flatpickr-weekday{cursor:default;font-size:90%;background:transparent;color:rgba(0,0,0,0.54);line-height:1;margin:0;text-align:center;display:block;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-weight:bolder}.dayContainer,.flatpickr-weeks{padding:1px 0 0 0}.flatpickr-days{position:relative;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;width:307.875px}.flatpickr-days:focus{outline:0}.dayContainer{padding:0;outline:0;text-align:left;width:307.875px;min-width:307.875px;max-width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-wrap:wrap;-ms-flex-pack:justify;-webkit-justify-content:space-around;justify-content:space-around;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.dayContainer + .dayContainer{-webkit-box-shadow:-1px 0 0 #e6e6e6;box-shadow:-1px 0 0 #e6e6e6}.flatpickr-day{background:none;border:1px solid transparent;border-radius:150px;-webkit-box-sizing:border-box;box-sizing:border-box;color:#393939;cursor:pointer;font-weight:400;width:14.2857143%;-webkit-flex-basis:14.2857143%;-ms-flex-preferred-size:14.2857143%;flex-basis:14.2857143%;max-width:39px;height:39px;line-height:39px;margin:0;display:inline-block;position:relative;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}.flatpickr-day.inRange,.flatpickr-day.prevMonthDay.inRange,.flatpickr-day.nextMonthDay.inRange,.flatpickr-day.today.inRange,.flatpickr-day.prevMonthDay.today.inRange,.flatpickr-day.nextMonthDay.today.inRange,.flatpickr-day:hover,.flatpickr-day.prevMonthDay:hover,.flatpickr-day.nextMonthDay:hover,.flatpickr-day:focus,.flatpickr-day.prevMonthDay:focus,.flatpickr-day.nextMonthDay:focus{cursor:pointer;outline:0;background:#e6e6e6;border-color:#e6e6e6}.flatpickr-day.today{border-color:#959ea9}.flatpickr-day.today:hover,.flatpickr-day.today:focus{border-color:#959ea9;background:#959ea9;color:#fff}.flatpickr-day.selected,.flatpickr-day.startRange,.flatpickr-day.endRange,.flatpickr-day.selected.inRange,.flatpickr-day.startRange.inRange,.flatpickr-day.endRange.inRange,.flatpickr-day.selected:focus,.flatpickr-day.startRange:focus,.flatpickr-day.endRange:focus,.flatpickr-day.selected:hover,.flatpickr-day.startRange:hover,.flatpickr-day.endRange:hover,.flatpickr-day.selected.prevMonthDay,.flatpickr-day.startRange.prevMonthDay,.flatpickr-day.endRange.prevMonthDay,.flatpickr-day.selected.nextMonthDay,.flatpickr-day.startRange.nextMonthDay,.flatpickr-day.endRange.nextMonthDay{background:#569ff7;-webkit-box-shadow:none;box-shadow:none;color:#fff;border-color:#569ff7}.flatpickr-day.selected.startRange,.flatpickr-day.startRange.startRange,.flatpickr-day.endRange.startRange{border-radius:50px 0 0 50px}.flatpickr-day.selected.endRange,.flatpickr-day.startRange.endRange,.flatpickr-day.endRange.endRange{border-radius:0 50px 50px 0}.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)),.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)),.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)){-webkit-box-shadow:-10px 0 0 #569ff7;box-shadow:-10px 0 0 #569ff7}.flatpickr-day.selected.startRange.endRange,.flatpickr-day.startRange.startRange.endRange,.flatpickr-day.endRange.startRange.endRange{border-radius:50px}.flatpickr-day.inRange{border-radius:0;-webkit-box-shadow:-5px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-5px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover,.flatpickr-day.prevMonthDay,.flatpickr-day.nextMonthDay,.flatpickr-day.notAllowed,.flatpickr-day.notAllowed.prevMonthDay,.flatpickr-day.notAllowed.nextMonthDay{color:rgba(57,57,57,0.3);background:transparent;border-color:transparent;cursor:default}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover{cursor:not-allowed;color:rgba(57,57,57,0.1)}.flatpickr-day.week.selected{border-radius:0;-webkit-box-shadow:-5px 0 0 #569ff7,5px 0 0 #569ff7;box-shadow:-5px 0 0 #569ff7,5px 0 0 #569ff7}.flatpickr-day.hidden{visibility:hidden}.rangeMode .flatpickr-day{margin-top:1px}.flatpickr-weekwrapper{float:left}.flatpickr-weekwrapper .flatpickr-weeks{padding:0 12px;-webkit-box-shadow:1px 0 0 #e6e6e6;box-shadow:1px 0 0 #e6e6e6}.flatpickr-weekwrapper .flatpickr-weekday{float:none;width:100%;line-height:28px}.flatpickr-weekwrapper span.flatpickr-day,.flatpickr-weekwrapper span.flatpickr-day:hover{display:block;width:100%;max-width:none;color:rgba(57,57,57,0.3);background:transparent;cursor:default;border:none}.flatpickr-innerContainer{display:block;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.flatpickr-rContainer{display:inline-block;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}.flatpickr-time{text-align:center;outline:0;display:block;height:0;line-height:40px;max-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flatpickr-time:after{content:"";display:table;clear:both}.flatpickr-time .numInputWrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;width:40%;height:40px;float:left}.flatpickr-time .numInputWrapper span.arrowUp:after{border-bottom-color:#393939}.flatpickr-time .numInputWrapper span.arrowDown:after{border-top-color:#393939}.flatpickr-time.hasSeconds .numInputWrapper{width:26%}.flatpickr-time.time24hr .numInputWrapper{width:49%}.flatpickr-time input{background:transparent;-webkit-box-shadow:none;box-shadow:none;border:0;border-radius:0;text-align:center;margin:0;padding:0;height:inherit;line-height:inherit;color:#393939;font-size:14px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-time input.flatpickr-hour{font-weight:bold}.flatpickr-time input.flatpickr-minute,.flatpickr-time input.flatpickr-second{font-weight:400}.flatpickr-time input:focus{outline:0;border:0}.flatpickr-time .flatpickr-time-separator,.flatpickr-time .flatpickr-am-pm{height:inherit;float:left;line-height:inherit;color:#393939;font-weight:bold;width:2%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.flatpickr-time .flatpickr-am-pm{outline:0;width:18%;cursor:pointer;text-align:center;font-weight:400}.flatpickr-time input:hover,.flatpickr-time .flatpickr-am-pm:hover,.flatpickr-time input:focus,.flatpickr-time .flatpickr-am-pm:focus{background:#eee}.flatpickr-input[readonly]{cursor:pointer}@-webkit-keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}} \ No newline at end of file diff --git a/backend-server/public/dashboard/images/404-illustration.svg b/backend-server/public/dashboard/images/404-illustration.svg new file mode 100644 index 00000000..66e4268a --- /dev/null +++ b/backend-server/public/dashboard/images/404-illustration.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/backend-server/public/dashboard/images/announcement-icon.svg b/backend-server/public/dashboard/images/announcement-icon.svg new file mode 100644 index 00000000..6f6d57eb --- /dev/null +++ b/backend-server/public/dashboard/images/announcement-icon.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/backend-server/public/dashboard/images/applications-image-01.jpg b/backend-server/public/dashboard/images/applications-image-01.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3e814c4025a5184eeed8f50b85d6ed0ebf36400a GIT binary patch literal 59710 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.U4DeG}vo8(|i?!h0h(xtJZ^ zxluY4mnDx$JW>5tdRxTN^T3#DY#T_zXM>R zV~!dY<-3Ze&zR$KzI9OnFu%pmMPulYCtN; z;4?X8Rm&1IGLky9RcO$mT6GW0{cwG{ja9SicJ(aNR_|5*h76ZSq@FySeg|8X9`Tx8 zj*_lFzFXI_yjV%f$eJ(ncJ`&zg{U@+Dl+3S7?XcFS%d7(+n(^mNLg*9w7slf2^MRr zd6@Ah;JT7_J9?Yc5o5vFq6o*rO1vGU8#~nb24d-22T9fU8_5tda&K~w8qaXo|KvJ~ z!kD6fFKHWG^;jaBu6q$}GA}d!@arIPguY<^0A>kLbp~+1;0qHK3D14d>c+?=tj+Oq z`1(&VR-&?(w8f22$w)jmLo#>`cG4fedPCAH5>C5?+-b3@B0s94&jbUu6hwU9X3?x@ z1{t^eQs|b6oT7cM_`*7K=ug5MUH(}W%9Koh7jS#WpB@s%VU=ZBb16zDas&BP8D>+Ms!;;U@*ECw7cbE< ze{4o^xlq`$8)}oXn*g_4n7B#uTo3zAb25%N2-QRoT42T9R`?ivZdoZu62u+6^*fLC za4@~}JzNlLp1@ytoTt5nFIuVpDm5IePT{|S{agm#=jiq<%`m>UT;eOyR*(-nLaB)` z`@jn*BYMtcdO+mMco9_ zbxEViQy^TQ&zdy+rNMUtpC~wU2Ya?>yRPvu5x32$wtkyJ$8ukOLaCv4q}d6D+7k&+ zrZBTkldYHhx~X(EK5qITrr!ShXP7#8+f*Yg#a8kUGOIyM2mPEj!3g~Q(&a)XpfXVK z!V}jRXIkT~kaimCNY73!d1z7&@@(kB(wG#U-cceth{vF804fU37i{}A_%%L2`~}gR zo<1i)weFOk;;$!D0H6jU-e{EmCO^Ubvj7<=2IGR8)yP09m-zPI5E4qQ$G=PHEhbVnjWniT$JZn66j)c}H@6J~xXB!%aJF9ykyML&ey|sTlG~}z3S!|)_XTB`+ z40umfVR9qlw7pR%`D0=;=fhMjkG?&3k04d2^$7Kxsn%@I)gkY}OyUx$4saGgNo`zV>n-$%ME+H2GZf(STs2JZ>1*?XdVNd`qD3 zK!2}8$#qRV`Q(xcHWy+CT|>A5=&hK@u! zxUveCJaLI>r75O2UmjIV3WmYL$bjrnFC%3i!jfF9H&V_4@Oj!f?Bwk)hjUPur3159 zVDr-cUmB7ClExH|%&^HuKXub~!;>dnk9+`GOS|)jyB3FEur^-m!K!Cv)glR3bEPhb zI|gx4Z2y-M!C)veNUHm$Y=27A{H0&D%u+}8uc_cjF!&t9!?y(!}(%XS&FhYxs^(k+E9F=qqc`ZZ3e-6^|~;$wxYd{lF@r)D)eeBS1cvryvS|8m{Fx7eCGjy3n(tj zgYDI>KUp-7qHMAz%9M{^LwV#0=TMIU;#H^L6KGXuQ+YXq74i4x%~~=+SbP5#XQK=? zi$9kkMFYwao-y$&fg5xV~GU(^dQ16 zLd6vYlHB0GCRO7&HzF0a3uo7#LfXK-uqJzeObPF1Cm)>hocaslu#6P_DX9}<02Y|y zi$ED=^zhZ-rRyO{$?`Y^$$Xe3TI34j=0cdhH4fy2&;Bp99@cKhj1yc@ky;@fYB z676Vt?695O$J1?RwAAw~%Mn_a>ESkd> zBNxf*i-Su?;k*#m&gRl<^sxaBYRUhg#pCd^wrLh~H|#xIEclBpyY?D`+AGh*#0e%;|{=f`#y*26ekJ-M~; zh5_KD-u=w0|I80q-E*%7{{_4w%sGAIYDFeVowl!(rUkE&_%MJRWph3L>3cIZ+GDZD zA$s7yIr)oW+VqM8lGbFE2yEiQhU*;WU~3PFjGTPIUoX0ieOjZ(bu2Y4F0BtOUlpi$ zHA%)1zQL)GH~r;HC)hE4TQuJTyfv|a^UbV`H`3FnFR~!1U9{g%CG>{>0r`Rbi8xeqRh;Cn7~yZk_eCl1vg+j>62CLCQag3C zkrKv@w;-*yh!rZ5C#?PFOgNhhm}@ELC{^2os0hZ}HpRp}1Ja7IsM6f-4nNW?Z=7$V zORkCxkFYbz*I=ph06A^B-6nTf4XS=4#chkh-wz~6#{yTiNl|Tl^AG`HlIy`tE)gtY z?1shv)=wc^eWdQozg+i82$uJ7ZZa=+6PhAUUR*>rPFj?Hd7KHefv|*Yi*DJCXv4w~ z=*4H-8pEEPYt|HhYZ&-NG9bZU2i34OX9x69A|f@!Y; z{q;GeXu;0M?d0+=p49lz@Q)>`6GtzL-jeCSzV7o-W=`U`7Jd7`zi|CF zM?pYoA{iF8<4?Y+bnE3AM+V_12QNO=K7%@_4tPj>nD*MyjsHmY{dvz5sRGqmYsp@2J= zRi!ruprIPPA~CT1sf=75M|h70nRCOC(^Z5Ou`k5|@(YD%PX}wm*is?BC_3IZ6b`*r zV-^l{WFiWvD(h3BT~S{RD?;oN6N#AcFCI=b``b!&Lt!nP7ydz8Q?+_1C3pbnI8s3NaTV8h+zKbUtW#z)OxMm4*fPH6Q=8plO2U}COwTK93gWH)?0VZTYNfUjS^q%fDWwK`7-Na-OSf38l%x;Nbz3@!S${l-i#8sV-qnrW=79ohFZ+x30|5!}c5U)3T>P31#tjejM9R zv2}&zPXyd@+c$LM4=w$yfCJarIoh)9C)h3Z1Qqo zJy~(`-zOPfY-#_n;t;|WPJe%`YI1a>8fllP<@Df;o8UFx`he0NBPB43z>pWOV=zOb z!5(=c`=$9ShE&@Wjl5^RTgmqi^A0)&-63~XI1Pp&w=PRY*n<^G@8AJyx_ZT<-$|zc zpjl`NbCE!~SC%T~CPCE6R&FX!NSgV7LBs;oU<=~^smv}Fs;t@mB(uze z3~M~^-s&nNS;$$-RDWAUp)yDwL|M6%CrpAxNYSiANa+J~RuaZuU^$pMr4jYSM-ihV z^sW7Iq~8H-71vK6$#v>iTAjHWAHx+0BlY(*8;hX(uYmB24DB~k78iz!w2JO(gEAEg zBQu3%vHQFcSgrJS4nF$00cuOMVQP0KZ|-Lb)DK4{BZywaO#eyN^$CtJb#~|4It#!| z*)$n=qn)VDT{bN%+jW=q2*9?T+ZirEu38Icy)hM*!=<-KK>tx=K=Lol#KlH{=)O7#gTLBx$}d?{oGc~=JKJdgHO$*hYQyC4#tLp zuE)J8jrL*W3{%QbZ&>qONxeoldSA`7taNUJlC1^>8VY&8bBKlxb; zOuP6bw8wzxsdruvIN3pd+--#K*Ei$2M@i^)+D_>ycG5p^X;#ixNmDl+XH))@h{&d`JOaA-}e zD2q%{U_X8O&I1l{fWEl(cP+_>)^uEZ^V>@60)$HPhJzgklEcbL(~5DE)PUunQAd;3Av5(Mis)ag2u?u6ZvMputE`|wsEPaF;zhYOfq5ArU0DfBWk{&t!((P$8 zR|Nv1H}|@-F9aCn?D654px=^=`?jeTeN)D%7adAr%llhXI=faXFTTS zK!G`ZM#@rq*8xacy76<;4s?w)*UB@}rvU^hwtehvnf3O+ZA?mFgd7y9%NL+@A>Ig2 z|F|bh4DE>)^+chcPdX&!9MX_T`IU8M2Z%*6zZIAE^MIM3v;~Ac$BC#4WwJhn#UcN^ zW!r$1qACA37~jf#fAU{Gi*UHAAR>4Z=iD%^Y1XeQ#-P^iU(}!BJC({4lF~kA6=?uKeA>I1J_~LVC z8DYO;QjDp;&kdye$mGdbjO9GhmB5w(yMAeIAQFmjUrbd?zdE}fv{!n~66qdf`o_sd z-Z%rgYujm48`%lW$#*%49sYJWe z+on|d6=tP*w1SSC;N%Xp z(iVOKkiPC=9s-WX$7(-eF15*O9B&59*^lHOBV-|W$y?n8Q-F)^h;uFSI5*{|df4&z z1OajNc1z0O6+33bO5XG_=Lqd*jKzL+gsIDwMspcDo=~13yYnh6qfrW-eYmJdTuDo9 zh_p{|AI3+h@|_>w3^L(daxC|{h5;#n={6i)B@WPE`-c63WYg452R^xCFT|%IOtZvEzaW{8 zH|X%h_xrq20lJx59A%0Ct;B>j1Ib@H(G{lTck1crAdIyeNH7FN&KQ{CFIwgM!H09sfIlIUBr9 zgOY1)iRAT#AXy(bQoiUb|9p6wjC2A0O4{>XKf6?h4i?tm=nl`Z)HM#47_ zq;O?-UYvC%;ZL)_{M;iE`U@ZdcQ_#Rh(k6~PS!39LW-}Tc@{X*jIZlPhR9h=6P#l4 z7zho_mIS$0z25P-LXQ~?a6WS#SEk3Y6sVys6T#k&acva}5+;5E!o-6RvO!jxNBfOW z+v@fi%F;p7{v=@bJvmN_dUYrk8scZa2oB{+36|*!*lrO24aButdtYVsgda|Vga8E~ zOIVP#haWK@&wr_lxU^$J&xvH2`zfCaL+1k~Xw-nPw!bee211VETMJ_A- zv-_>O3)`@1SRg%eWr!1#;-r|d2fu=^Lwah)?@;C#@O1ErEcsRv@HpHv=Eo+dl$z3hT0=Oi$t1Z02lPJc163U-QIzUe=CdJCC6ztO!4REl+*&}Tc zUwUw=aiqn{Gv_O_Z5ZI?pZ33uo>d)$&%J$XeTWebEVl0cR81u)qYwNJ3S|17cZX{~ z9j+q-9{qkTCZs$@XEm5B9hF*n+8_3GiKz^>$qlR-to69+iH7~^#b>f=?uC_cm;f6g z|J>BrWL;mPhHUunXjQhjFkZtE6=$SO_OTp*C-`cX^Oo2rgE2KS0-Ww-H zTl2KXmkYd#OeR&C_S`M!d2H7 zI=kdeNQ+QL`l+CcV5Fv(ErRRLaTgXqf;#Fx&C|}SmFrPBeTZc2Ct}B35;XnS9$iKa2^#hhF^~Vx)vjNF=Q0pyPbR8m1`%>$wJoXJRlxP;*a8 zZzw^39QN@j;#7vQvoPy)90L5;4fw;KJpqrc zCzIVn0^YN>!cNi<;HQlYc(P=~voReN&NT#X3L;0U(HgjQX5(F%-r;0nd3y`XmE`Ze ze7TePv5P}6!-K%ae|C_RfA!!S7y#$-r4YQ&v^UM_N{fVx;(i}aE(-#~8{GJhWB^Xt zezMHh=T~XN_|@v(*Al&{|4n{&1rsQAAz0?V{7!o~CxSIlqc1A1k3MbQm8c__nFxyI z0O|nzJ&FaztC+=7Nr%(|U@&On9;$<%Pw^cQ?l&BrV`k#G2*o>W_TOC8kEx&H%`5V* z6CR$h`Ta>X@Nknqx=$#?YE!l4r&;+f_^kmp%ZxTRU~-ib7o^fkXQsT05LB@nun#Y( z1nazqRAjy;r~$A;#yWD}6YZREqCgMvh{Uk+2kIcSVHH;&GxY?hd`_ACZ0@ku2KQEA zy|EIEtX5gH4Djp#cC*9%JhC)}j2z5vkimYQ@P3#6nM~R!Z6kXlmy-jgRfZ6b zUk~p(W~)N*^(IUq$(Zq-%1MSBXl+-eYCH%3sNr;}46iF0-~f<+WzSp3Vz=i0w0-Ns zx1Qs+bq)_j9}p|JTxYp_F&i+y{5;9j__y;l9P63$vY5HahV$RNi0Ne6A*iM_RqZj= z9fWfERc;PqjSq%a{jfwh0|`-}TF^u-w{rhlI5XjlE{&3?Vx}MceZ6s3QWPx_m6ZdZ zH&O^1!H6;pa@8@K4cCN9oGouRgh|rL))0rp@2?FcAtP_P-f5{cdCZSqY^cRa(fO}W zqCBJaS)G+As)?z>Z}s(U+B9q#u6B7CmRo&I*xtv;SBaQT+?Ik`Kq->#3ZDbA z8DtR>5ZNhZ#!BhJc-}wR9*oFyk`)iGYhur2<9+QeMTjpr^OB_54Zl9gd@jU&PZreM z>&R++aTI6MI|D$G^Rr;|w^}%A;Mf1^4*u_19`S%C8UX{l@>X2j#{wYkWFiJnT=q7g zNx=={GaWHYl^7GYr_ACV|Ngr#A7h#Vs{m>H<#&_cMZAY0+B8+DDkKO@jS9pX6 zoTmicKj)t^V5+*4k<7`iC)vZ@=|l*uAgSBARXH9h0NqkaD?Sl*Yc~dmnqR|{yX71z zAaTrp+!R-Yh*nP~A;lNnJtAc!!2T`NF19n6AhVz3jC}IKSBR^iW_+z0ex4AeK@(KS zZS!H6L>_7H?0HA0f+M*{J$L+(%?d}6Fg!6e=5hbI?sGrB`=T~aYriL6C{jNq1FrDI zK1ZUYsi6EQ@t`L+>NXU6HQvPcMbotK3)y9b^sXupRJ1SZm0Ggo(J62O!x8Algq`D@ zHzCs^wOd|MKET<`@pWHTBHFqxcEBhGsWux1KVy1p9~RF*$h7;h2~k;-+|#eOGCR6G znWxoR?FV}zmHPPqj^iG&`dl*dt8VzlZ2OME!qUCgH>Lnn*PGfVZ3f43A;#u6Pq>0( zbEDqsR}V01y0HS`vQcOMPvb;0Q1_wT%JCY_^-Gz4At87$^r}6sMFYCB-P)LYNGMRs zzNr}%{>CGm>{)@27I!da=HN+vY4@hdZa0mX_8cQC_NK9aCSgolSy`$2dO+U(t$FE? zNd3(%C%RW*P}f*bJ(x%^up`SsSJ>l_^-RG;j-dLig{}NowU}Vg)i7 z#(x>N3cMnf9p=oIrtLRfbbsHzsT3*xUJ4aZeif;iQ!qG^10?kiO5Cd7|NBHR-G&_m z@4)M5r?uS3!OhfTq4YOo*ezFv9_Fd& zGhcg}bqa6HOv0~Ud>#O%uRr=^CG`5w25#H@5|it@vHd&p12n$avUzXKUYB`fl0gGEaEZ>(fRvbl9{4dWns;LWF(Yn((OXFj%SXHZhLHk~87Z%14t1cT z1T_T~+imG#=lI!M-6+&I$K&OPUn^$?vFH0?VJw)cW3wV(d|? zEx$3yz$F+~{44p3(^l$mKTwX;`g%zm_8p0ph)VNNhCC_w3_F>phNO6Im!qW1XH17^ zWdaAJoPo`%$CEZ~c%P|)iO{Ov>U|_DNjM`>0U1#t77BP{Nl8l+a4*0uxFoZDr;{Ru z_@El+Xlp(>}|H zUNcF+A*b++8}Ihz0~@Io=%wT8Se{mLN`}ST=Y9XUc~qbRnx2UthEx42iH#!vZPdp& z=zc>)!t#B#!xlC`0D?Nwesrx>%+RJG?$;TQ+wn58fKy4d^Vx zZpRA{g}?pgh7d$64S(R|qw`bo#^T)57qSq+r5EFAdYZN`A2j~|J1O^?9+E_#O0`-) zz$nUUkfBD(xQprDWG!#(R$IRg>~Y}XV7-x&2+N#Zg74v1*4C3YV7mA|6KN*lk%N60 zZN^9Ie2)tHS=!zc7vF^)+|5-ezkYBqrp6$qDZ0;O*L-?Rpp>R3p7mM)&HGE-gc+}X>CxG^=I0`GF~1Rh~`GG zdM$f%P?V&PX?&*YZMkgefL6g1Jh~d^6b1_v0_fIkG2AdsY0U+M2k98d6VEGVlWXqPJkB_Xoq7V08AGsU_UmG#8IdZw1rY#cY{pi7lA}c=F*Tt4igvYhg``?4=i_h5FSU4X&gS1FC*0>!1zDkl)A zO3Mo5Y1s2?`t(5?392FKjbqqjY4F4a?~OTuj`29d8(bq3eK^z@JR*z1T;x z3gF_h78en@s#Tlp@um6mg{fdTch5UQGs)~Y!eIsuhQOg29WVFBj$~;S8FgOl(iPFc zr*Kd=M1EH62{)vfuGGQr7_21hLA|s_B;2s|mpw!H5 z${=$I@UyeL;23)g9)@cr(#l@BtGmY$a7}4OOEAlQfJ6g_l4Cn1$priyc_O~By%|-I zkf3nw01Lh_3^-M?qQCnR5C*0(49a=b0*4Fm$9vMx5ELP*vd> z_dNsOm8Z~1tHUE)KiUg8UGuQxJ}B72*hy_4xE(7E;FCD|-c?OCDy{oZ8XmoS*u|!s zbaCx%-eFysNiKLvBYH9Rh`k#Qntk(n3)>m_iBed<=)~M$;g=O8T^;Eb*TG`HGC4w1 z0YllwXzQNP{G7U=v19vym=1bmf7r{UDXg_CK*xbJ{Sf(h1oWt~u`UP2a;!;=;s5#f zZ2Z>zyudYAlJPn2^FbSWw*sJo^6jchpK=ip<8pt^R8N>v%gX&CM%e8G$gAwrecn`Q z3H&s`!iW51Faxx5Z0=MYT{7VfCM7sYK|QSXV0`58OIXwjE=N?n`OPu`s_Q}3X5jc=e?kA=$~x!` zIK9EJKf+c#hSg$BNl#n(MfW*O>!8do7xM5$TM&CxaeCpGWpV6g9Mh4k^94qVZys&h z;jTtlW!sF2vAz&tdw$QzKnf_JKrj!_tbjzCKSx1cOMf@OeL^GZr%s!zwNg+c+vs(- z&mcf(T+9nA<8R@8Nc{53sX5`>ZTTW6eX3Gs8>z!H%nsDO9Ab;`|B#3BugM#=Sam=S zm+Mz3U2wl2ybVbc&6J%Mibml^hlN9lpRxG@AS`?+cU_|cMG%V;XRez+CB+SqlFqar z?;#MP@*A0o%Mnpi*)&zWUW+gK_*)QxZ~|hlNCZM%y+WWMnT%;qUq2ku>ZaHaFYg9- z14V-5?h&Pa#}Tfx_9J)S!?zqG(1phZHe8Te6g_LBqN2fvyt*tNxTaB&$onNr zGX7JP^DtBdx&mH1YGRW^MT)+w-lW}s$(usw=(yD<9Zah1$n(JUnG~b-$S@IC;CrA0(g44g(rJRt|5F4 z^uIH3`0RgIeNT5@;y?p# zwkf0j*&|+|pZ_FbA2NWkm`K}L0e`9$c-94v&(@42SyH(_;}3+j{M1I^E}tcj(c&ahz8$_c0Egw^ z7NWN;ubO#YV6yH>??seJutMIB-6+R!S_IOclyvY{r~{-bv+4GeptrQBk_M=7Pen&c zEO8_S@e`CZ(|)!az&BHStNlnST?PkF{WMEft35&%xW@~|y$ZEKhDHU(2e5y^36_)G zb}-NMQFC~t(>^9d0~a`=%wdHp^oe0S(ypb&2GxywK4{~)$3(fq zz|n!GTrS(E#6X$pHL>UwxP*<7Pu{eFg2PF_DrMGWm+KtE0*!o*7hUl{qf((M>0mkr z=%MBZw|d*nkm(YfIR4I|Mk3I#;2y(cq;%t|XSy7ahIRrkOIx0K9bb=X!ARD`Ag@rSgApM7`Q(KhO?~;qa=tnIT@sq5$@5S&jHRrKEk@) zj`U4nWF|I|*ffE85>%9x{^k8m+dNTRVOOLiLm`ur#a&tbYA)vFpd?4(4{JAg&W!vDM!0vI^4nWp%pDFVIaKxx#!S6M%8%-iufW zc-q-pc|ANLY2$4x$gEqcDF@SS;*q}(qW!x@@5_{#V`kd&Fu1ou!hG|$h^^^Ib|eJG zywc49eRq#tObS%kK+-N=nU&xMs7>MU$q$679<~W_;BPb(T(RY~v)rL)1)eu$T2oE4 z`auZy&`-0hOqF}gzBCE-)up~r&KblO>u;JOj?__}&B{=dz5n{q92!Ti9m8{UQc&zd-;JfM zX;e11;^Z*9A)D)kNHN{}-1(kFA+_FnG1EfC0$-5=;v3;?L5GW|igw;&fKsT-ZI z^6Nk?(Tqy9E{nuGEw4hXP%Ql$<_e}!)TQio*io%?ZpHu-Wz;MJ@;Snp3eFrwxLWDE zNe{@I_~<~*%pTT;hP3OJj2eqs3*zAYm2W_D8g8c;pz4u`Upg-?Ly5cIku}?CUj2 z{g9BvjGuu0fF2QJUOJ#}DOy0Uz-Uw6K~X}m!Om#>jlh8fdOZ*s?)mBleh$sj_5fCxtDneKc<5ERL2oNAbfKgdOh!99JBpGJL---AAy`T3#l#ooG z=RDtY&i8!Jc^E!O^-k~F)22!p637to;bT7ixIZ}*GnHrJD3W{Wuyu~E_n>>_`?UNE zwTPK*q^>G=dDy521Pr#h^)Et2GO|g#bTr_zpuXx6qd|@nP;F0EAK{a%MiEzuU z6n>N5LExR|A(U_lR1{+KaHp5h=Nv5 zm!ktZxmr;Z`gKiRcG_YCP%g2i=q}QVL1KdK zGjOVKd2e&EsIO!45vzVii=H4OeL*dvA2`pdf~#}u>7@gEV~)k@Ovw>%i$z3l-vd#n zVa2ax3~ZNlxk~*ys|tfmkfgPsLexa@VUEDC?+T*Kqm4Qj;t<^@kvpmf;Xa1YV-KlSc_49H=wlnCT zt()6d(m1(oN#7VQGRn1{cRf#eX5XrGUYp~fsr%$&OmM~29BVW5+dm4uE0<`%$k^sc z-!C=HY8K5eQOLO>h=#wN71Mc?V1B;s?v8Aju~9fP;bJm09m2d8PiD`Z7l9u*m|X{! zvw{(k*-wKHQz`W3dBw&Rfu2eHC@TGGqW+aeT#1Tweo~XrN6;9uGKj^in{|YsIQrY% zLaHsP;=Roo?)8Fco6&oS^(ZZ!@lGUy1OCN^4YNc0+c7yA1dOUf{7PQKUm}mkr9O!F ztEYv#qNxenK@d^Rd#U*Hk0?5h!q~&kMKYeo6oC~uo!S;GI;Dz+9(19p!mY3dz6yk% z!EUTg{+2=du(UI-b9aUSS5hvcmVTx`g%&Qt z9=_2H0rSHMmXCf?e9W4QLk!8<){IKha526UreH_~aS#o8;K2`$ZULd2R0uGVw^|&IKCFX(cEEWYsMDWCDHIGbt2f_O-$ks3FA~PrY^M#p9 zE!)4BPDTm(G^iXd&G2q|0WKB{#SVYj^w)Cup_OCa>7dOO)f}#ZxaQ5vE<9gYt8;$6 znPq_G`eaH>kj4S z-xvddaz2WzxyW}Arg7b|?c(A{JqfGPN|i4!baQ~RE%s7-M|9jB+9pn+^@}#hTn6Ys zfpFt5eNcXF#fMERwBt2dW!u67teKyIAlJlG?qJ;*<-_Q5`+LDIJ`($7mNG z(>EC>TL?>3@M-Q|hfXy`iWtn?+W#!f2t0s)Ta>?kMeW9;=dCEt#a_=}a!5-u5>;`t zCj5Xs^fb#O$?n{hn3mLYk1gd3x`dD$gGdyQ4S)WFeI(?8J#m_Kz>Gg3755s>fuWKO zit}7hfHTOO^aNZfO5@d{KLe1Tg0LcCta_;NvR^R8%%14Mb20d88zH1|VX&JU)kjtN z*X8CAV?l&Yf}@(5Pa&)9%^4G0{$0a{T`U+Kor9_8cg;o@30>!JbUKDe^rIeCsjF1* z+{2>*Rqc+uKq^jJ*iU6I<9Z)Kyhq5p&(sG3+`!Q?G#-rh1Uav_^abrJ)Nc*}uK*7v zhD|@WrV;f6GYHh>)`LHQjj1%Ejx!s2+575s)rq)j_+8k7m0%{FadDFBa^-jlkYjb8_c&q(ykJf3SWr6Mum|)YOEx7O?5EM_Lp6(J!k17|G=3 zJz}Ji`%F%tN0X#sb(n1K`ehHtD-s!D>iTVm>O7QO+ImI@ z@&Sz5@H%=HCX+)AjQDDo6tjexDzSg=V@0B4_ozuT8G|m8G~k#g9r{H#y9l5jl}8Sq zSPjK45l@+?UJx6r6j@yb7fdwnVRr5`Itmh6WldP&-MXNl6ItNs>EDU$lCSAdvv4L; zL=knmV01f!J|~=~{Kkp@P~I4zmk(})GvT4rj~Rd6U!r@7R$Hri>lR@Hj!Yom-B0z4 z-QCei|G+xFsQQg7uHr&MaGhM;bo!Ozqf^Kz%4SMzTwjdx4CXC%Ju>u7!wvQ*r@Pv` zWj$7BTL0cAwdP~g(>P_af-zWJ81%w-PY2CeBDEo30}Lc-*!b_wcLf~92?kxrmJHCb zQVKaT@5{XkfbR)SORyNG2V=>5)}~@y1@Be@k%|T1ef98WmvB z0nn;sWHD|bg<%!+r1Uz_GIw_fSuf5qv5;!q=@oJP#>6gTnRlX>@lLKZkfYS%z;*qY zSc;3V}1Rz-Qj@jAJM37K>iIT z1K(E~z{|g$h)c9uLx=VbaQvET%R40NP>NN6(4mI%bpEKB0 ztQo8FCi%4K5TifP@s-g^hyDq6zVE2#3L)kJA@tbbBKP2Hv9sN*QH_N2;zTYjJcrb1 z+x^xxi`-$0g*hbDX*{2yXtSu-^QOnpSeRZquwIdnZ|!$Nwl@K`O0-7B%l4IBN-3c+ zVX~`wPK_EwbHc=u5C@6Yk|6U4FTMd-ZME5XJohg$u2#T9V9<7`*-E3_3yMjYlCo2d zl#c6osJ3!@SkI1{et2IEQXM|$^bR)9Nu(q!_PHH+JcXtyjGC^yE8ZvwrbN+4@2Uy* zu2CzsW`L%}qGzxr6P3MsabQLgmnuZE4<=5QJIC*Fu&Y# zT^dx8f*+s1ELkAAr{^lW`*uXC4B6Lj9T7f2|F8*6B1XTl9@XQ{Zy@Cpo;uFYtIRp@ z%1~_?|Mk&Mj|z0Kkb1d43@1xc&tFzZfSkVWm$yBP=W0P8Z5|lpaGqE`qQic9S2DzS zbM$U%X$|nCOecDwsolPN7`Y0Yzw?T8zlpkkxc}D(ky?V(7sR=A$pO(+{;!i}mkg4# zekwg`tR`4*{8_SCLqMo@)^vB;dF(!Q=U|SB(E9CPRvKHO`Y+5|c{hLQ!WxG;S&7gl zVU7lkn1vlw1wqz=Xo?%#7UzUJG`!3ThAtO1UQUhMNhy1K^V8N1;6HyctDJ9jsB$e) z0Ay$_(J0PHUORqKylXI^-TpX2f%*!i(d}zBUL&Vjg=f2H~y$w`~5`g?nwkvayk}q#@f(LS!qhLdNs=$?}5sGKd zi|6JO6=z^@mFT5GwoN^&9K84Q*M8vy>bN2e=yt?_2{x`|{6x z?o9>=XBxHf+J+t;dxg~%^fntjz1XpU;z|nKfP24fX88lH92^qTLr&nLZ`8D)Yi}_y zN?PCk$5|!`jAzhk@mEcy?`?W}Rl|xLspl>DR;^@AY;i?fj-$j)OM=a|7;{bNYad~t z1xabK<08~&Y%{tuhbSj)dsCDw^|0j91HTUZ1j)`P%y;wH`>Ey3NwG^iuMQN**`M{s z3t@IsA&zw@`~DT@fE%VfTqW9rehKrW657YG9W@_wIS=1o=~GEXd-oj z1YJoq^jhJ7;I+~b(U-S%^N?ns5#UgE@0=##UX~2G?XLvA#fotCUh&^?46-s%c$g6}3jN&xyTTy>F+{ywLFkV@Y0d$m_{>UnbHc*~NbxUU+Dpk=SK%09W~mv!it{gB-K|6q^kFRoT^*wAEQHW) zESA8!^_8z0&#NJRW~uLz4LD_|9eP*Nag*_*Tr2@}5%#33CpH*%N@^MMxRioX6VWMR zGq(NbHIa|h5G-g#J%>OhZJGJFwTXuHxyU^_qryIk$wob?r+eeMq_((%d*(m`E+_T0 zaNTD`0veHX44ST#7OQ_iUA2uo7()gjd2h~=A*Usu$tCbLmQ%|M;t`G(>#4sL4QJ_z zT9H*zULQ9ICy~aGGCOplQV$@WVpUO8eY*opG>7zSTw~)w5+{6{-|< zs$})s^t%%o&rw*nTCHOn)XR2u@|~lr;RKotZ4iSL^!An$8t@f%YS9z7CV&R<&e*8=GUOe0Ac=qj4mA*UQ07EiJ z>3;M5J*F<&V-T5}R~+G`HN!9szh~Ql9A>)*?pZSayAghYoPG_9quu^fJQ`q0 z7+v;T3Rnx}rPlx@hDS75>@xP9Ytd8%i@`JjGd5bN^kVMu>a-4kWNR|c zT>6rZS-8=v-@yt-v!60qqGOt`JBLOG_V4ydvObPTFZctZ25$wa*mu9Pa-%%Rss(~E zfw$^dN)g4W6&nbw{Mu_u(j+>Ihdil9rUK!ZYu{@1MgG0dQRl+AgCXJ zJAi+KI0rx(J$9fVVw4}ty@_nEBfO!YYsC~f)*VqB-^TXYvr9cQ7w>}MGb0y7kMrgF zKqoSAXWvQXD?{BTHPjCn;UMcQ_}fWETsFLK4^Ew3K6|}Z_l5Nn-%JTq=s0@E^_{Q| z4&*OTF~(%Db{;nrzmnB1cH=rMaUV+$Cz zI`e^~Pr|G%oc3Q9G-Xn^md0w(b+g!7-MlYDfMtRQJooWrOF|48bDgK`Epx9(82yOV zAV8jrZ;UPALkIj~;a!;jfj)9L=U&Eyz#3lQkmxXt)Rrdw72NLp0N?X2tbwmbpO9Nh zltV_Q9K$Hy^ena?UCUfIscA?^B*O@&yND3f+Y7uhTLl}4;H24=-Z zO-)Wh$z*`M>DA?8-VK;u8c}1P(nd0_216GU;uYpF7mobjE12Ns`dyF~234sWG~)d| z(B(=vNL%k)o0$rQvdP{)ZME*8BdBHU!dGPM`kf00?!C<&HOZe@0ubF|dewVb$ISB0 zIQ(GjQ1s=cQ51p<2rBFz7r4S;@U*mx(!Ey+3oH`*xz;gc>;Vvo@Xl)jujwR&g~|8d zj{xa!j`k1*gtmR4SBgLZl?ZjHDms23YE(MC8jdN{RmxhtjYF`&LDaR<#h_XR&M`Vx zx-l&Bq4n1Q4gSlWNY#)5>Q|ZB{fBCL+;oh=MPBprFPixFIQN3wHv9 z2o@>uq;!99i@0wqf9B*241MB`u88&Pr}w12y?WE#12nO^V_(HWx*xoO*)_euHL+Mv zgraF(+tYQ4AcbJO`VX%77V1PyTF?I7K_f{3&WL(dh-8)bq0ShUk#-%Z%!^tBGCF#h zcCVdgbAT5s6cVWL{NmRHUM=#=73gQi(^Zh$yLmw@zDg8}N>+5TwO>oLURL zJV2)~sOZqdq|p?dRbPyCbkX}YZD^2>5*S*I7Bt%BUmjJ7_+qqjPA%FZwEcQ_NQ0t< zXObvEE&s0$4oQr{*j@8>+fCCnOx(~)D>NSb0cSz<2`$# zT6v0LdWA3qA}J7k=szf?mAy?bYI~wan?Ph?EzB+UN3-x#wTi-i>gs>GFeQQa?!8%( z0@OkM^4XQG7ogNqg7+msKq1kp@%?v8K8D_4MnJFInpDbQtVUJjo&`t7BMPZx53)62 zO$fcni18exFP~OnqJi3z5!S;=#+sf6q6)=G3vwY5XC{Ki@dpu33Ntt4tzjxux<-!z zseYmNhdhJgOqqee*l3DMivQ~aKl8?H`?r@{+|mD0E8weoB3Ij=qpQKy08tZ&Y_fSn z%*qOcu)YCZVPoj@Ri6f&hdF{N3KGqIu~k+=VRhJ(p1AtLXj3^@)Ol!z-_oh$nP;c@ zJs>u;gwyOsp;!8Vlne465ITRg9S&%C{AilslelO3k(vMVI^IgPvPTkqLC7I)n7h zRd6g4?A`L*W_n5|Sn3#@@4c@YKG_>YRi}V~pR*B`{#jiPhlcR4hVcchr~B(+plDhq zR(Jl(_cq1wPQ*abSg!Cko_Fi=dmGHe*3a%8n-7lc@mY|6aThUS;o3?RG6usQ%Nmvb zwvTa}P(rRf+dIaHXnw=^xZpbQAU6E!cjJ{n3EcXQJ32;96)j32zW*{Ao^8b!GDPyo zPH%>x?xbOLmWum4;!#%SO7z@e7@aTS8MwmpgQ5}zeIZP79O#;W#pLS%Sl z)yp%jPgKldkRZin44Q{n~Z7bNIw4o%gNAeuF1_oZ>(?&}e<((=vp!unkx zM=6XmHS`bW_P`e=Y1xvvx3}3)m5tTixLfCLJtp!N*)Byu?PKyN6RFV=qvE+r=!-H1 zIR|$1rVha?o}laWD>4>TM8asq(^7SFi@jVzA(UNKXUvL>jb?l60mFW5EudgiQ^B2A zcAhJ7!*M#!$VFcc93EN`X>D61pj+I&h24rPVUgA);vls{#B{LQD?BpkgPkygK@9YC z1k;=M!^^oSQIgZp-nrKvzAcQi{Cj~5)+Hhs;kn%3U9&4S5K08Xv%&dV_1f<*fDkNL z*-$6Zt3ZieTH5%1QP&;+OgAt_g(WNW44&Mr38$x?^_G2J5cd#9NS(k(w4NKo%;-a2 ze$ZU$wx-~2Ggb|dM~*e@VyliV->U$=NK4OmKB*ZhY^<9DxJoWC7oV9uJ}Xwit1X5{r)y;v~vd~h4w;sDv_ zu)A<@b3xt*9lQJZx1sJOR1BmBJ?C0U;Ve-48TQY0aQNFphGyazu1Uz2Ob8V@x7)dlSf!0>tH7* zEme^qKGJlCW1#-L{T)}?ugqywy>J0(92+4vBGQCE+o-CAU;`zYd@cUBI!-#i6k#w13FN~)f)KTW=gFE)Z&^%#P=(~4^Zg$u`!7St3#Vgsh7!Uy$ zgg%E}?t6#5Rx!3<(Z_%JYNR&o6Jg@irCd<;v%R~@HI^~JOt({^ilt+wS zFm0!}ZPPCB6#_)=QI>aL?{2v=3viMNx@DXGpzJlsT`|k(Tx)c0LIC1>nRu4i=14`V zyvroFXja3qS6U=54RzbBnZO_vjX-r{ZS_-6#ioR@v~Vm2o2X>hmWV1)a;lYPx)ueDXhEbm4}dm5F<9$lRvY zMV^pH!e>tT0+Nq+33zg}wa&0W_~+{q$SVv&8S&fP53j|g1DHK-wSCy5`A~ea6 z_gVE!^<&rm=v4*_1S^Gzx_oeTJ*bgpdU$?!S^`#B18GFku8VHXrMn@WqeD zUq?j7+y0&3SLq&MhIt0l8PE!TlSF<57$u(6xvy&s&7i+pDvW@Kg;U_!#l@fqp%l;U zoy879*)Ki+=RC6Q{~hx&obOsgcAD^>H*ln%ytg^}&6;$Jx_vFbVAI@FC1D9qew#vaX8B3%gUyb{q!Nlg9Y|Dwez^E*AYh#Oc7DDgo4~ z&wg6g!+gDdV%xHSb8$Vc%F z^eV|3s zHD7J1!s2~U6^{Nm%2aVvxGm>uce%0DNcS@Y$SDQXL4$aD{ff^+<5+4vIcn@n2BP{x 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ⅆ5TjMbLLwi0!$?pK! zQf6f;c!|q<0?ior%%q%rF1X4`MyJ)Az+y2qJLOlBkxVd^^#Ai6{%WM2@;g&+LWQvP zmOOHWjx%OABY#h5sD2Q{{iHtg$FtZo5gPUEPJIl()CUMQduMJ72oLOJR?zk^7=wQM zvtBQ@6SaH|i!^vPCWiEM=?V<#6OxTr8X@td(%0`1?qjP*h8e+zhhlM@ri|14n z&7>Td%8()Q>r`Tt#wgZaKc^G-;zRz+dPS5+W=rWRrga{3blQ>;dl3Ki3DEKY;0{H# z9~e5OqLBXBUUW4(b$WL%4@R}0$XV6}9Gk$(U0TWeJ>UFT}AlD92Z;UC>Z-`I#6@OCY0kX8$p^G&sh(R8cnnC$?SWHZ~&ecY(G0}|!6 zrxM35uxI9B_@ z;n=m7H6}u>F0uzlH74XbAC`tL+sDgmS?=a{s?VfSFFV8fWzv@~8&Eg<+d9)$tE%-r@2UMUx zu5vw$)0ql|uWnw=#`A2{N&|1^;=cAg@6+V@z#=p`CO|mAva3rZcFtFXfzyGVI<)zv zYc#T-jBHlzzj?7XoHI|&G6WLmvDGBhuyM+(j0KWluIEz`W}dkFyq4uYi9+_8JZb{> zB!dqWStITwMZRjcUy#mtFMny*=7JPEw(V74%vcF2AefU2+=p<_kgi&Lckeq-`%;Q{ zp+Z~T9o4?(W{3$4pwHa60l$>1+mb^u!`Re`yB(-7!St3Ne)I{BDkz7Z-!EuT8oz(f zG2V7+8&_G-YnX)PPTvQ9!GZFbnb1emb=>9w5<2V-5YsgE5fnB$Ksfr!jXjsMZ@zT@~J1A{gu zY-_*?Hhwi5XxKH0tto|HyWQ7eMhXUIwR$5ugKnV4-lFwp+%{evefR;G4DKf-RqZM5 zIHD@+^wu@~`CL*ZyRpR{^ymIbbn>+%h z^{gfDJKt|Y}H3zzWZaq+(e%x zztW6MUPq-ul}^agH39MLlk9P5CH-p0`dgr7FODZ3?Fx%>1G|m3)>?&NEH0f#BPp zplea8mldD{znAr?R6;g_G%X*2?Oj%~qg^%XYs&0#cG*lea)0GV!UJbm8aH(6jYMhl zx#ZTftD&8_tsrE=7zzg^Dz847eZYSFQtN{sEE zR*_}I{*(gPS_-p$hYtAEK$8k>OdI@(oLT_O%oH`mnfBTXe2f5*rX{zlJ?*(#UaIah zA+6_1=r5>rf?O5>2RH%-zg-{C~Kgw2*4cpb?3zmyRJ-G6KtH_M@ncp4w zmi7j4zK%P&;C77iPA#)AR7tq4ULlpG!n}m*%lV6};~mSft)#kS-ctM-m4qm}CL_p0 zK2^DlC^Rrf2M_Xl%+R{|Z7|gH@L1B%=U_>xtcE%qbYE_#VFYNlMjpIlv=7Eb{waFB z3K9dzBK867RohB+t1VGyP_$ktKWKYrSFYN|>w&@*Xc~-uAEe-nCY9{Ylby;%UK|v5 zv#7{7DQNRzCzPS(iu!77c>Qo zLiN8^ajxcn9wiLs&SM{G#gg=A)W?!DS@mTp85MN-9wlo168Ghmb$ z`}=khRf{K;t15}cUMCSwF0d*0J-1ZL_dN#MFl;Bp#7mlZ3e zYRG>Zu_HIT*4UFg4C5i%|Lx*sEoL*b#Ornlo@6Vn6E?X+CNCBb^bdL~aR)8A5w^W} zAi$UTi^C|0h_4l;>O}!4l&OCq4(xE}$d&z#me-vA`y=2P;9>p%QpP>_aS_kC*FVYY@0ij0`k&oM#AB%fr790NLE42 z0K;nF4$qW?h+uUTrFB~%e-5$1p@g{#K!puNuTj{PV)rj}{@%h$-eM8U$Y&v8+&u5Y z;MO15EbO>|VGxOGfJrgBd(FYVVBi^Yvw4$aU^9?2B*xUGWx+aSh5+2jLi}w)pdn%S z0RU~Kj*Ja<+^~@oV-cGp@Pn^2!mhp>5b-g|SlJ1BX@PdiQWTJgaMSu9c>+eJ0C0+e z=y?O(u(d=}3QkC{(ymk_|8aK4wbWQLDg+7jK$uKvFMVHa{#|OUXWLslzi#iEMFVUH zBfb}SI+sy~^*wIYrzswkKmo@zxFk``Ok$K6^!Vpoe`RxG_J|&`F5~NpvjK=W3`MHU z5`cOI>T$j3&jT><$C!#{HAhxoh=WFiI-)PaI6K!6Rm$%l>XB`y>j+^>om&#=4Fe@i z8z#BsRp|&4{P@9Lkq(Mcj;9}&eJpMsq>s3#PX+8fgU0x82JuAw?xGH6=-wd_5UBDS zds7dXUi66MYT8~OmmYGjz3ay}6pDVp9f(+%)(QItT=}Jf`pQuWLnq#L_zpp`Dd#!d z6F+ESl6=X=)8JdW3wp7$+v`#jvOojB)iD&Z=QwR(g$kh?zrAS+^H&RW@fnbb(p&dJ zdagTQq!QqLkl8?$#_{qg0T!5#4C~3iBG$a?=S=$D0*9a_ocb!>V&9dPV<-Os;&g0E?;@}{lw0+O5(p`CsOa> zeISungcx4Z`zReZY1?nj_K4)8nKh7bBM((zQ?DR?+zVM#OW6>U!~-o;)nZWzQo)7o z!0yE}jfy;zukqVI4t9ghVf+E3NpG784$Rp}Khm?G z+D0|MW2gPNWZpaG)6dl98-Z$6-B*1BUAMv)-gi2i`7_k8;PyykAS!G{=gN9FzO{4K z>N94+WKHVe-ZcpQ;aC~-tg{aZi0#%e#2RB5<1*P+%jf?XrXB_NQ;~NOsvn*xvk0n; z@(A(ub9QF)d+m*S?J(|C@m!#c$v;j3!(VGy{n!O))uau!J1{w-lb812%yUvxvMzMn)|tV`gBmh=2z`1#8@L~gk5!}8 zzP8L%?y6?&6W&ZFf*^1Z`Ttb<`sb-R9zR-`ExNd1VmvjiKubAouiybU=`3WfhqZ!hF?>(zG(_oT1p$(}j$cuhGC<~^RWEzonVA{T{PV7Xwry46yUMRK@a?|Ww zj9rl}zLbdkIj4(-7~evYTr||h)}oE7uP-q}8I0;8_w3Wxt8*d#h$GJ5E?onK z425m=0}kc3Wla_<@T|b$^UR=EDFqkbxYWc=U zTZ9_0iIDWX8GDuASx8CD=D`A8f)E1SUoh^n<4RAvx57;N1D+^D2Ox|!hXoIvcLPC0 z+cx@U0u0oQ5pv_LY5_`Kjz4W*qa!&mTjNet!r}V( zY$Y}Wf?%}roBRrlg#_q~u4ln!OQ-5M7#t4-50H{d-InE8cbPfEv*JOWAeE$=D3o3`II6_Uo zOlb)BphBQY%BW5LGn z^9CGYW-!cX8yDIYt&yD0X%Qq$bl^YjtOScqp+>FRx$>YrN>LSw2jc?}9gZTa7R|Yf zDu@$yC-C6^oXcoT<-L~R`UjdZS~|mDz0(*{2aD$`zF4<6f@D~el~uBIpNMzukge84 zybTJ1U@gd`Fy^`pfm&cfOR02kmh<9KunHcGKk&fY2-CxM9r?*7 z=;6?|SAl04C6R4AoV6yB@o4|UG3Hs5o5mul=UujHoL{sRudS@~yZ)vQl)N&FAD)Y? z@6`o6&nZhbicKefQ=b}S1m7&s_oSw<*+^KFytJW#a!5^RPSHFk5xFz*zB~6LwZ`&x zE+G{4T3{UU!=GTx0ORBwdJSAPyTK?XzHCa;!vFADecO*%s2X?fSMfp7N{@dh?1UYx zUFbcgR^(A1{V)8m3?6k^B}t}uJ+aA}9FrTl!Y4GvbmZB1kebL?w+lYR=!^8sXcsj= z&4T_gPMI^*m?qvNF!H0GUPlMB{LC|Zmjd>ySE-L8YYhrtJ9#0U5!Ra3Xo_hv6%Lg5p$5D6HZ&y~6 z$fNyna9$>cjKv`*Icj*fE*{vGaM(5%(Q>4n=!{(wlSyG%I`7~N#9p1<_f~`$Y@8LI|-AZ5Gjwjk~^1Ht+w*l~)f}Qdj*nSfz zqtK^0++O8N&B)QVdU!?|s_A%Tp0RmEx&iV~=nquDEsG7k^uAxR zHj9$U8_K04=*)Is%C61p&P`I{&A8UGcIp|r#@vVeE{HJd)B}VBv)1HHV}hl#735#Q(XEG`>P)IsFJGLZ_Wq?;wL7cOO4-Enq` z%QQ?-hfvjE8epjCz&!-akupfq(YA_m;E9k8V$SjNkt3Vo(?-ha)ZGnAYCaO8Qx=wa zjWU%?UO#gGc^3C3-)PpGw5GcSV77p%W7+(D4Y(#HuhF!2z}|}lCztE_=bTIG04>5B zz_n5OIUsi9q7e1fj;~wBzZ&r~#ZF{sJYVNM4mDA=IigYHk>kowdO=SC^7*16cDQpg z_^V<{bf}7{)Z+7J9dt^8%?CRd{=0|0FaJaE*WKI?nzGW8;aoFy4=i`>X-<)rOP6ds z3;o8$=<1xX?H{go5MkqlG`;O&#U2Ba3b|#KA9s7Wr#sjOs`_rRUIha~Ts1?-F58HU zwDuYB+!&PDaBG8aO>1Hqxq3MtIH4Yc%m2!TpclnE8DH#re^Bs_E98;6SiECG%juY_ z_NS%3<#D0}Cf)JG&!V0;F_oQG_k`EN%Jt!SYPf184ScRB*acePujIBF-gy)piUqRn>I-+Vv*yjA1p}S6wHZj0r_{rvJh%?Xr#VuJDz|D^Nx27C8_ zE8)mszyT%GD+dyC%AjAEV(@}r4HW2cxY1HrWB=S{D=i(;X9kK}+3b|h*bcj__qMVW z%|u|yxH+3coZ)5`1zplDg@S0%Oi z;aB5TVlOQ2J>n*v+(t$(P043khm*VcABeNK;x6 zeDyb5qGv4)W=h;_5l6Ime3Og3zi zj1Q$|pqh?799tBH{MH!ASHka3i%lN3NF4% zg3V4>4s5V)h@g;cZRzj5tUP@xt>w2e+0`;7xM*f<2z`@OA|N?+GcDnl4P z+?k31exHYQmLGCDn$o8>Z)O2N>^*;CdUY^_v3=S-kpz_2$}%wSm^ zwqsJC9GzOmXhI&ma8wNoqEKo(JtSKQo#yYnM4Jx2m{EVGp1bJZ3D4lH?7?Doinl<@ zALNRW{Pn22Mb*G0odNztjn-hZ8d=v$OYb;N`Ba1OCbUi;P9oWj!&)3 z4dLho4Zhsv-<$(oI|%C^LF(=X9VIsMJ%g;0nZi1hX;d#ZUpuWQkIRyY`G=i{K?9Mf zf4nb9L%Mq?3u~5CgBZ2lJ`8d%-O6e$C z@@mQyAe?OBE84PEI5#JhNx0nzLRxIbvmq0jQ;7DI-Q_J}k4`M5D@I1v-BNF>+}a^9t_^q5!EIGXZgC|F8LKGvr8b zE9M*~nYdx_h%bZLV5c+Q^)RHqlwPTr%cE)%VGKcO@jg3|6AqbN_aZj;Z;2#tYa(Dn zND~1wNrung>zA!0NDpMIxp8MckExRrmDs^97?%cbvYD_~O}X4!y8*V&=xAH^cyitn zBX$*m;l}tLsI;!iD`M$PuhY)zJ>98;h`I4cGmCP(uTzb%sP})beKU+L@Os$BLK=wa z6AolR=r-ccL5e0Y&%!^UbPFCFCPxB%2k|xUSoww>uxfn&Hdb59+lW0NTzuX{Eo<@X@yy<)VH$Nx7#H7 zF8BJlj+|Jy8(|AE(`G>m-^R*Wd`xX}{mg^mpga}qQqft#mtWxqx@lC+R3!DS;#U&^ zZ4vuHc|DTr^GU!yA{TKMXps9d>690H;TLNEK^%&Nmdrr6`OZ!Qm8TmqU?B_yv6AY2 z9yES;w$TDU=IDFp>qOlQP#l`(d+Ki*v_O32NY*66(LH+KP~;a{V?GP+PD^7O+tJq+hLRp8OMCnRkIoi5csS!Hs%@K#(C^2`dHQ=g;Oh%r&9gts_PzyL_q#$dKwIR|HifBX7ukl(~J z`>|clP-$p}Ktw&r%n0N6QNX)50negG!tid^CxBInpGQWrqzQwPw1#^P3O`lLJj}08>IChorLh~%_a^zXD+i2DqCv4aI#;T&4P(m|2yH#mpnDNeHtZw z4^DE1kppCl^&*`m#Q4|871h1jI7sXHq5%(k3=*vso4#t;-rHOq=!4*|D1I+o{M~l& z2hp-nD81af!ECW|St;DjgQgX=AoVx4{@ijuSAh0#)D>eJX4E zDu!aJm@QaJl3{IeUbZ}(;z;E&`6aVX43k`^Fqw2`^JV0ptnw;c1Pr=V#N2JC zjUtdg+-|ITa=iRq}T9uEzl4%rFgNSQr)lSgO3;=z7RvPfyKAoO|IPDgw6E4lN|RTs*?gjYTZ-=dZhS zkCFT;f}r-71s4rme7rZ3O$q#trOHgeZsRN1Hd_%)zEGlNrAV zSB*cOoWAf~THQ!-jvcDt)x)-0vM(VLtF$Nieg?z4*F1%wyzXt>)G%&)cpt_i-CDi* zfT=wsQPod*&*4Jtn3{ZQ?^(N1cDgk2u^I(7l4sB5nlvR3sAETGY{Y7)a4n36-i?o- zq8c(`kkQCx@`)Msj)^)mQ3w6FU4J5>Cd55WVs`U|8Z|qC_@D`B53I3kPv)xW_pcSozU5d~gWW>b6tRaL~Om||N0=zwn~VpIvtP8HC5 zX-pdrP3DMhowEO6CbJ4U0?QVJh+!kD@|k; z`XB=N$ZHY3?eTrMD>nc~&=2z1Ze75wZ>M7xDjlW+OuX)>)FEJpza;};_`ng5r*FautpCD z>VGZhCfU$6uyrH4&n};h6e6QjQhrT@%>2#p&tvDbKFuv^OeqDLG>#l~kUl7sW;BDnP?*^mnP$xFbx$A0T zjxzS|+@OS^x25{iuhC{p)hceuvE&oo?exVgI z;7+y*n}YM_naQIGf$zrBeWw*1hFN3Z_UHUN0iiB6Zh{&kwqKaAme+2|9B7<9zun_B zBErnV=tR0(NPi-B?8nwtDPwJ#!&V9r9#~tJp;i*Ep^vXUE$zKE-iz;g|3e8m#aL&! zHqHIw6E0|lU;E#r)PWIbktZ+N#YaoD1_WEhy#7q>IAWO(V~DPmpMSaVHdu#SH!Y$0 z_L1zGudxw``4p*I8Fe4Vy-7uneB}rLsfj*h;E62meL;`ZoiTv zNjKjrmBRyNFe>wxBH7J+emKo!^eas#OvijiV^|F>!jXp%Cn5RpIsf9p8mFR>@l?O;@3 zxf3evl6-w!^w0Gl!Aa>31`GJ_gaahw%jK}in4_*=6xE?L&8W_#-_O!9t%-u{Z7w(M z@xG3`=qHa0dwg--A>h?3EzU24n93{B&alV~=D_q|X1ZBtkTib^q)Se+IWTB-9RtFA ze){akh>@ub!`zhh=Vrn)wOd^Y2{jcHw(r38w+jJe3K%b_)4$LFAWjn2@6zCUwh8siPEb z(Nhg@N-5l#OI1a&&T!ET;8@C_er>OG7F?Pc>LbOVEDs2L{lra|lIwc^hC}x3&5kNc}Vg8@Iy&fS*wZmQ=?;wO1#O_l!KD1F|WO!f^0i zF;yhe0G+gL1N&NlgA7*~(4YI5l8AI8%EMK~e^HPR^3{v?t~}s2Y=(>8OU=2&Zx9i* z=I9b__>HMBKuxD?&=e=Mq>kaR_m~Dp%iWCMkx*4vSH2BDdf3kytXu30B={NlD`s;2 zF-t29i3Y_IJ)}GB=2A1rsDtOV3mSg3SF#vWAaS81qvo?TSQ4{Dd%GgZpl`JxZ8h`D zP*l|4K?Yz0H`{1&XqPReNG0EM9ocH-kKWY`kn@JrpkjLYHP*|IKal4&{(5OM55+5P zcTkZx7k{myKD<~GQ)eF}{FQLp0FHz%q6T0NmNcdl94+#I+W(Wf0Y|RG+*T>AsWER{ zsLxD3Ixb)7$p{{HJt>Np1te{@c>gOPBdj`#B0F>1l0#539vun8;MX)`fuXJ3Ijvxf&m zi}M-s@3$Y1lOw#LrqgQiOJrS$P1bNU0Eg*_w_;;2+%@k?xF8%E39s9Jv&V zc7hpcSD#|(QS3_g-gUP@`K;~w)+>(rnSd#`yqJ8blQEIdn$SGBfbYXYlObW9{Lwal zm|Y+Bc{f(zjK1li9%6Vzhtqfx>GfQ;)BXAelxf z6(qhG`_2G{6?y{FDb1y_#L)}G2W+xXTeM|K2oO2IF<&3o@5kt2Af+&y+3m^F1>r`Q zxmD3A$3lEiIji9ou{pOAYSG?0m47eVJHYFW^4RRNtTZ$OG?q><xfVc5to}Ofe?&(BQ4p5VS-3w=wZ+r=vb1q(`JZX?-mQIPTA*r*TIhw}tz-#bFbu^&^BKyFyjpp9%Af~Hgp zjmb2&odU4?9?4m%(O@QYHrUc}#&tpqHmQ)LAyOaCQWK-cGhIQ9JLPQA1!f_ahQAo%ew4fR=iFQol^qX4Q0H`BugdE!j2Ia-iWmzvRdGk))L1}=LhU1 zr?iy2rekS57VL|RVi?g$kW*^d;AGYU>?u5Wt@K5m-!Iu#RE^zV$*d+{DH)c`ROnY8UJVyVguM6qizExu|P+8 z??2qi6<}xE76SJF=6`1Kj{FWj%|XHF4gGI0$BtKG{W=*Q$Q&vn6m*LiZI!>Yk?6jr zNGj8K=H=^*HABds8)`^ecWGQekb%ha_MU(R>G*xfWtKf;n9?2Zn>=)E8|h#yIjz$m zzMnLR?l9pR*6mo6`Cua0vzNaFPb)TySubPvOg{SQY5zLAUtJD~*ay>IpPqsSJUz?x zjjBRL-%Orf|Nlz5`k*H6EvhmtQ>`#Q1&fNY1w|htvGHF%;RRFGF#(5t@0GO}2-J9Y&#eFlng>Ag|NF1QRz~;=Ej>71lWS4v@1qT{Zz~V=(G( z=BCR|i;eb~nqV!l?RVaou0>_PfiJgWp23f!K)@X{2F!=77A=CJs-<7%G%HAGBqD;nN)rq2+lo>JwG@Ge?#lvvN7$m+^&p_w3LxY&Gh|^|1{0 z8egW>&F)*>^&dw9baiu~a07rb;L+d_V{xvVEs$NZ; zOAi)1Tp~5K+hx6ygrs%P5Elqa!?b0!?%B`F0oYg+ROAt}Hy2GsX=LUxA^cc_04~Gm znt)=d+yKYQmiwB#MDeKPZvtLP$XNrp8TetT6qa`@=A#mBvt2CQ1ec6;X}J4vR&s>T zYf4Co6-0y2K;}$8)S((9HL_-Shz{_;=9W`y^=cqJEAB?Z>G4N@ffX4n1t!pKo>B^NlhFNSexfpbSI&F6!HfQ!;9FDbUt%uWiz#{i~I>-n?Br&#adXjianb0 z@rTLilkqv3e0aaEqiyWLn2OXW69QKt{*NgwLpyRX4?$rv0*g8tpC5jIHoBs8nLo z!DsuuT=+fDmI3&$d(!JsE$0Do>8r1<1_zu z_qMD_Hy!X@o4IawH(m1ei}7yy+D{X9tQN*(8g?8PI*N3!Zwhh=S+S7c#uVGwB$?;e zC=i|`I(HQr?I8*o8C<&bwDt8gP;|!PYO@OU?E@BbS7=(m&EV!?+p5EjP|K0cXk14(&^LEgNaBB^fw6Sxn2Oc3_7*XsN2Uh9Ig1>ks2;N9X5=x+6rUG z^)kI|EZzO6_zq*3#E%O_NLdH7D30>z?h~s-vZ9k@#aCw$A&sxf)7r4M8_S&L30b#& zkKRyYm^sA~c+->R!pvTG|5DuaCsKBSeNc8jVE;Fvcv#Szs_2SbHZrxSS{#SF19r6u8~*#nX;v)xI7AdRm5sf+s3cg_+Mkz)g2!%6uE$tZt+E&H zUyTdbijj+0Wu;xVow~Ff7l$)-fSjT>L`AY#AQe0Ld;lC8ugl%h?**>=tzTOZvE)wB zmZZ|Cm@%47T4^N+*jD)!>%Ps#KeJko{R+$prs#eaT7;*tadrc=RK|rbetdHdo`k3kBva^zEX;NkcseASAu4bDn4vo+0WT@lfH?n)xg#X;y z1*ak%*C~eA)RKG*2C_;0IKBz}lUzkAehBnSVp=)OWf}VHzY|Q1_0UoSve}|CayC8u z0ysS4=sN6L4A}VbwYX=IeP9ZlSme>Tx3N9zI5VSLlop9{<1CQeV<%)sJIuwK z;|-b|TdE`fGz{fQOF=t4k`MvqFQBADH$(m#tK1{Zq)N3JV0jwIiN`+CA{h++&{V_P zTr|_T*)&k!76yN#w`S<7U*Ux{17^o-RWk<@1kEj0r1z&Q-}?-qVbG4^;2BPb^p^R` zIFLWtMO3|GTr*NcdAz(t!ra6PiZX6T1*2qz}fYb@hW*A5Ov6( zk8Zzg(;D-jOdcEDIZcBcL`>*^QCmeRq)PbuGo2P|XSbjY33Z?4MNOb(Hi4_zvio~Z zF&8lysD%F=lj^2TZyZ-h6EtZ<6a}<#OjZA5qK_n3$DV?tufU%^TM08WDW*Lw{#j(N zj8@iIC*ck56wqqhnGCxkmEG8$AB_QRYim2kSEbDibe#e7c0Oraq1_sK!J(U~R8Fev zw6+^d1~S3SZ&NSx7O{y2`XU7IqZx!huDQ3lRD{WfK6Pz`UTRGo`i7JpJsZfO>(to8 zr`H~`3=-OHU27swwai0xt^pSOcvB`(C*t_aQa=~Ar08{HKg4W7Qf+AALdii>*@1#W zr-s*LatPms9$C>etJWGf-Q`b=^2!&6>#oO7c3IIXq)U+xE?Hw8!-K`f zw<}Q9B(kI%}^W8~WAZZ@wgbiCzNa%W`@OzL` z0k=GRKIG)${Kj zYQSgcEb-_*-*|z5bw*C)@bvx4mm0EN@b+j1uwpx?4T^g(8+3urnCy1Xgtct}LUvW< zBx)7o=OX&hA@Oi}d^56oW%nwGE&nV=fUr$loSbBU)KgiiB!#N?^S9F2+%jUnn>R_^DQz}c}?xKHA+c*w}+%iSv{muMhA_%g=Hk+Wi!FknWm zv&Y%Kj`~!%JgoMtVBaR=Kh)0r)&wQw^@-{APDM4q2`HeGJA0Huk)JNP^r_F>kHMF!ewY79~w6(#VRPY(3ZKPwoc$L$XS-bz#U2?)? zb^P^vQ$U6FZ`inL^S15IJ6v|U?%Lz+ zGKz5uU@}-`>v+8?tL?-rL~Rw>GPNFZ#}(z-}(K5fl;wUDjOS@D^Lwc>%WEm zIideCA24wZO>J#0ZC&+zG&G~ZUo9hToyDuB7(4CO{qw}EC9C77nryv(@5xKOrE9!K zO!uE`(w}XVv3K%N=|9rcS=s>rZL z;i=v7-<5wp`0=8#q~tU{UN#8{Cm}q`Q_l)ge-Wg9NyvJX#_G%UJo?YGti0fNsVSsh z?R$iA$Kupfn%iT82dS};@AZU$fk|kQ$#Q&;cW;_PV-p(Y-Z?$ESaaHBut)3Nj*zl1XT>UhxI8 zL@AIs%P?eddkMk~pM*4uody!(KRcu=1lazWhPw&rVG%2H?kNXeJSaoh5~F$AkvSig zw{`HLoiHg*$1(D|Cb-LGvjnU9V=ZH-1`NnS5bFW<#qnKwx@1TGZvSun!M4qtKh=AxZfIxt)h!Pry#{YnS6KXiQF zMuuK>^;^gm@|ZHkN+U$mdG|FJ|BqhLO@q4D`xo+V;dk%DIAs{3b-61uF$s;)g%|w?W1(yb;F#beMnq=I4vvo}3=c z1VVqfQXHfwAaFajEEdIsb*IeO)a>gQrGQDtza~}@)z;N-(I9<_A%%%?S_~Y&D$7kak~NsnhQpmWSM;w~2y7-rA9be>`NMz>j2B$Gu`{%b3o#Y3#feu91qx-MTdR z=IRCQ?aEK+JFjwa|307M*veNA?h!1r*UcWAK=q1B&3&|3mI|2e-}J?Z6Ro0YKkS{b zKSI}LP%gSD+=8RZx0QMD!X8yleQ(f%%bA4y^LDv0 zRdB&&p53~f?$Yl&g4y>_85oAj=SWyShOj(~$6W6lOvISE-R zs$N$81^cUbZ4aCs4EY%RF3+85jdk#Ev-d zX1h^a!UCK-%o66_nE5kit}PtY2#E9CH@kF51>g2O@=qlF=Vcc?dH_aw&2hN@v+L_m z@vzeTW92Hsv>%@{jE{r2Afy*To|Mr$yfno$Cq`Co4b$*2*F7%thR@Bakwqb^gvumgklkjf(yu#@zG5P@ z4^~+Kdr0Zu+BjiYk7H2^lqxe!mZdndf<$7EjQdaAnYPvbDs=}8!KiE(F-rkg@9(1_ z^p3$vNOSfDjuQ4LK0@VoxCY)IQ@&7HbBKquEp`eMmdDSs%<1!AK0YxCebop|<%pS3 ze5%97b-M!Rmnr=iMn<1n#j-0CV^Yo8UI@`Y`}-rUsoH;VG?(q8T1_LJD4O}TEL5SR zy|Ebka|gO)YsuB{0S#{rry`%UZzd-H*FE=`0xjfWWsv{RxbQR6{u?;d8I(}SI)-pN zeuFgQul(5duMboXA)20$V3%NsCF>N(wwEdlA%i%WPBEDi2t(nO?O4URf|);zXpiN=?_<{M zt4f|?RR`i7V#bE{{>3iIq`I{3*dSfBdBmE3-xc;<@k;vMBjfdD>*Y%g#<2SBbDzADp{T)xX3;RL>ZgvE)$&u#TXual~Cyz67M| zXemQ$J z`4E3!_d1C5Kj6*ZzL%-kBqY~f+t!~u8r-fNH$&L|jn2`;Aj4pc(z?ULF(a-}AjgqN zSgBZLmX#e`0pNn}{lY?exmvG%!c3imPTpDgy z?pwFQN+!toOD*hzULUEX)4zK9Jh=7dxn-XKbNVgQrHNIqd=>vr?}!YJ^W6JiLjURf z+FyGQ#m)ZL68^IbPrd%->u-GvxBa|`uvwx+*owFMqIwAkan~1o^l0LsN?nevd9vrq zca+_+$L5suyjrNF6&r*-e6Xo7J!xtdPl%mxsY1o98dPzwK*p(~AtOC`xhzuPE`7!V z)1;$R_~Vg%_se)3^l@S4mq{pa%v@jhg)HyXAc)ieW+kj@2_k1#`6{ce`ck_{cLC7T zKXY9IbCV6H5`%R7evP$bOVoDwo6dc~v1Tam`(>euMlgB7-3|h*1j;)_+o{*`N3aBK zfr?L@lTlW55^Q#~_>t|zn%)Zzzjzez+%WsOF{8(!VZ*Tu)5lr9vXCl()bP7Ir z6nWrE_!oz&!Nw|NZ5r$AImRa|EoK-@mdN4Vq(u)=d*v|6QidpT)%k504`aPf`VdjD zXShlvl+C&lsL$4A)F_n568qLX%V!|iOU&~}DM_{PDqx%bP3|(TM6=*!2TT_Vg>v7f zw8N3@=qG*Rl+Dv&y2phPX0Z7rR3|F+n1pVVv#iS~BeCMn_@oKIB<}txa~(SiPM5PBvzC?UcNn$DS+y!|=eKk^$J;-4Gq3Mm)0KL;QBpLda}+c6bmAQ5dJD zs$${5bNTCBZO=iOH}1L}54Ww;GyvI^E)jTs@2Z!<+^$34(NGl}Skq&++^Vzy1_?w9 zZFJoP-!;*s=$G$sNaL$0^DX9rpMie>(WJK2bOGzD3PDs5X+-xZ`A>|RCviSn)rV11*|-g= zm@9n~*p14Zv~MeD^&D(&U?NY6nY`eo$t259ISe9rwq)W0r0e9C88`{)V9wLr(gS&Y z3TSuK_)*Pd9mwpoiQ?dAjC9*LzbBQe@Ue0%qb+hQY)WEff<rybj;| zFb*29ZhS~G>vAlM?)7&vB}pO$t1Dv$@8JtkN93=Hi^qp1A>Euh+0ejyFQ;oRe2ju! z5cx zExgFint0=Rdi13(E*FeMh)pSS&xvsROD2@#NkZ}RIvgK0!tng;@OdPkNocxrr5EW8 z{Lvv|60+w+%pJpg?uVB%abH1}1bceS#$GYj&rRd!yl*fKw8vG0{cnL~e}#Z`@%iK{ zPk$9hlQzymIc29m{hLpY(4N!fdpk zu*1M6Vz|(^`~QH5q(Zsp_Ay0D;{lTy>oXcXkNuZfN6yN6z;fgV&Ao=^P zFBpj{I|%}l+s%5voHV7u`S8-`#i16DduA)sWRF2DTc~JK?DLRNWw=;P)4$ zC09n*oFa$M`Q~_Twyga_{MJ-#UC8ZNcvrwcGXe%aYb87x zN@6J*>@CU_wj_nkjDUiP(n%;@vS4O3p089{eRu12jj1Hb#&0%|&jmDqN|{xC+S6X& z!(DdZ#fH`^JGTx6e*&SB?{ozJp;;^hg=NWx$CHp_i)n*S=~v{#dfaZJhiDjt;swHI zbLz)ccvKpyE?`D_6Wb}*j%bG!q)W#><3FNSE`FF~V2PMK91zRCQ+w!U0P8FQ|f-(sO#I#GU zwI99g6)*wQ$s7RAb_CL8{gyc4u$1FcS^4`8HyT(o2RwVL&0cmE2W)xwusgyEfaw7% zKCn|X*VF*_6Jn>>OG@`(WlFk2_`U0FF)(^kYvwt<#kyNgp|pivH6w4y^VF!1jUp%g zF{BRfnB42@D+uKLLw_)G_<3_%W z|NP|NXy|rtOT>J~!ohk{=kCsUh`hbFW)$ z^$4OJ+JDYcd1PoVxd41rtEZ_U!l=tPmG-Hk&4vKjgjvLlnjQyhFY=#;Q)5TLW0-!{ z{&m1jRneLRMg%U2;t@FeibSJ&R-<>^NM?>W=df7xbmEhN8sO~I4K}kfmTn`qBhDBQXZLvoMzH~^fM4p*_`z>!fT9@MRglDlHiI1bgaCa_ z><`g=3z^KYw@qa zujMT5@NLRKKLdMmtTZj6J!nVOwwO)7lVOVlfx^0mRNeNTijA&AF??D*Eq_PEPAsV0d?&2r}Gs^VL@Me z>8*!HpBzr)f;-}Is^GT~JA8TMdQR@T`G1*ui-ZYB^`7AV*{8Y7n5+c(19fiUU8otMWYap&(d9JL~r!H`?R#6vvM`y~DbH%Y3 zX=H1{D{$ZOtyF}a?Uo({b5HJTmSE*6pjbKLAfV8u9CM$9k_WQ2OMm1Ry=7x+;PbG# z^XB_oPhmTubfV_0jNcBXAPZ0UWM5vG zr5G#T4{{EokUroyg{o-K7EOvb`Fr)hPUL^#cY8Q+Op~yx+N7ho*@my8A;%4-5=#}* zN7c!T7J}!Ebro}UPC{uc)wt+L^& z(e-vY1Ms`}i=I(xqJ&=w{baZMHMSb`(wpNJKxTjgoR#9fg89j6uBUbn12yaeoQ3hd z+L{~?S@3FtLqA7X(P-b#mC|K7%2f`UpukzXCvXoU>!L?0l(pAU8@{L8$ zL`}(UlTaV|^~ey_eqKrqolhshuR)$=2F|=$G*NNKmJ*G;=iR!dT9~wL^fVB9MgGYS9Gtrir}vzHC!_?0S^X z_?IK&$^_t23ry&L3cY&M?hd-81d*RC^2EQpFHV!?$W%)=ECcLPq*p?K5V&OP+0#9mL;8Yre^^SG%ia}rxs%6H zeo{XHZTe8=d`5;5vK3=*4crx!5Ummx1A{+4(9&w8ZH=35=%mnx+^>L`>L`Vp zGcQOOQ)asCCg`a_u1U59FwE9h381`D12wCEkeR;TDG;2MuM)N9TaOvZ5GtOvFJaLZz$vlC%>W!Pq2duitMLk%!Ba7sF7js%J&WC|yzm^D{gA zyv?PyS24rWN1%9Orm#Q`A}GYDG?JlaAo2qvK!RKG_-1@+YFb$gU9G93R) z**)7mz?oRDm9?KfUZ+f)bfohYzOUdBTo%CN@B5a|Vco-Ee)<;!AqU+)Bs6@7AK_hh zuUXimOm8#z*!i}ta~XmYO01uYKu+D&WJ95mM)dkQo%XC&+5>})>>O}e|G;(6q85FA zg3G-^kY)aLB8~SiQ1AD?67qrHvdLb@{?=c@Ea((rJN!#KALp;V8eYH?>rYejfv$CS z;#r{Uw#&rul<@Z#yZr55&{*gW4|m0i*Li@h{l|F%n+K7?waT zCmU4Lyie`e>%_t##;oQm?FS_kM67iD19YSuc>pjm zca3-Gt-5yOpI)U@2v_m4pocFg61x{zoQY!AXC4YVmD4r6zP0shCQm;wjJK0C$1V9E zgvXS-9{pD90Z+Hd!|;iaP?rla^gMfmpJU$YW{l>+O$&R}pwF@GmK|9l5{Y;U+B{tv zV#(pu*XPhCp>3cJMWXqtUj_TY5;}HaS;~won-FXg;&8-9TlYSfjpO*aL&E0LtLc(J zzX3OliN>^x{KGh__sX}N#M`krZDosOO(IZVy#&R(_60ttl$RxK!*9H^<}Fu=%49X$ zxR(Wq{TQiFVxis~`xOPw<^H$1MzS7tpkGbQj(91ZKzz{lmNeBFu!i0#opV!buA;C9 zmVtPN6&h~m5(nCc(3zkVkDMqH#IjtszkTk3U@XZ;!=Aw1l!wTJZCDAZ?UpjS#_A z0_#nZrwgui1+eHuZ_!Dd(lChK+*W$;u654{{vMz|%JvT@UpBTQ1=C-Hfm=5lu(=>; z#1YB%Zx!wJ$C5~bscH1pSkNA6 zDf9-s6S%zU|Jhr1d62%>f|7{LlKc3t>g*iDkiZFzMV=09rsamGKde0$K(L$3HAB0+1e75Pu-upV~`g+A|94*oVNfr%6qo?UF2;HnVV~5d#&-q=A)0@jTmx{Q!JfoHN;7o=l%Ka}?a>;J0RY~ys)h$* z_;vZ_SbJb8g%=v|k?$h0xu${az}(44DD5!y;nu_yLa@0XzVj^uBDrC`_O(B?9$U9a{=wAD5GZ zKNtD(vye-q%M=5aeX1yBgyNZT_hvOy#FiB1I?}l^Y{xMkM_O8V4KJUza(EU?3X-%8 z*Id?}O?T_06^Ia}F=*(airdYFYvh=Aq*9o_q9Gu>N*qMzhDXT!{2Jfi+>DXF!tCP6 zZLvx^JM2u;FJ}<q@=m(3Im)`9|J@qTk$^I#>I#Y#E9RB-VLSbcQhc4Qq9+nrnwejoO5L7r zk9UBr8`z~?Kr>L0a&C(3<|O3xD=%6Vtxi%tr)!8W$tudtkeYANQ~*p#s|j(De1-R> z(h~aZO_euO#JFp(Qm#-iJ5;%I;mphm7!Uk}*qJm=?^XfVUbGNU4G(&GDTCVau0!(l zUABX9r_~LQ{GqwS!@!hsjdd&m`=swdoqYwJKz^j3p8zohxM+3q^bydC2rh`m$|KdT zrY<{rwx#=9s3_0~Bf`{CT8`8!lc%|PlmTR%+CnY>F3 z-LqP(wf{Ene`M{cb9+<$X7Ct#{*|++$P5=j84t;4bm|Mg#0#=p1T~eIlvhpkjUJpb5x4f}!X0?4?lIzr?euz@?pm z>LosV20+jL#KiO&uJN@EKwjZsNDiX=L$`o?Uf&y>+MF%1yzlN1ISE}*D61z1yoG?~ z+6P|*9#AlHvAjTqRT3F%4tgN`{;<7{^yBkRSq3@4Xb*_V)?EOw;J#1UE@(kvV!z9} zCPR5-X9O)z)cnpcx-X~W;Kxdst>~o{x9Ua;6cMWJ!5$Sja?Q0YC4Ro(d>)B|N|y!1 zL@ESwd;Ika$1}jqLxDHC%4ABeR7IVBS2B^-4fH)nZO(!GJTMn5$Sj55zV%^jP-~qx zy0W_Gcn?=BR3iQZIr*-rJq?#-Az;ZKmQ1|3ddV-vA?cfo!t}E)D}Sl92_Z&~KMTzQ z8Hfwu16Njf@n;dTnpA&K9!d^+=v}}S(BJrNr#OCWh;cxS<~3hK)OsoZt`*He6qvL+ zHpc!;CT}8ihg01+pmKx(#!^yu8WqG;-R)i{-cj+)eG5xOs2=k`RhY*Y%+LAo0xf`F zq_PfrE>W+>}?8)zpJ#j}1er*wO<68?}G z3gZ6P8qk4osk9@$fM1$E9LK8Ml;;XO-5UPdRt|dVV*UHlpq;0G`$1F#nqa5|NmCl{ z`}snE`mJr3!~XMxmLR~B;=bw${6b!HM-@?6vCU1pOFxLPpB%N<_pUE?ZvY#1@wB!y zZx=dPj&NR>$2$=Fd`>fO@}kj2pu3~v7Cu~^yx8IN!~47xKe5!5M-@J1}}}J&{*U}F~IL)owOeSU`LM2HP!}B@OOJVk&Q|!%>FqeQOsq3HAE4MEKVi3<&^X{N)buKH$x2;~xEBeiCpe49|isGYwUp*=9NPjH1 zHNaaWpC_K4)Li1%8PT#2*kN@{Rj5$BW?4{0EEWjw>c57Sw-_cP_Zq?LR;P|aN)2w-`;I1BE}_91`oPFpP#@}#}A$W~lkj`&MZfH6i? zeo;A!D(Y{Xq$UBc6mqw32m>OmX;);84au~#Nz5Z|<%$|-YC32Ia61my;25rZc1`IbsVs*A`kBib0-zyo{=yo{$qaLEzw)R&{LeAx&;O}4FX{+`a zJ3;)St&~yMlJOQj&G^PsXscBu#ZEYk6#&o%L7O0N{A^3)Q4Tg zX@Uc2SrGh*(FZ@1fsqC!=FYzyRN2*?K+y~_Ywmnt9~^5a8A{jVC*8#=1~&qA4gz95 z(`f}YjRz=87oZhwi>v7Ra;8YRO5FL4$6hg2kQinw+Kktv23 zFN$1e;Niamv}*;5l+@V8=Ty3CHPkr+5kS+m#XnyTeV5_u6+Yscr@&fQD}q1M;M)gK z`iG{2pQ*LKmfOA1pLYRfr+ciTIu2>~%;5|-QmRgG!8PCaEGh7jU$+YI$yd6xnCeA< zC@FMudfA|pD(m$;RQWj|3rkbzOga10NsSi|;EjOdWfx?nB{d*A2~fJ&W@INYR}n17 zwbeYMR%C#c6X5dL6iDz3hAV@fhp!asZ#tmd`9HUkhFke z`E|$46eUY>n=}0hj`Te&Uwp2_9N(Y#4Q8z$3fC&O|)7eBBj-_}Trkh<3)Q%qY%GFAo z;>O=6GJ9AGw5_RaG#1aU^=+-GDv)pgUKveVEe^nky?a$PJauLAq>2Di@IVya2X2 zxuF6uu<}1cb4z>6pNQYWFR@3Uu3xCG>scNH_BK@_urqddR)m5)tc6Zo0*($66%qJ3 zc%wOs8;>?mxe*QUBUty}l0j)>qv}Lh?30B5+Pm62r)<=W1GHXEDY!@2gxuBitV$H; z15#lH5>32q`0pni&~+tkKxA@_MNow4=1Niz3a4m$I498y+{4_b+)fq2KCkw?5>4R>1_Xe`WIK z^i5?J(eg8&ZC`|>mdc*L!V)D}H<3%qTRg7pL~b;E0vF`&`(>$nkrP4h`T%|vA*d4r zD!#?1GH>W`l?KRh(Ec;@tI?I@-muG`xOii8jf*P$yW8&utE-Y+RIu+t<~2iNAK{C; zG4Mb0FU=&FNGJPlT!ka<(l?)O2$;vRlUAAp49S4-$7LoO4vOGSUdmAKqz)k$#Xo8aK?3>22gIF*;V(e>Eyl zyYC>JqK1iUmK_BQ`iN=K(x(!xOgX)yQ1qSIUv{SJ;dVaj8$P-4_S>M&PGC*Rg}{(r ziTDMp3JpmTP)BA&Iv=6CVaxaZqQdJ0Tlf5MZ2%q%b5~RXCH_mJb0@f?7&CCUtIfEZ zSj(U%55@J`6xy?V6nET($G8*eq>YbMl=iordW)h5s{`>@76?9ad0OTTJxVLA~uAtizD1aH6gwEM#KSl2T0Ar~!4p|_T zkiG*}K>rtV)QTPBFiR%>!DjC)+{=>VTQ6zG4^u;y{X?PvmX52GF>cOQR(xLM=~z`X zLtHb#9wBkbwKo8G#3E)DNDkyz#;Iv*E#HoRn^X41r7}qeKy%rP7XB2F0r*R5##o

Y~HhNhlM6-&*oMlk%VM5Fq;^_EQlxOzIe#@GqpcRTHxR*1xTdbu7=h(8B` zM70)D`vX{~9)eM$2Ek|zpz=Z7;S!q32X^c=K+-7FJl%YO>3A8xQ8`#GBi?VK9XP7G z0Q5Ai@61S@s-qiU7l69*;-vxCg70oS3(#D{QHG=EEOk%JKd7*p#@^dZ4Ns`3f*U$o=VQAIg?h zf##s^9MA(%kUvo^)~Vw||60zclTQ}*G~d0PreF!Z4w@+GCq116zpriUm24E)o&iQM z39YKW-h4eY=gFcIyre!tO`}$#5l_O<)itXD3ySxLXnitVy`oW<_Y_a!Ds4thXM;+D zwWq1vYNwnnluAJsxK;-Tz8X{5m6wC$&Ay%_U~@QvfF0|}BT{fwA~0GY2fg0U%J;K2 z@&R4%2P#V`v*(xJWgvm>oPMdDr4ZC9PX*5Ow+mp^PQP@w5N4l*^#ut{AbczKUa$>s zZi5}LUV7|YNeRpb#U5Z$LYca0=apCI-d$A z_uw6t_TtKk7L}pc6r^6oM&v`oK)YnMxd} zbjakT};F7KC+ z+RH{9x*D)rX#jRw4PP&VV;q17RQGN@-ToSfElLM|Qh?S|QUd3&l*WVyQf2?*y2_=% zk^+qL3|A&QI#_-$JutN&nUMQiHY&%J^ZQ^KMcV?r?^Ihp%Zr&0SioZ%TnMa?W2od zGJ^pVATs|*@xHM3mQV`rpRd2?iWpQT8#fJu@(}g(9C;tx1GKXQ1BPMcgS2Z|sNv{3 z`Ij6%2bGo90-*mp-I=GEVCfw(EHQ^z zm(TuGNnOnI`t($4n%XOogop5TJ;1pa0A7^tF1+}#p5sJwh!K)ce?aHj@{JW_yK zy<#c%emgp732Fw`3(5-KnkCVIoKXF~g=X5M!$j?bVxv@>KT_rJKJIU`nF<;Oge=B^ zkDVv5Sla2j!rL}M80jWxAK-ux=r$)4$@vCX`)xO6b&X9R-PP}J$V7GcTX05%lfOzt zF2@#3&r2dPaD`!~ZAtf)k(yUCR9vO=kRVQ(V711; z{)yu^QQ-M(R5kVY*ra-;b=Ha`5wN?mlxIy$y1FYTU)6TDsI40u%rRN+kgNHFPXuA~ zGL#I&7f|vdvlx7~W~f6QWEl@y8zx$zq2Mfn?4EV*LVjDq{M1fyA&)z-WjUVcuU8ge zqd=Nwsm15!r@d&IMWCr0t7d_P1VgRIxHv%fIRN?yuonq2tdWPxF%q|9r-?yA{K>ju z=^(OfdByUR&K(4EgaJl%;pSn|PSt{l8kqP*&=8v>g%2S26 zqm|XWf?X@m-_jBaoIIME$gMKKA*v|XZ&`k#cp3o-_2RQ}t3%ecZ&yAGPs>E1l^ztgoX00w>aHG;3$ z^K20Nt`$vpa;6_1Upa%{4!&zX;TJZ8p(AlXz*(rO<ds=O`wz-V`_EZtzyG2 zU~S^!oY#KY-)4*zZ#Oq;D;_^sNN0UGwxJEbt{ph;`S}C~=d~&Ak^`Vz6aZ^?&$l<^ zD+P(s;Ipk?DTeRkL6evKrun2>!g44Py0~mhbEHmV zkrNLbONwpw@Dh`fdN3!@_HyYlv#veq7Ivm&VO}Pvq73g0NQbD7eTb~UqUKL0^ZX1p zP=7aSRRfvc&RJYFpASxonos*=SPzCL>j#a#P+L+DtGl%0lIBk+{1wyNb_O$0_!U z46hKwC$Xy036L*=BsG^$H3nz$UVcQ)0X4xWpTm)@ebL7o*~(7?6~)sYf&UIa+1jhD zf%TW{EytIn6OTXoEqmILs&7*^nYWGly3Tk0-F$8G6nD3q(xiqltX%cwDoAZ!zADmj z;|u1c6Jv z6c)nuAD+%W2Jood}%t#OrNL)zR=gCvtSg^CT~m~IZr_wb*273Q9UYyK*L=# z&SVv?+qGak=-Mlgs>?cVtaPktz9%UxCAFzwX6>0#ps7{4c>TZ~3G~Qu(BS#{CRP=? zp8k0v1DUpR9GBLujXe(=JsZ5^AR>60b5k!eq#f$#aDqXn>w*E4+zlw}1=O}0UZRkd1oaS+{ zRh?xJEff1*eD$bEOyZurDtG``T^H6jB2f^KdxX^vK-76HYd z4_TO4-kt+|N|&VwIqbF!2F-a^V-z?e@Y%+{>&l2S%IMA-8mSSMDVR6H$u_EC-or$q zNH#D|E#c&xTJ0;8T8^%}e~mrSR(h*1C)T1h`>^r}h_A58Zn#`NiqUR9S>az&CJ|#o)R0-cJnEx52<*IXYl0;>**TMEPFpym8&0ZeJXw%<+TuB3N{MX*D zC&ZE@PL5(`**GoVum$*;+h3u6t9{MF9I%ht+g_y($#PEDG=Q%=4$!Mw_}FK8pTmI>Y_8r` z@Zr6aOt3FRaOx!>?rY);wYv+58I|gKi&b%pRnB?ZbcP3xlK?iy)uDHIA_AaJ*6MvJ zaz8fOs;tqm6bOBQ^^&-~+ro!`%h&ZlSc);m_IR~^0K{bnYch4|xKt6X>1nS4+B+1A zZGZykzDVXXvR^FvPixjtxddSkgZA3ebYeG=i#Ddt6}WGElz|-(yMoJpsxxo(iE_?K zH)ZnBTu}j57CxS$ZKl9{49E}ZxBo`XQ?ROSqt|ZEsp<`yI0tep5M;+vBC(qfOjA?W zCJ1@tmTUJtMB=qeqXzNwpSuhJW$JAsX>apMvNJfj0@9S`?4v5{9#d03aNR&C+zp)2 z#xzd+C5xr)Usa9yEZ>B0P|T;CK?>jKwzR&mxX;az@z54yx7Oj>&l84hCB6ovuC4Au zyK)pOADd?cDBR#@ynE9Y(EA8y8B>4UW8L%1z?iZojEs;$+O(^^blV_@-d0rRA7~RX z|H>`i2%fc7jpLV}Qg2vL)Y{!{+!sd29ROTou5A|_5T|pOM2bBYKo8z|)!g7= z!ud3_ryyt!IoWP_c!>stQrzTD{$m_p%-DCO030G(HYQW)X!RzM-(E@`fY*5cXgTRU zUvUYwP@Mm6#+G1_XVf>!I?i(@mcv25%5xoEMH^S7k${Z$`f4ii`;mR~+dZe#_b9;e zgEa;qQmutRZT%IyVXR0SPwP>gxzK2_u1yF4xWROg;exW?;^i74_1xOi$3drmZQX#~ z$+J5LD>r2QieQKk(=vS!OdTU#>|hEN6htUnbMVaHhGIObazA#nGr^7z*RbE)9F#Pp zCfO(2M?iLrW8Uy8O%s*_+2ph}7G$o%a5VoJ$9+s|voHJGDLDu=j;&99OH-7w7<^i! z2mpwVwch&_`!P6VpBG6ZWhPj!`bsAW{cE~OTu&Q(Ckmtai3nY}>Gzs>z?tyfe!9$Z z;B4R5wVuI5@;QtDyq;7q^iPPA3j3WniG+3G6bHJjCDao}TV}X2Hw0#8ok8H{xH6%s zIGm#=>3qUn>YRpt zggvrgRtx5H#Pw)#iAY&Klhft(bP!=;za956dj>%3#)mJm+v@94HI-5dq?G^Rrt|o1!pevH*yym2rS;_I}XE`Zfs>o-PDpABg}6 z8k|`&p7PQufD?wnIS82PmP!jce+;NQ4f4$YQSpT>Fr>9KS54S{-t9*V+!rwuuw|ljZ|-KplAE|?#HN2CE!Dw3>U``6E7IB@uMmpurBxa677#&C2w4D?imd4a;xG!k7w zbC|KzfCWMm9w4OiOCSE0O)c5x7B2$3G+)CBu_K9>9LKcu<}VIE`eziYQ$L{Fndnz+)=>iZ>hUhMNP^gpXq~d7w$?PY3c1{D&Ym z8z^)VR*Z_=zQoX$^wPGK8t!(>7~5Xd*1rM#UuNK&Wipw{Q10C|5jRD*651Re=#ai( zZqf;XYr)_bFpht(W!8X4vpfz9@fy z`Cl`LO_E@=8#8t}>`$u$zsds?@z@zp{E0CoQg@AU=K7EvkvNuyR*OJegWYTM&D-{2 zmzy6(ightXV}MVRVtmxU9{~S>-_dFn4bl^x_`C=c)r*RJiaxK-Y5-oGJTCILYCm|a zlLz)>Dd6vhyfX}BqZmmAk1~y0t61WBTXzh&01r|OhsOJ`=gJDc7&ZV-=7YYd(GZp> zg+BM)o@(k&AxCNFW0T9QrSK8;#;iyV2VNv+GS!u&u~kP zRaL8Nc9Ntm-7Q)iNMapSE!meM8&VwwPRL>cb@htc2Eebp&UgJ!La>!EZ|#g_o!9j? zZFF@K$n(fC$pgMR>HPTuIjt;beU%3$k zyi;*^$8vz`0*vNp<>1v+{NJrw?t)mmw;+qFC`Ktn|0yW}Gt3Q&reC^E{}a?Q=FCD- zxypWKniSlOwoJeH*o=Y|houKNIEregUYRxMVBO-y^XrUzMVPm4+p}U6CdJG<)tpun>QE_? zD9vPPWSc{_663VnBHL7!Q4L}+G6pkdzVm;+aemkD_rI>Ly2zMszVCgX=eh6ae(v{v zVHc4w!5Uw=XTvQ1d7RYgFXF~ScUsahVk3>eoWMoNu{AEgF}fMe$L|-l%?f{sH{qY= z?R6GSlVAL-`JT*S_D}b)h<0B7j__+IS8fq>5Gc$+ zok1f*?>0@YV^V&Bik;W`boW@p05D{~Cfm;nk$#TYKj;~w&w4wBCqTA!1uV`R`V^HS zgkPOXG|j##L@&ebIy|YqFRX4#ThcW5)Ymu9>fMYMFrLUN2eDk&*B;f9b(2-cU6JWb z4>%{I7@_^Kknm#mvJf!ao6k`U;yCT&OF$~TRT->qMkCRr9WJdkJ!Oh$NfRW10`EXy zyfs>8vjc$f3=*f;3RK>C=vX#OdYStG6v7;vnt!1BqQNc#JllD0r}jMUMu`&Vop=ln zn`zZYEn%T{ceNz78Uk;#oFy354CpDh6_{9Bs=c$Z^l{J!qvuWyvOF!z7|0zIx z2G)q{YsZQcHU}uQ9AcGj+;F(!kE+AQ# zDyWT$TE8!-%bt~w!X4buQ-_ruM|NSq1-GmDGa32j;!}v)ICvXcW+n>OWcR+7z*l~E z)$Z-XvoMqM;d+v*i>w8Ews>2RpV6JMkvofnyJBpOdrWxCD}|JgG4h0`P$g*Xr18uS zcgfK!1CPRG;|E=_%<%k}(4=8vm3BLsI4JxCem?B2VF=h7N8m8|rR)OLzT& zMIN_3KmAsI{ZjmQ^Ldpa8v!h@i^{#$3*{nRIYJR3tMSViezP!MkfY)?bC%c1T6^P0 z6Bo*`{Jj+?hoGICdV8@M0~)~4TH|~8K*f4-p$X^Y3~C?#fF(ktTHL%LT-JpUtpcZc zMmu1U0zB)akuWV+A$fN~|HS$o6tswy$Pj!l+&$}STsS7)Zo=`6E^5B@5*D~(Y0~Gj zQAI*y3M?Zfr5;D@);s!sZXMoU1&_fK0P7u(E*_pH7u5*5i)3!PWr-Hp#&JX%)B`4VA{ZcCd;*1s!iSm+Q zhSUpoPy<(L*DAJ3Cp{yCNL9vw9=vs#aZsfH5ST*XSH|r>9&i};oM;i2L)N=O?;Og( ze{i%JkNhs*y7L4mPE{rrUM|KDPCT)@>)F(O-fbH>>gQ^2T*{IakHq-qYWaOBlfIVd z%WEw*lAeH`&9Dva)Rar~118KE4^23O!cwZ{G>AokG0OikjezTcG-)S`KGS+3o=g6U z+*ZcmPz;?|b~mRiHG|Oz9LzJLN1A;}@;b-;qwmUQUB4A`b(WSLWFMV=Nl~uXmTuTkWjQcYYg6 z+=zgsPb+>L-&bM`Ey_2U{rP}tmmN@{=g3tog^v{kN*~+gfU$Mh93GD9l2hrCTU0{S z`;BsPI?lTvJP9(PfvmpMvw|40$aA$ij(Vpx#_SP0?~AZCsC+2R$zpP)^P`<-g%i)$ zIP8c7uIgG?`ML8!AZq&IF4zI(M+l5Rhpbu={sDUoWxF#>pvn~E!ulfPZFv=Z_C}eC zbdlFUYz(aP2>iuKsRyia8PVCl`;&qCH)-r&dTJW~=lh?A6XE^{aZL{Srf^Xyi+w@( z$giK+OHSC;${eA4g-;vl$fveIghbT^M7u0bzJMf*xR)Bq@Wn5*